packages feed

pandoc 3.1.13 → 3.10

raw patch · 1026 files changed

Files

AUTHORS.md view
@@ -2,9 +2,12 @@  - Aaron Wolen - Adelar da Silva Queiróz+- Agriya Khetarpal - Agustín Martín Barbero+- Akash Patel - Akos Marton - Albert Krewinkel+- Albert Lei - Alex Ivkin - Alex Toldaiev - Alex Vong@@ -22,6 +25,7 @@ - Amy de Buitléir - Anabra - Anders Waldenborg+- Andreas Deininger - Andreas Lööw - Andreas Scherer - Andres Freund@@ -30,6 +34,8 @@ - Aner Lucero - Anti-Distinctlyminty - Antoine Latter+- Anton Antich+- Anton Melnikov - Antonio Terceiro - Arata Mizuki - Arata Mizuki@@ -37,6 +43,7 @@ - Arlo O'Keeffe - Artem Pelenitsyn - Artyom Kazak+- Asliddinbek Azizovich - B. Scott Michel - Bastien Dumont - Ben Firshman@@ -67,20 +74,24 @@ - Cezary Drożak - Chandrahas77 - Charanjit Singh+- Charles Tapley Hoyt - Charlotte Koch - Chris Black+- Chris Callison-Burch - Christian Conkle - Christian Christiansen - Christian Despres - Christoffer Ackelman - Christoffer Sawicki - Christophe Dervieux+- Christopher Kenny - Clare Macrae - Clint Adams - Conal Elliott - Cormac Relf - Craig S. Bosma - Damien Clochard+- Dan Jacobson - Daniel Bergey - Daniel Kessler - Daniel Maslowski@@ -104,15 +115,18 @@ - Eigil Rischel - Elliot Bobrow - Emanuel Evans+- Emmanuel Ferdman - Emerson Harkin - Emily Bourke - Emily Eisenberg - Eric Kow - Eric Schrijver - Eric Seidel+- Erik Post - Erik Rask - Ethan Riley - Étienne Bersac+- Evan Silberman - Even Brenden - Ezwal - Fabián Heredia Montiel@@ -122,6 +136,7 @@ - Florian Eitel - Florian Klink - Florian Kohrt+- FoxChillz - Francesco Mazzoli - Francesco Occhipinti - François Gannaz@@ -136,7 +151,9 @@ - Gavin Beatty - George Stagg - Georgi Lyubenov+- GHyman83 - Gokul Rajiv+- Gordon Woodhull - Gottfried Haider - Greg Maslov - Greg Rundlett@@ -145,6 +162,7 @@ - Gwern Branwen - Hamish Mackenzie - Hans-Peter Deifel+- Hendrik Erz - Heiko Schlittermann - Henrik Tramberend - Henry de Valence@@ -163,6 +181,7 @@ - Ivar de Bruin - Ivo Clarysse - Jaap de Jong+- Jacob Larkin - James J Balamuta - J. B. Rainsberger - J. Lewis Muir@@ -172,6 +191,8 @@ - Jake Zimmerman - Jakob Voß - James Aspnes+- James P. Ascher+- James Barlow - James Scott-Brown - Jamie F. Olson - Jan Larres@@ -185,14 +206,17 @@ - Jeff Runningen - Jens Getreu - Jens Petersen+- Jens Oehlschlägel - Jesse Hathaway - Jeremie Knuesel - Jérémy Bobbio - Jeroen de Haas - Jerry Sky - Jesse Rosenthal+- Jez Cope - Joe Hermaszewski - Joe Hillenbrand+- Johan Larsson - John KetzerX - John Luke Bentley - John MacFarlane@@ -200,6 +224,7 @@ - John Purnell - Jonas Scholl - Jonas Smedegaard+- Jonathan - Jonathan Daugherty - Jonathan Dönszelmann - Jose Luis Duran@@ -214,6 +239,7 @@ - Justin Bogner - Justin Wood - Karl Pettersson+- Keenan Brock - Keiichiro Shikano - Kelsey Hightower - Kevin Broch@@ -225,6 +251,7 @@ - Laurent P. René de Cotret - Lawrence Chonavel - Leif Metcalf+- Leo Heitmann Ruiz - Leonard Rosenthol - Lila - Link Swanson@@ -233,14 +260,18 @@ - Lucas Escot - Lucas Viana - Lucas V. R+- Luis Rivera - Luke Plant+- Manolis Stamatogiannakis - Marc Schreiber - Marcin Serwin - Mario Lang+- Mark Gardner - Mark Szepieniec - Mark Wright - Martin Joerg - Martin Linn+- Martin Michlmayr - Martín Pozo - Masataka Ogawa - Masayoshi Takahashi@@ -258,6 +289,7 @@ - Max Bolingbroke - Max Heller - Max Rydahl Andersen+- Meher Chaitanya - Merijn Verstraaten - Michael Beaumont - Michael Chladek@@ -268,10 +300,12 @@ - Michael Snoyman - Michael Stahl - Michael Thompson+- Mickaël Canouil - Mike Tzou - Mikołaj Machowski - Milan Bracke - MinRK+- Mohamed Akram - Morgan Willcock - Morton Fox - Nathan Gass@@ -281,6 +315,7 @@ - Nick Berendsen - Nick Fleisher - Nicolas Kaiser+- Niklas Eicker - Nikolai Korobeinikov - Nikolay Yakimov - Nils Carlson@@ -294,18 +329,21 @@ - Oliver Fabel - Oliver Matthews - Olivier Benz+- Olivier Dossmann - Ophir Lifshitz - Or Neeman - OvidiusCicero - Owen McGrath - Pablo Rodríguez - Pascal Wagler+- Pau RE - Paul Rivier - Paul Tilley - Paulo Tanimoto - Pavol Otto - Per Christian Gaustad - Pete Ryland+- Peter Briggs - Peter Fabinksi - Peter Wang - Philip Pesca@@ -319,22 +357,31 @@ - R. N. West - Ralf Stephan - Raniere Silva+- Raymond Berger - Raymond Ehlers - Recai Oktaş+- Repetitive+- Reuben Thomas - Rowan Rodrik van der Molen - Roland Hieber - Roman Beránek - Ruqi - RyanGlScott+- Ryan Gibb - S.P.H+- Sai Asish Y - Salim B - Sam S. Almahri - Sam May - Samuel Tardieu - Saumel Lemmenmeier+- Santiago Zarate - Sascha Wilde - Scott Morrison+- Sean Soon - Sebastian Talmon+- Sebbones+- Sen-wen Deng - Sergei Trofimovich - Sergey Astanin - Seth Speaks@@ -343,6 +390,7 @@ - Shim Myeongseob - Shin Sang-jae - Sidarth Kapur+- Sidney Mau - Sidharth Kapur - Simon Hengel - Simon Schuster@@ -351,9 +399,13 @@ - Stephan Daus - Stephan Meijer - Stephen Altamirano+- Stephen Huan+- Stephen Reindl+- Stéphane Guillou - Sukil Etxenike - Sukka - Sumit Sahrawat+- Suraj Patil - Sven Wick - TEC - Tarik Graba@@ -361,7 +413,9 @@ - Terence Eden - Thenaesh Elango - Thomas Hodgson+- Thomas Soeiro - Thomas Weißschuh+- Tiago-Manzato - Tim Lin - Tim Stewart - Tim Wisotzki@@ -375,6 +429,7 @@ - Toni Dietze - Tristan Stenner - Tristan de Cacqueray+- Tristano Ajmone - Tuong Nguyen Manh - Uli Köhler - Urs Liska@@ -398,42 +453,54 @@ - Wout Gevaert - Xavier Olive - Yan Pashkovsky+- Yann Trividic+- Yehuda Katz - YI - Yoan Blanc+- You Jiangbin - Yuchen Pei - Zihang Chen - 3w36zj6 - arcnmx - a-vrma - andrebauer+- benniekiss - black-desk - blmage - bucklereed - bumper314 - chinapedia - cholonam+- closeobserve - csforste - d-dorazio - damon-sava-stanley - dbecher-ito - ebiim - ech0+- etclub - favonia+- guqicun+- har7an - harabat - hseg - infinity0x - jeongminkim-islab+- josch - kaizshang91 - lawcho - lifeunleaded - lux-lth - luz paz - lwolfsonkin+- massifrg+- mbracke - mbrackeantidot - mh4ckt3mh4ckt1c4s - mjfs - mt_caret - nbehrnd+- nibras shami - niszet - nkalvi - nuew@@ -446,6 +513,7 @@ - priiduonu - qerub - quasicomputational+- reptee - ricnorr - robabla - roblabla@@ -459,6 +527,7 @@ - tecosaur - tgkokk - the-solipsist+- thomjur - thsutton - thron7 - timo-a@@ -468,3 +537,4 @@ - wiefling - willj-dev - wuffi+- λx.x
CONTRIBUTING.md view
@@ -118,7 +118,7 @@ So before submitting a bug report, consider whether it might be "out of scope." If it concerns a feature of documents that isn't representable in pandoc's Markdown, then it very likely is.-(If in doubt, you can always ask on the [discussion-forum].)+(If in doubt, you can always ask on the [discussion forum].)  Fixing bugs from the issue tracker ----------------------------------@@ -215,9 +215,9 @@     external C libraries should especially be avoided.  10. We aim for compatibility with at least the last three-    released ghc versions, and sometimes more. Currently pandoc-    can be compiled on ghc 8.6 an higher. All pull requests and-    commits are tested automatically on GitHub Actions.+    released ghc versions, and sometimes more.  Currently we+    support ghc versions 9.6 and higher. All pull requests+    and commits are tested automatically on GitHub Actions.  Tests -----@@ -422,10 +422,33 @@   - `Text.Pandoc.UUID` contains functions for generating UUIDs.   - `Text.Pandoc.XML` contains functions for formatting XML. +Adding a new command-line option+--------------------------------++To add a new command-line option, you'll need to make changes in several+places:++- `MANUAL.txt` -- documentation for new option, both in the list+  of options and in the section on defaults files.+- `Text.Pandoc.App.Opt` -- new constructor for Opt and default+  value+- `Text.Pandoc.App.CommandLineOptions` -- the option parser+- `Text.Pandoc.App` or `Text.Pandoc.App.OutputSettings` --+  handle the new option+- possibly in pandoc-server: `Text.Pandoc.Server` -- handle the+  new option++If your change requires a new field for ReaderOptions or+WriterOptions, you'll also need to++- `Text.Pandoc.Options` -- type change and default value+- in pandoc-lua-engine: Text.Pandoc.Lua.Marshal.WriterOptions+  and/or Text.Pandoc.Lua.Marshal.ReaderOptions+ Lua filters ----------- -If you've written a useful pandoc [lua filter](lua-filters.html),+If you've written a useful pandoc [lua filter](./doc/lua-filters.md), you may want to consider submitting a pull request to the [lua-filters repository](https://github.com/pandoc/lua-filters). 
COPYING.md view
@@ -3,8 +3,8 @@ Version 2, June 1991      Copyright (C) 1989, 1991 Free Software Foundation, Inc.  -    51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA-+    <https://fsf.org/>+         Everyone is permitted to copy and distribute verbatim copies     of this license document, but changing it is not allowed. @@ -317,10 +317,9 @@     but WITHOUT ANY WARRANTY; without even the implied warranty of     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     GNU General Public License for more details.--    You should have received a copy of the GNU General Public License-    along with this program; if not, write to the Free Software-    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.+    +    You should have received a copy of the GNU General Public License along+    with this program; if not, see <https://www.gnu.org/licenses/>.  Also add information on how to contact you by electronic and paper mail.
@@ -1,5 +1,5 @@ Pandoc-Copyright (C) 2006-2023 John MacFarlane <jgm at berkeley dot edu>+Copyright (C) 2006-2024 John MacFarlane <jgm at berkeley dot edu>  With the exceptions noted below, this code is released under the [GPL], version 2 or later:@@ -14,9 +14,8 @@    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details. -   You should have received a copy of the GNU General Public License-   along with this program; if not, write to the Free Software-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA+   You should have received a copy of the GNU General Public License along+   with this program; if not, see <https://www.gnu.org/licenses/>.  The GNU General Public License is available in the file COPYING.md in the source distribution.  On Debian systems, the complete text of the@@ -24,9 +23,9 @@  [GPL]: https://www.gnu.org/copyleft/gpl.html -Pandoc's complete source code is available from the [Pandoc home page].--[Pandoc home page]: https://pandoc.org+The complete source code for pandoc version X.Y.Z is available at+<https://hackage.haskell.org/package/pandoc-X.Y.Z/pandoc-X.Y.Z.tar.gz>+and at <https://github.com/jgm/pandoc/tree/X.Y.Z>.  Pandoc includes some code with different copyrights, or subject to different licenses.  The copyright and license statements for these sources are included@@ -37,7 +36,7 @@ Text.Pandoc.Builder, Text.Pandoc.Generics, Text.Pandoc.JSON, Text.Pandoc.Walk) are licensed under the BSD 3-clause license: -Copyright (c) 2006-2023, John MacFarlane+Copyright (c) 2006-2024, John MacFarlane  All rights reserved. @@ -73,7 +72,7 @@ GPL (v2 or higher, same as pandoc) or (at your option) the BSD 3-clause license. -Copyright (c) 2014--2023, John MacFarlane+Copyright (c) 2014--2024, John MacFarlane  ---------------------------------------------------------------------- src/Text/Pandoc/Writers/Muse.hs@@ -83,19 +82,19 @@  ---------------------------------------------------------------------- src/Text/Pandoc/Writers/Texinfo.hs-Copyright (C) 2008-2023 John MacFarlane and Peter Wang+Copyright (C) 2008-2024 John MacFarlane and Peter Wang  Released under the GNU General Public License version 2 or later.  ---------------------------------------------------------------------- src/Text/Pandoc/Writers/OpenDocument.hs-Copyright (C) 2008-2023 Andrea Rossato and John MacFarlane+Copyright (C) 2008-2024 Andrea Rossato and John MacFarlane  Released under the GNU General Public License version 2 or later.  ---------------------------------------------------------------------- src/Text/Pandoc/Writers/Org.hs-Copyright (C) 2010-2023 Puneeth Chaganti, John MacFarlane, and+Copyright (C) 2010-2024 Puneeth Chaganti, John MacFarlane, and                         Albert Krewinkel  Released under the GNU General Public License version 2 or later.@@ -115,7 +114,7 @@  ---------------------------------------------------------------------- src/Text/Pandoc/Readers/Textile.hs-Copyright (C) 2010-2023 Paul Rivier and John MacFarlane+Copyright (C) 2010-2024 Paul Rivier and John MacFarlane  Released under the GNU General Public License version 2 or later. @@ -133,7 +132,7 @@  ---------------------------------------------------------------------- src/Text/Pandoc/Readers/EPUB.hs-Copyright (C) 2014-2023 Matthew Pickering and John MacFarlane+Copyright (C) 2014-2024 Matthew Pickering and John MacFarlane  Released under the GNU General Public License version 2 or later. @@ -141,7 +140,7 @@ src/Text/Pandoc/Readers/Org.hs src/Text/Pandoc/Readers/Org/* test/Tests/Readers/Org/*-Copyright (C) 2014-2023 Albert Krewinkel+Copyright (C) 2014-2024 Albert Krewinkel  Released under the GNU General Public License version 2 or later. @@ -149,7 +148,7 @@ pandoc-lua-engine/src/Text/Pandoc/Lua.hs pandoc-lua-engine/src/Text/Pandoc/Lua/* pandoc-lua-engine/test/lua/*-Copyright (C) 2017--2023 Albert Krewinkel and John MacFarlane+Copyright (C) 2017--2024 Albert Krewinkel and John MacFarlane  Released under the GNU General Public License version 2 or later. @@ -157,7 +156,7 @@ src/Text/Pandoc/Readers/Jira.hs src/Text/Pandoc/Writers/Jira.hs test/Tests/Readers/Jira.hs-Copyright (C) 2019--2023 Albert Krewinkel+Copyright (C) 2019--2024 Albert Krewinkel  Released under the GNU General Public License version 2 or later. @@ -177,7 +176,7 @@ ------------------------------------------------------------------------ Pandoc embeds a Lua interpreter (via hslua). -Copyright © 1994–2022 Lua.org, PUC-Rio.+Copyright © 1994--2023 Lua.org, PUC-Rio.  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the@@ -197,3 +196,30 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.++------------------------------------------------------------------------+Some of the code in wasm/pandoc.js and the patches in wasm/patches is+from https://github.com/haskell-wasm/pandoc-wasm. It is released under+this license:++MIT License++Copyright (c) Tweag I/O Limited.++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in all+copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+SOFTWARE.
INSTALL.md view
@@ -7,9 +7,15 @@   Download the latest installer </a> -For alternative ways to install pandoc, see below-under the heading for your operating system.+For alternative ways to install pandoc, see below under the heading for+your operating system. +**Note**: the statically linked Pandoc binaries provided by us (or those+available on Conda Forge) have a limitation. They are unable to utilise Lua+filters that rely on Lua modules written in C. If you require the+functionality offered by these filters, please consider an alternative+method of installation.+ ## Windows  There is a package installer at pandoc's [download page].@@ -33,12 +39,14 @@ [MiKTeX] (to typeset PDFs with [LaTeX]):      choco install rsvg-convert python miktex-    + Or, you can install pandoc using [winget](https://github.com/microsoft/winget-pkgs):      winget install --source winget --exact --id JohnMacFarlane.Pandoc +Or, you can install Pandoc using [Conda forge].+ Using multiple installation methods can result in two separate installations of pandoc; it is recommended to properly uninstall pandoc before switching to an alternative installation method.@@ -70,6 +78,12 @@ Homebrew installs from source, which takes additional time and disk space for the `ghc` compiler and dependent Haskell libraries. +You can also install pandoc using [MacPorts]:++    port install pandoc++Or, you can install Pandoc using [Conda forge].+ We also provide a zip file containing the binaries and man pages, for those who prefer not to use the installer.  Simply unzip the file and move the binaries and man pages to@@ -90,16 +104,14 @@  Check whether the pandoc version in your package manager is not outdated. Pandoc is in the [Debian], [Ubuntu], [Slackware],-[Arch], [Fedora], [NiXOS], [openSUSE], [gentoo] and [Void] repositories.+[Arch], [Fedora], [NixOS], [openSUSE], [gentoo] and [Void] repositories.  To get the latest release, we provide a binary package for amd64 architecture on the **[download page]**.  The executable is statically linked and has no dynamic dependencies or dependencies on external-data files.  Note:  because of the static-linking, the pandoc binary from this package cannot use lua-filters that require external lua modules written in C.+data files.  Both a tarball and a deb installer are provided.  To install the deb: @@ -122,11 +134,10 @@      ar p $DEB data.tar.gz | tar xvz --strip-components 2 -C $DEST +Or, you can install Pandoc using [Conda forge].+ You can also install from source, using the instructions below under [Compiling from source].-Note that most distros have the Haskell platform in their-package repositories.  For example, on Debian/Ubuntu,-you can install it with `apt-get install haskell-platform`.  By default, Pandoc creates PDFs using LaTeX.  We recommend installing [TeX Live](https://www.tug.org/texlive/) via your package@@ -148,8 +159,23 @@  ## BSD -Pandoc is in the [NetBSD] and [FreeBSD ports] repositories.+Pandoc is in the [NetBSD], [FreeBSD], and [OpenBSD ports] repositories. +## Conda Forge++You can install Pandoc using a [Conda+Forge](https://anaconda.org/conda-forge/pandoc) tool, like+[Conda](https://conda.pydata.org/docs/intro.html),+[[Micro]Mamba](https://mamba.readthedocs.io/en/latest/index.html) or+[Pixi](https://prefix.dev). Conda forge also includes multiple LaTeX and+other relevant packages for Pandoc (including `pandoc-citeproc`,+`pandoc-plot`, `rsvg-convert` via `librsvg` etc.). **Note:** conda forge+installs a statically-linked executable.++    conda install -c conda-forge pandoc+    pixi global install pandoc+    micromamba install pandoc+ ## Docker  The official Docker images for pandoc can be found at@@ -236,9 +262,12 @@      This procedure will install the released version of pandoc,     which will be downloaded automatically from HackageDB.-    The `pandoc` executable will be placed in `$HOME/.cabal/bin`+    The `pandoc` executable will be symlinked in`$HOME/.cabal/bin`     on linux/unix/macOS and in `%APPDATA%\cabal\bin` on Windows.-    Make sure this directory is in your path.+    Make sure this directory is in your path. To specify a+    custom install directory, use `--installdir`. To have+    the executable copied instead of symlinked, use+    `--install-method=copy`.      If you want to install a modified or development version of     pandoc instead, switch to the source directory before running@@ -264,12 +293,10 @@ assume that the pandoc source directory is your working directory. You will need cabal version 2.0 or higher. -1.  Install dependencies:  in addition to the [Haskell platform],-    you will need a number of additional libraries.  You can install-    them all with+1.  Install dependencies:          cabal update-        cabal install --only-dependencies+        cabal build --only-dependencies  2.  Configure: @@ -306,19 +333,20 @@          cabal haddock --html-location=URL --hyperlink-source +5.  Install +        cabal install pandoc-cli+ ### Creating a relocatable binary  It is possible to compile pandoc such that the data files pandoc uses are embedded in the binary.  The resulting binary can be run from any directory and is completely self-contained. With cabal, add `-fembed_data_files` to the `cabal configure`-or `cabal install` commands.+or `cabal build` commands.  With stack, use `--flag pandoc:embed_data_files`. -- ### Running tests  Pandoc comes with an automated test suite.@@ -370,12 +398,12 @@ [Cabal User's Guide]: https://cabal.readthedocs.io/ [Debian]: https://packages.debian.org/search?keywords=pandoc [Fedora]: https://packages.fedoraproject.org/pkgs/pandoc/pandoc/-[FreeBSD ports]: https://www.freshports.org/textproc/hs-pandoc/+[FreeBSD]: https://www.freshports.org/textproc/hs-pandoc/ [GHC]:  https://www.haskell.org/ghc/ [GitLab CI/CD]: https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/-[Haskell platform]: https://hackage.haskell.org/platform/-[MacPorts]: https://trac.macports.org/browser/trunk/dports/textproc/pandoc/Portfile+[MacPorts]: https://ports.macports.org/port/pandoc/ [MacTeX]: https://tug.org/mactex/+[OpenBSD ports]: https://cvsweb.openbsd.org/ports/textproc/pandoc/ [BasicTeX]: https://www.tug.org/mactex/morepackages.html [LaTeX]: https://www.latex-project.org [MiKTeX]: https://miktex.org/
MANUAL.txt view
@@ -1,7476 +1,8050 @@ --- title: Pandoc User's Guide author: John MacFarlane-date: April 7, 2024------# Synopsis--`pandoc` [*options*] [*input-file*]...--# Description--Pandoc is a [Haskell] library for converting from one markup format to-another, and a command-line tool that uses this library.--Pandoc can convert between numerous markup and word processing formats,-including, but not limited to, various flavors of [Markdown], [HTML],-[LaTeX] and [Word docx]. For the full lists of input and output formats,-see the `--from` and `--to` [options below][General options].-Pandoc can also produce [PDF] output: see [creating a PDF], below.--Pandoc's enhanced version of Markdown includes syntax for [tables],-[definition lists], [metadata blocks], [footnotes], [citations], [math],-and much more.  See below under [Pandoc's Markdown].--Pandoc has a modular design: it consists of a set of readers, which parse-text in a given format and produce a native representation of the document-(an _abstract syntax tree_ or AST), and a set of writers, which convert-this native representation into a target format. Thus, adding an input-or output format requires only adding a reader or writer. Users can also-run custom [pandoc filters] to modify the intermediate AST.--Because pandoc's intermediate representation of a document is less-expressive than many of the formats it converts between, one should-not expect perfect conversions between every format and every other.-Pandoc attempts to preserve the structural elements of a document, but-not formatting details such as margin size.  And some document elements,-such as complex tables, may not fit into pandoc's simple document-model.  While conversions from pandoc's Markdown to all formats aspire-to be perfect, conversions from formats more expressive than pandoc's-Markdown can be expected to be lossy.--## Using pandoc--If no *input-files* are specified, input is read from *stdin*.-Output goes to *stdout* by default. For output to a file,-use the `-o` option:--    pandoc -o output.html input.txt--By default, pandoc produces a document fragment. To produce a standalone-document (e.g. a valid HTML file including `<head>` and `<body>`),-use the `-s` or `--standalone` flag:--    pandoc -s -o output.html input.txt--For more information on how standalone documents are produced, see-[Templates] below.--If multiple input files are given, pandoc will concatenate them all (with-blank lines between them) before parsing. (Use `--file-scope` to parse files-individually.)--## Specifying formats--The format of the input and output can be specified explicitly using-command-line options.  The input format can be specified using the-`-f/--from` option, the output format using the `-t/--to` option.-Thus, to convert `hello.txt` from Markdown to LaTeX, you could type:--    pandoc -f markdown -t latex hello.txt--To convert `hello.html` from HTML to Markdown:--    pandoc -f html -t markdown hello.html--Supported input and output formats are listed below under [Options]-(see `-f` for input formats and `-t` for output formats).  You-can also use `pandoc --list-input-formats` and-`pandoc --list-output-formats` to print lists of supported-formats.--If the input or output format is not specified explicitly, pandoc-will attempt to guess it from the extensions of the filenames.-Thus, for example,--    pandoc -o hello.tex hello.txt--will convert `hello.txt` from Markdown to LaTeX.  If no output file-is specified (so that output goes to *stdout*), or if the output file's-extension is unknown, the output format will default to HTML.-If no input file is specified (so that input comes from *stdin*), or-if the input files' extensions are unknown, the input format will-be assumed to be Markdown.--## Character encoding--Pandoc uses the UTF-8 character encoding for both input and output.-If your local character encoding is not UTF-8, you-should pipe input and output through [`iconv`]:--    iconv -t utf-8 input.txt | pandoc | iconv -f utf-8--Note that in some output formats (such as HTML, LaTeX, ConTeXt,-RTF, OPML, DocBook, and Texinfo), information about-the character encoding is included in the document header, which-will only be included if you use the `-s/--standalone` option.--[`iconv`]: https://www.gnu.org/software/libiconv/--## Creating a PDF--To produce a PDF, specify an output file with a `.pdf` extension:--    pandoc test.txt -o test.pdf--By default, pandoc will use LaTeX to create the PDF, which requires-that a LaTeX engine be installed (see `--pdf-engine` below).-Alternatively, pandoc can use ConTeXt, roff ms, or HTML as an-intermediate format.  To do this, specify an output file with a-`.pdf` extension, as before, but add the `--pdf-engine` option-or `-t context`, `-t html`, or `-t ms` to the command line.-The tool used to generate the PDF from the intermediate format-may be specified using `--pdf-engine`.--You can control the PDF style using variables, depending on-the intermediate format used: see [variables for LaTeX],-[variables for ConTeXt], [variables for `wkhtmltopdf`],-[variables for ms].  When HTML is used as an intermediate-format, the output can be styled using `--css`.--To debug the PDF creation, it can be useful to look at the intermediate-representation: instead of `-o test.pdf`, use for example `-s -o test.tex`-to output the generated LaTeX. You can then test it with `pdflatex test.tex`.--When using LaTeX, the following packages need to be available-(they are included with all recent versions of [TeX Live]):-[`amsfonts`], [`amsmath`], [`lm`], [`unicode-math`],-[`iftex`], [`listings`] (if the-`--listings` option is used), [`fancyvrb`], [`longtable`],-[`booktabs`], [`graphicx`] (if the document-contains images), [`bookmark`], [`xcolor`],-[`soul`], [`geometry`] (with the `geometry` variable set),-[`setspace`] (with `linestretch`), and-[`babel`] (with `lang`).  If `CJKmainfont` is set, [`xeCJK`]-is needed.  The use of `xelatex` or `lualatex` as-the PDF engine requires [`fontspec`].  `lualatex` uses-[`selnolig`]. `xelatex` uses [`bidi`] (with the `dir` variable set).-If the `mathspec` variable is set, `xelatex` will use [`mathspec`]-instead of [`unicode-math`].  The [`upquote`] and [`microtype`]-packages are used if available, and [`csquotes`] will be used-for [typography] if the `csquotes` variable or metadata field is-set to a true value.  The [`natbib`], [`biblatex`], [`bibtex`],-and [`biber`] packages can optionally be used for [citation-rendering].  The following packages will be used to improve-output quality if present, but pandoc does not require them to-be present: [`upquote`] (for straight quotes in verbatim-environments), [`microtype`] (for better spacing adjustments),-[`parskip`] (for better inter-paragraph spaces), [`xurl`] (for-better line breaks in URLs), and [`footnotehyper`] or-[`footnote`] (to allow footnotes in tables).--[TeX Live]: https://www.tug.org/texlive/-[`amsfonts`]: https://ctan.org/pkg/amsfonts-[`amsmath`]: https://ctan.org/pkg/amsmath-[`babel`]: https://ctan.org/pkg/babel-[`biber`]: https://ctan.org/pkg/biber-[`biblatex`]: https://ctan.org/pkg/biblatex-[`bibtex`]: https://ctan.org/pkg/bibtex-[`bidi`]: https://ctan.org/pkg/bidi-[`bookmark`]: https://ctan.org/pkg/bookmark-[`booktabs`]: https://ctan.org/pkg/booktabs-[`csquotes`]: https://ctan.org/pkg/csquotes-[`fancyvrb`]: https://ctan.org/pkg/fancyvrb-[`fontspec`]: https://ctan.org/pkg/fontspec-[`footnote`]: https://ctan.org/pkg/footnote-[`footnotehyper`]: https://ctan.org/pkg/footnotehyper-[`geometry`]: https://ctan.org/pkg/geometry-[`graphicx`]: https://ctan.org/pkg/graphicx-[`grffile`]: https://ctan.org/pkg/grffile-[`hyperref`]: https://ctan.org/pkg/hyperref-[`iftex`]: https://ctan.org/pkg/iftex-[`listings`]: https://ctan.org/pkg/listings-[`lm`]: https://ctan.org/pkg/lm-[`longtable`]: https://ctan.org/pkg/longtable-[`mathspec`]: https://ctan.org/pkg/mathspec-[`microtype`]: https://ctan.org/pkg/microtype-[`natbib`]: https://ctan.org/pkg/natbib-[`parskip`]: https://ctan.org/pkg/parskip-[`polyglossia`]: https://ctan.org/pkg/polyglossia-[`prince`]: https://www.princexml.com/-[`setspace`]: https://ctan.org/pkg/setspace-[`soul`]: https://ctan.org/pkg/soul-[`unicode-math`]: https://ctan.org/pkg/unicode-math-[`upquote`]: https://ctan.org/pkg/upquote-[`weasyprint`]: https://weasyprint.org-[`wkhtmltopdf`]: https://wkhtmltopdf.org-[`xcolor`]: https://ctan.org/pkg/xcolor-[`xeCJK`]: https://ctan.org/pkg/xecjk-[`xurl`]: https://ctan.org/pkg/xurl-[`selnolig`]: https://ctan.org/pkg/selnolig----## Reading from the Web--Instead of an input file, an absolute URI may be given. In this case-pandoc will fetch the content using HTTP:--    pandoc -f html -t markdown https://www.fsf.org--It is possible to supply a custom User-Agent string or other-header when requesting a document from a URL:--    pandoc -f html -t markdown --request-header User-Agent:"Mozilla/5.0" \-      https://www.fsf.org--# Options--## General options {.options}--`-f` *FORMAT*, `-r` *FORMAT*, `--from=`*FORMAT*, `--read=`*FORMAT*--:   Specify input format.  *FORMAT* can be:--    ::: {#input-formats}-    - `bibtex` ([BibTeX] bibliography)-    - `biblatex` ([BibLaTeX] bibliography)-    - `bits` ([BITS] XML, alias for `jats`)-    - `commonmark` ([CommonMark] Markdown)-    - `commonmark_x` ([CommonMark] Markdown with extensions)-    - `creole` ([Creole 1.0])-    - `csljson` ([CSL JSON] bibliography)-    - `csv` ([CSV] table)-    - `tsv` ([TSV] table)-    - `djot` ([Djot markup])-    - `docbook` ([DocBook])-    - `docx` ([Word docx])-    - `dokuwiki` ([DokuWiki markup])-    - `endnotexml` ([EndNote XML bibliography])-    - `epub` ([EPUB])-    - `fb2` ([FictionBook2] e-book)-    - `gfm` ([GitHub-Flavored Markdown]),-      or the deprecated and less accurate `markdown_github`;-      use [`markdown_github`](#markdown-variants) only-      if you need extensions not supported in [`gfm`](#markdown-variants).-    - `haddock` ([Haddock markup])-    - `html` ([HTML])-    - `ipynb` ([Jupyter notebook])-    - `jats` ([JATS] XML)-    - `jira` ([Jira]/Confluence wiki markup)-    - `json` (JSON version of native AST)-    - `latex` ([LaTeX])-    - `markdown` ([Pandoc's Markdown])-    - `markdown_mmd` ([MultiMarkdown])-    - `markdown_phpextra` ([PHP Markdown Extra])-    - `markdown_strict` (original unextended [Markdown])-    - `mediawiki` ([MediaWiki markup])-    - `man` ([roff man])-    - `muse` ([Muse])-    - `native` (native Haskell)-    - `odt` ([ODT])-    - `opml` ([OPML])-    - `org` ([Emacs Org mode])-    - `ris` ([RIS] bibliography)-    - `rtf` ([Rich Text Format])-    - `rst` ([reStructuredText])-    - `t2t` ([txt2tags])-    - `textile` ([Textile])-    - `tikiwiki` ([TikiWiki markup])-    - `twiki` ([TWiki markup])-    - `typst` ([typst])-    - `vimwiki` ([Vimwiki])-    - the path of a custom Lua reader, see [Custom readers and writers] below-    :::--    Extensions can be individually enabled or disabled by-    appending `+EXTENSION` or `-EXTENSION` to the format name.-    See [Extensions] below, for a list of extensions and-    their names.  See `--list-input-formats` and `--list-extensions`,-    below.--`-t` *FORMAT*, `-w` *FORMAT*, `--to=`*FORMAT*, `--write=`*FORMAT*--:   Specify output format.  *FORMAT* can be:--    ::: {#output-formats}-    - `asciidoc` (modern [AsciiDoc] as interpreted by [AsciiDoctor])-    - `asciidoc_legacy` ([AsciiDoc] as interpreted by [`asciidoc-py`]).-    - `asciidoctor` (deprecated synonym for `asciidoc`)-    - `beamer` ([LaTeX beamer][`beamer`] slide show)-    - `bibtex` ([BibTeX] bibliography)-    - `biblatex` ([BibLaTeX] bibliography)-    - `chunkedhtml` (zip archive of multiple linked HTML files)-    - `commonmark` ([CommonMark] Markdown)-    - `commonmark_x` ([CommonMark] Markdown with extensions)-    - `context` ([ConTeXt])-    - `csljson` ([CSL JSON] bibliography)-    - `djot` ([Djot markup])-    - `docbook` or `docbook4` ([DocBook] 4)-    - `docbook5` (DocBook 5)-    - `docx` ([Word docx])-    - `dokuwiki` ([DokuWiki markup])-    - `epub` or `epub3` ([EPUB] v3 book)-    - `epub2` (EPUB v2)-    - `fb2` ([FictionBook2] e-book)-    - `gfm` ([GitHub-Flavored Markdown]),-      or the deprecated and less accurate `markdown_github`;-      use [`markdown_github`](#markdown-variants) only-      if you need extensions not supported in [`gfm`](#markdown-variants).-    - `haddock` ([Haddock markup])-    - `html` or `html5` ([HTML], i.e. [HTML5]/XHTML [polyglot markup])-    - `html4` ([XHTML] 1.0 Transitional)-    - `icml` ([InDesign ICML])-    - `ipynb` ([Jupyter notebook])-    - `jats_archiving` ([JATS] XML, Archiving and Interchange Tag Set)-    - `jats_articleauthoring` ([JATS] XML, Article Authoring Tag Set)-    - `jats_publishing` ([JATS] XML, Journal Publishing Tag Set)-    - `jats` (alias for `jats_archiving`)-    - `jira` ([Jira]/Confluence wiki markup)-    - `json` (JSON version of native AST)-    - `latex` ([LaTeX])-    - `man` ([roff man])-    - `markdown` ([Pandoc's Markdown])-    - `markdown_mmd` ([MultiMarkdown])-    - `markdown_phpextra` ([PHP Markdown Extra])-    - `markdown_strict` (original unextended [Markdown])-    - `markua` ([Markua])-    - `mediawiki` ([MediaWiki markup])-    - `ms` ([roff ms])-    - `muse` ([Muse])-    - `native` (native Haskell)-    - `odt` ([OpenOffice text document][ODT])-    - `opml` ([OPML])-    - `opendocument` ([OpenDocument])-    - `org` ([Emacs Org mode])-    - `pdf` ([PDF])-    - `plain` (plain text)-    - `pptx` ([PowerPoint] slide show)-    - `rst` ([reStructuredText])-    - `rtf` ([Rich Text Format])-    - `texinfo` ([GNU Texinfo])-    - `textile` ([Textile])-    - `slideous` ([Slideous] HTML and JavaScript slide show)-    - `slidy` ([Slidy] HTML and JavaScript slide show)-    - `dzslides` ([DZSlides] HTML5 + JavaScript slide show)-    - `revealjs` ([reveal.js] HTML5 + JavaScript slide show)-    - `s5` ([S5] HTML and JavaScript slide show)-    - `tei` ([TEI Simple])-    - `typst` ([typst])-    - `xwiki` ([XWiki markup])-    - `zimwiki` ([ZimWiki markup])-    - the path of a custom Lua writer, see [Custom readers and writers] below-    :::--    Note that `odt`, `docx`, `epub`, and `pdf` output will not be directed-    to *stdout* unless forced with `-o -`.--    Extensions can be individually enabled or-    disabled by appending `+EXTENSION` or `-EXTENSION` to the format-    name.  See [Extensions] below, for a list of extensions and their-    names.  See `--list-output-formats` and `--list-extensions`, below.--`-o` *FILE*, `--output=`*FILE*--:   Write output to *FILE* instead of *stdout*.  If *FILE* is-    `-`, output will go to *stdout*, even if a non-textual format-    (`docx`, `odt`, `epub2`, `epub3`) is specified.  If the-    output format is `chunkedhtml` and *FILE* has no extension,-    then instead of producing a `.zip` file pandoc will create-    a directory *FILE* and unpack the zip archive there-    (unless *FILE* already exists, in which case an error-    will be raised).--`--data-dir=`*DIRECTORY*--:   Specify the user data directory to search for pandoc data files.-    If this option is not specified, the default user data directory-    will be used.  On \*nix and macOS systems this will be the `pandoc`-    subdirectory of the XDG data directory (by default,-    `$HOME/.local/share`, overridable by setting the `XDG_DATA_HOME`-    environment variable).  If that directory does not exist and-    `$HOME/.pandoc` exists, it will be used (for backwards compatibility).-    On Windows the default user data directory is `%APPDATA%\pandoc`.-    You can find the default user data directory on your system by-    looking at the output of `pandoc --version`.-    Data files placed in this directory (for example, `reference.odt`,-    `reference.docx`, `epub.css`, `templates`) will override-    pandoc's normal defaults.  (Note that the user data directory-    is not created by pandoc, so you will need to create it yourself-    if you want to make use of it.)--`-d` *FILE*, `--defaults=`*FILE*--:   Specify a set of default option settings.  *FILE* is a YAML-    file whose fields correspond to command-line option-    settings.  All options for document conversion, including input-    and output files, can be set using a defaults file.  The file will-    be searched for first in the working directory, and then in-    the `defaults` subdirectory of the user data directory-    (see `--data-dir`).  The `.yaml` extension may be omitted.-    See the section [Defaults files] for more information on the-    file format.  Settings from the defaults file may be-    overridden or extended by subsequent options on the command-    line.--`--bash-completion`--:   Generate a bash completion script.  To enable bash completion-    with pandoc, add this to your `.bashrc`:--        eval "$(pandoc --bash-completion)"--`--verbose`--:   Give verbose debugging output.--`--quiet`--:   Suppress warning messages.--`--fail-if-warnings[=true|false]`--:   Exit with error status if there are any warnings.--`--log=`*FILE*--:   Write log messages in machine-readable JSON format to-    *FILE*.  All messages above DEBUG level will be written,-    regardless of verbosity settings (`--verbose`, `--quiet`).--`--list-input-formats`--:   List supported input formats, one per line.--`--list-output-formats`--:   List supported output formats, one per line.--`--list-extensions`[`=`*FORMAT*]--:   List supported extensions for *FORMAT*, one per line, preceded-    by a `+` or `-` indicating whether it is enabled by default-    in *FORMAT*. If *FORMAT* is not specified, defaults for-    pandoc's Markdown are given.--`--list-highlight-languages`--:   List supported languages for syntax highlighting, one per-    line.--`--list-highlight-styles`--:   List supported styles for syntax highlighting, one per line.-    See `--highlight-style`.--`-v`, `--version`--:   Print version.--`-h`, `--help`--:   Show usage message.--[Markdown]: https://daringfireball.net/projects/markdown/-[CommonMark]: https://commonmark.org-[PHP Markdown Extra]: https://michelf.ca/projects/php-markdown/extra/-[GitHub-Flavored Markdown]: https://help.github.com/articles/github-flavored-markdown/-[MultiMarkdown]: https://fletcherpenney.net/multimarkdown/-[reStructuredText]: https://docutils.sourceforge.io/docs/ref/rst/introduction.html-[S5]: https://meyerweb.com/eric/tools/s5/-[Slidy]: https://www.w3.org/Talks/Tools/Slidy2/-[Slideous]: https://goessner.net/articles/slideous/-[HTML]: https://www.w3.org/html/-[HTML5]: https://html.spec.whatwg.org/-[polyglot markup]: https://www.w3.org/TR/html-polyglot/-[XHTML]: https://www.w3.org/TR/xhtml1/-[LaTeX]: https://www.latex-project.org/-[`beamer`]: https://ctan.org/pkg/beamer-[Beamer User's Guide]: http://mirrors.ctan.org/macros/latex/contrib/beamer/doc/beameruserguide.pdf-[ConTeXt]: https://www.contextgarden.net/-[Rich Text Format]: https://en.wikipedia.org/wiki/Rich_Text_Format-[DocBook]: https://docbook.org-[Djot markup]: https://djot.net-[JATS]: https://jats.nlm.nih.gov-[BITS]: https://jats.nlm.nih.gov/extensions/bits/-[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-[OpenDocument]: http://opendocument.xml.org-[ODT]: https://en.wikipedia.org/wiki/OpenDocument-[Textile]: https://textile-lang.com-[MediaWiki markup]: https://www.mediawiki.org/wiki/Help:Formatting-[DokuWiki markup]: https://www.dokuwiki.org/dokuwiki-[ZimWiki markup]: https://zim-wiki.org/manual/Help/Wiki_Syntax.html-[XWiki markup]: https://www.xwiki.org/xwiki/bin/view/Documentation/UserGuide/Features/XWikiSyntax/-[TWiki markup]: https://twiki.org/cgi-bin/view/TWiki/TextFormattingRules-[TikiWiki markup]: https://doc.tiki.org/Wiki-Syntax-Text#The_Markup_Language_Wiki-Syntax-[Haddock markup]: https://www.haskell.org/haddock/doc/html/ch03s08.html-[Creole 1.0]: http://www.wikicreole.org/wiki/Creole1.0-[CSV]: https://tools.ietf.org/html/rfc4180-[TSV]: https://www.iana.org/assignments/media-types/text/tab-separated-values-[roff man]: https://man.cx/groff_man(7)-[roff ms]: https://man.cx/groff_ms(7)-[Haskell]: https://www.haskell.org-[GNU Texinfo]: https://www.gnu.org/software/texinfo/-[RIS]: https://en.wikipedia.org/wiki/RIS_(file_format)-[Emacs Org mode]: https://orgmode.org-[AsciiDoc]: https://www.methods.co.nz/asciidoc/-[AsciiDoctor]: https://asciidoctor.org/-[`asciidoc-py`]: https://github.com/asciidoc-py/asciidoc-py-[DZSlides]: https://paulrouget.com/dzslides/-[Word docx]: https://en.wikipedia.org/wiki/Office_Open_XML-[PDF]: https://www.adobe.com/pdf/-[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-[TEI Simple]: https://github.com/TEIC/TEI-Simple-[Muse]: https://amusewiki.org/library/manual-[PowerPoint]: https://en.wikipedia.org/wiki/Microsoft_PowerPoint-[Vimwiki]: https://vimwiki.github.io-[CSL JSON]: https://citeproc-js.readthedocs.io/en/latest/csl-json/markup.html-[BibTeX]: https://ctan.org/pkg/bibtex-[BibLaTeX]: https://ctan.org/pkg/biblatex-[Markua]: https://leanpub.com/markua/read-[EndNote XML bibliography]: https://support.clarivate.com/Endnote/s/article/EndNote-XML-Document-Type-Definition-[typst]: https://typst.app--## Reader options {.options}--`--shift-heading-level-by=`*NUMBER*--:   Shift heading levels by a positive or negative integer.-    For example, with `--shift-heading-level-by=-1`, level 2-    headings become level 1 headings, and level 3 headings-    become level 2 headings.  Headings cannot have a level-    less than 1, so a heading that would be shifted below level 1-    becomes a regular paragraph.  Exception: with a shift of -N,-    a level-N heading at the beginning of the document-    replaces the metadata title. `--shift-heading-level-by=-1`-    is a good choice when converting HTML or Markdown documents that-    use an initial level-1 heading for the document title and-    level-2+ headings for sections. `--shift-heading-level-by=1`-    may be a good choice for converting Markdown documents that-    use level-1 headings for sections to HTML, since pandoc uses-    a level-1 heading to render the document title.--`--base-header-level=`*NUMBER*--:   *Deprecated.  Use `--shift-heading-level-by`=X instead,-    where X = NUMBER - 1.* Specify the base level for headings-    (defaults to 1).--`--indented-code-classes=`*CLASSES*--:   Specify classes to use for indented code blocks--for example,-    `perl,numberLines` or `haskell`. Multiple classes may be separated-    by spaces or commas.--`--default-image-extension=`*EXTENSION*--:   Specify a default extension to use when image paths/URLs have no-    extension.  This allows you to use the same source for formats that-    require different kinds of images.  Currently this option only affects-    the Markdown and LaTeX readers.--`--file-scope[=true|false]`--:   Parse each file individually before combining for multifile-    documents. This will allow footnotes in different files with the-    same identifiers to work as expected. If this option is set,-    footnotes and links will not work across files. Reading binary-    files (docx, odt, epub) implies `--file-scope`.--    If two or more files are processed using `--file-scope`,-    prefixes based on the filenames will be added to identifiers-    in order to disambiguate them, and internal links will-    be adjusted accordingly.  For example, a header with-    identifier `foo` in `subdir/file1.txt` will have its-    identifier changed to `subdir__file1.txt__foo`.--    In addition, a Div with an identifier based on the filename-    will be added around the file's content, so that internal-    links to the filename will point to this Div's identifier.--`-F` *PROGRAM*, `--filter=`*PROGRAM*--:   Specify an executable to be used as a filter transforming the-    pandoc AST after the input is parsed and before the output is-    written.  The executable should read JSON from stdin and write-    JSON to stdout.  The JSON must be formatted like  pandoc's own-    JSON input and output.  The name of the output format will be-    passed to the filter as the first argument.  Hence,--        pandoc --filter ./caps.py -t latex--    is equivalent to--        pandoc -t json | ./caps.py latex | pandoc -f json -t latex--    The latter form may be useful for debugging filters.--    Filters may be written in any language.  `Text.Pandoc.JSON`-    exports `toJSONFilter` to facilitate writing filters in Haskell.-    Those who would prefer to write filters in python can use the-    module [`pandocfilters`], installable from PyPI. There are also-    pandoc filter libraries in [PHP], [perl], and-    [JavaScript/node.js].--    In order of preference, pandoc will look for filters in--     1. a specified full or relative path (executable or-     non-executable),--     2. `$DATADIR/filters` (executable or non-executable)-     where `$DATADIR` is the user data directory (see-     `--data-dir`, above),--     3. `$PATH` (executable only).--    Filters, Lua-filters, and citeproc processing are applied in-    the order specified on the command line.--`-L` *SCRIPT*, `--lua-filter=`*SCRIPT*--:   Transform the document in a similar fashion as JSON filters (see-    `--filter`), but use pandoc's built-in Lua filtering system.  The given-    Lua script is expected to return a list of Lua filters which will be-    applied in order.  Each Lua filter must contain element-transforming-    functions indexed by the name of the AST element on which the filter-    function should be applied.--    The `pandoc` Lua module provides helper functions for element-    creation.  It is always loaded into the script's Lua environment.--    See the [Lua filters documentation] for further details.--    In order of preference, pandoc will look for Lua filters in--     1. a specified full or relative path,--     2. `$DATADIR/filters` where `$DATADIR` is the user data-     directory (see `--data-dir`, above).--    Filters, Lua filters, and citeproc processing are applied in-    the order specified on the command line.--`-M` *KEY*[`=`*VAL*], `--metadata=`*KEY*[`:`*VAL*]--:   Set the metadata field *KEY* to the value *VAL*.  A value specified-    on the command line overrides a value specified in the document-    using [YAML metadata blocks][Extension: `yaml_metadata_block`].-    Values will be parsed as YAML boolean or string values. If no value is-    specified, the value will be treated as Boolean true.  Like-    `--variable`, `--metadata` causes template variables to be set.-    But unlike `--variable`, `--metadata` affects the metadata of the-    underlying document (which is accessible from filters and may be-    printed in some output formats) and metadata values will be escaped-    when inserted into the template.--`--metadata-file=`*FILE*--:   Read metadata from the supplied YAML (or JSON) file. This-    option can be used with every input format, but string scalars-    in the metadata file will always be parsed as Markdown. (If the-    input format is Markdown or a Markdown variant, then the-    same variant will be used to parse the metadata file;-    if it is a non-Markdown format, pandoc's default Markdown-    extensions will be used.) This option can be used-    repeatedly to include multiple metadata files; values in-    files specified later on the command line will be preferred-    over those specified in earlier files. Metadata values-    specified inside the document, or by using `-M`, overwrite-    values specified with this option. The file will be searched-    for first in the working directory, and then in the `metadata`-    subdirectory of the user data directory (see `--data-dir`).--`-p`, `--preserve-tabs[=true|false]`--:   Preserve tabs instead of converting them to spaces. (By default, pandoc-    converts tabs to spaces before parsing its input.)  Note that this will-    only affect tabs in literal code spans and code blocks. Tabs in regular-    text are always treated as spaces.--`--tab-stop=`*NUMBER*--:   Specify the number of spaces per tab (default is 4).--`--track-changes=accept`|`reject`|`all`--:   Specifies what to do with insertions, deletions, and comments-    produced by the MS Word "Track Changes" feature.  `accept` (the-    default) processes all the insertions and deletions.-    `reject` ignores them.  Both `accept` and `reject` ignore comments.-    `all` includes all insertions, deletions, and comments, wrapped-    in spans with `insertion`, `deletion`, `comment-start`, and-    `comment-end` classes, respectively. The author and time of-    change is included. `all` is useful for scripting: only-    accepting changes from a certain reviewer, say, or before a-    certain date. If a paragraph is inserted or deleted,-    `track-changes=all` produces a span with the class-    `paragraph-insertion`/`paragraph-deletion` before the-    affected paragraph break. This option only affects the docx-    reader.--`--extract-media=`*DIR*--:   Extract images and other media contained in or linked from-    the source document to the path *DIR*, creating it if-    necessary, and adjust the images references in the document-    so they point to the extracted files.  Media are downloaded,-    read from the file system, or extracted from a binary-    container (e.g. docx), as needed.  The original file paths-    are used if they are relative paths not containing `..`.-    Otherwise filenames are constructed from the SHA1 hash of-    the contents.--`--abbreviations=`*FILE*--:   Specifies a custom abbreviations file, with abbreviations-    one to a line.  If this option is not specified, pandoc will-    read the data file `abbreviations` from the user data-    directory or fall back on a system default.  To see the-    system default, use-    `pandoc --print-default-data-file=abbreviations`.  The only-    use pandoc makes of this list is in the Markdown reader.-    Strings found in this list will be followed by a nonbreaking-    space, and the period will not produce sentence-ending space-    in formats like LaTeX.  The strings may not contain spaces.--`--trace[=true|false]`--:   Print diagnostic output tracing parser progress to stderr.-    This option is intended for use by developers in diagnosing-    performance issues.--[`pandocfilters`]: https://github.com/jgm/pandocfilters-[PHP]: https://github.com/vinai/pandocfilters-php-[perl]: https://metacpan.org/pod/Pandoc::Filter-[JavaScript/node.js]: https://github.com/mvhenderson/pandoc-filter-node-[Lua filters documentation]: https://pandoc.org/lua-filters.html--## General writer options {.options}--`-s`, `--standalone`--:   Produce output with an appropriate header and footer (e.g. a-    standalone HTML, LaTeX, TEI, or RTF file, not a fragment).  This option-    is set automatically for `pdf`, `epub`, `epub3`, `fb2`, `docx`, and `odt`-    output.  For `native` output, this option causes metadata to-    be included; otherwise, metadata is suppressed.--`--template=`*FILE*|*URL*--:   Use the specified file as a custom template for the generated document.-    Implies `--standalone`. See [Templates], below, for a description-    of template syntax. If no extension is specified, an extension-    corresponding to the writer will be added, so that `--template=special`-    looks for `special.html` for HTML output.  If the template is not-    found, pandoc will search for it in the `templates` subdirectory of-    the user data directory (see `--data-dir`). If this option is not used,-    a default template appropriate for the output format will be used (see-    `-D/--print-default-template`).--`-V` *KEY*[`=`*VAL*], `--variable=`*KEY*[`:`*VAL*]--:   Set the template variable *KEY* to the value *VAL* when rendering the-    document in standalone mode. If no *VAL* is specified, the-    key will be given the value `true`.--`--sandbox[=true|false]`--:   Run pandoc in a sandbox, limiting IO operations in readers-    and writers to reading the files specified on the command line.-    Note that this option does not limit IO operations by-    filters or in the production of PDF documents.  But it does-    offer security against, for example, disclosure of files-    through the use of `include` directives.  Anyone using-    pandoc on untrusted user input should use this option.--    Note: some readers and writers (e.g., `docx`) need access to data-    files.  If these are stored on the file system, then pandoc-    will not be able to find them when run in `--sandbox` mode-    and will raise an error. For these applications, we-    recommend using a pandoc binary compiled with the `embed_data_files`-    option, which causes the data files to be baked into the binary-    instead of being stored on the file system.--`-D` *FORMAT*, `--print-default-template=`*FORMAT*--:   Print the system default template for an output *FORMAT*. (See `-t`-    for a list of possible *FORMAT*s.)  Templates in the user data-    directory are ignored.  This option may be used with-    `-o`/`--output` to redirect output to a file, but-    `-o`/`--output` must come before `--print-default-template`-    on the command line.--    Note that some of the default templates use partials, for-    example `styles.html`.  To print the partials, use-    `--print-default-data-file`: for example,-    `--print-default-data-file=templates/styles.html`.--`--print-default-data-file=`*FILE*--:   Print a system default data file.  Files in the user data directory-    are ignored.  This option may be used with `-o`/`--output` to-    redirect output to a file, but `-o`/`--output` must come before-    `--print-default-data-file` on the command line.--`--eol=crlf`|`lf`|`native`--:   Manually specify line endings: `crlf` (Windows), `lf`-    (macOS/Linux/UNIX), or `native` (line endings appropriate-    to the OS on which pandoc is being run).  The default is-    `native`.--`--dpi`=*NUMBER*--:   Specify the default dpi (dots per inch) value for conversion-    from pixels to inch/centimeters and vice versa. (Technically,-    the correct term would be ppi: pixels per inch.) The default-    is 96dpi.   When images contain information about dpi-    internally, the encoded value is used instead of the default-    specified by this option.--`--wrap=auto`|`none`|`preserve`--:   Determine how text is wrapped in the output (the source-    code, not the rendered version).  With `auto` (the default),-    pandoc will attempt to wrap lines to the column width specified by-    `--columns` (default 72).  With `none`, pandoc will not wrap-    lines at all.  With `preserve`, pandoc will attempt to-    preserve the wrapping from the source document (that is,-    where there are nonsemantic newlines in the source, there-    will be nonsemantic newlines in the output as well).-    In `ipynb` output, this option affects wrapping of the-    contents of Markdown cells.--`--columns=`*NUMBER*--:   Specify length of lines in characters.  This affects text wrapping-    in the generated source code (see `--wrap`).  It also affects-    calculation of column widths for plain text tables (see [Tables] below).--`--toc[=true|false]`, `--table-of-contents[=true|false]`--:   Include an automatically generated table of contents (or, in-    the case of `latex`, `context`, `docx`, `odt`,-    `opendocument`, `rst`, or `ms`, an instruction to create-    one) in the output document. This option has no effect-    unless `-s/--standalone` is used, and it has no effect-    on `man`, `docbook4`, `docbook5`, or `jats` output.--    Note that if you are producing a PDF via `ms`, the table-    of contents will appear at the beginning of the-    document, before the title.  If you would prefer it to-    be at the end of the document, use the option-    `--pdf-engine-opt=--no-toc-relocation`.--`--toc-depth=`*NUMBER*--:   Specify the number of section levels to include in the table-    of contents.  The default is 3 (which means that level-1, 2, and 3-    headings will be listed in the contents).--`--strip-comments[=true|false]`--:   Strip out HTML comments in the Markdown or Textile source,-    rather than passing them on to Markdown, Textile or HTML-    output as raw HTML.  This does not apply to HTML comments-    inside raw HTML blocks when the `markdown_in_html_blocks`-    extension is not set.--`--no-highlight`--:   Disables syntax highlighting for code blocks and inlines, even when-    a language attribute is given.--`--highlight-style=`*STYLE*|*FILE*--:   Specifies the coloring style to be used in highlighted source code.-    Options are `pygments` (the default), `kate`, `monochrome`,-    `breezeDark`, `espresso`, `zenburn`, `haddock`, and `tango`.-    For more information on syntax highlighting in pandoc, see-    [Syntax highlighting], below.  See also-    `--list-highlight-styles`.--    Instead of a *STYLE* name, a JSON file with extension-    `.theme` may be supplied.  This will be parsed as a KDE-    syntax highlighting theme and (if valid) used as the-    highlighting style.--    To generate the JSON version of an existing style,-    use `--print-highlight-style`.--`--print-highlight-style=`*STYLE*|*FILE*--:   Prints a JSON version of a highlighting style, which can-    be modified, saved with a `.theme` extension, and used-    with `--highlight-style`.  This option may be used with-    `-o`/`--output` to redirect output to a file, but-    `-o`/`--output` must come before `--print-highlight-style`-    on the command line.--`--syntax-definition=`*FILE*--:   Instructs pandoc to load a KDE XML syntax definition file,-    which will be used for syntax highlighting of appropriately-    marked code blocks.  This can be used to add support for-    new languages or to use altered syntax definitions for-    existing languages.  This option may be repeated to add-    multiple syntax definitions.--`-H` *FILE*, `--include-in-header=`*FILE*|*URL*--:   Include contents of *FILE*, verbatim, at the end of the header.-    This can be used, for example, to include special-    CSS or JavaScript in HTML documents.  This option can be used-    repeatedly to include multiple files in the header.  They will be-    included in the order specified.  Implies `--standalone`.--`-B` *FILE*, `--include-before-body=`*FILE*|*URL*--:   Include contents of *FILE*, verbatim, at the beginning of the-    document body (e.g. after the `<body>` tag in HTML, or the-    `\begin{document}` command in LaTeX). This can be used to include-    navigation bars or banners in HTML documents. This option can be-    used repeatedly to include multiple files. They will be included in-    the order specified.  Implies `--standalone`.--`-A` *FILE*, `--include-after-body=`*FILE*|*URL*--:   Include contents of *FILE*, verbatim, at the end of the document-    body (before the `</body>` tag in HTML, or the-    `\end{document}` command in LaTeX). This option can be used-    repeatedly to include multiple files. They will be included in the-    order specified.  Implies `--standalone`.--`--resource-path=`*SEARCHPATH*--:   List of paths to search for images and other resources.-    The paths should be separated by `:` on Linux, UNIX, and-    macOS systems, and by `;` on Windows.  If `--resource-path`-    is not specified, the default resource path is the working-    directory. Note that, if `--resource-path` is specified,-    the working directory must be explicitly listed or it-    will not be searched.  For example:-    `--resource-path=.:test` will search the working directory-    and the `test` subdirectory, in that order.-    This option can be used repeatedly. Search path components-    that come later on the command line will be searched before-    those that come earlier, so-    `--resource-path foo:bar --resource-path baz:bim` is-    equivalent to `--resource-path baz:bim:foo:bar`.-    Note that this option only has an effect when pandoc-    itself needs to find an image (e.g., in producing a-    PDF or docx, or when `--embed-resources` is used.)-    It will not cause image paths to be rewritten in other-    cases (e.g., when pandoc is generating LaTeX or HTML).--`--request-header=`*NAME*`:`*VAL*--:   Set the request header *NAME* to the value *VAL* when making-    HTTP requests (for example, when a URL is given on the-    command line, or when resources used in a document must be-    downloaded). If you're behind a proxy, you also need to set-    the environment variable `http_proxy` to `http://...`.--`--no-check-certificate[=true|false]`--:   Disable the certificate verification to allow access to-    unsecure HTTP resources (for example when the certificate-    is no longer valid or self signed).--## Options affecting specific writers {.options}--`--self-contained[=true|false]`--:   *Deprecated synonym for `--embed-resources --standalone`.*--`--embed-resources[=true|false]`--:   Produce a standalone HTML file with no external dependencies, using-    `data:` URIs to incorporate the contents of linked scripts, stylesheets,-    images, and videos. The resulting file should be "self-contained," in the-    sense that it needs no external files and no net access to be displayed-    properly by a browser. This option works only with HTML output formats,-    including `html4`, `html5`, `html+lhs`, `html5+lhs`, `s5`, `slidy`,-    `slideous`, `dzslides`, and `revealjs`. Scripts, images, and stylesheets at-    absolute URLs will be downloaded; those at relative URLs will be sought-    relative to the working directory (if the first source-    file is local) or relative to the base URL (if the first source-    file is remote).  Elements with the attribute-    `data-external="1"` will be left alone; the documents they-    link to will not be incorporated in the document.-    Limitation: resources that are loaded dynamically through-    JavaScript cannot be incorporated; as a result, fonts may-    be missing when `--mathjax` is used, and some-    advanced features (e.g.  zoom or speaker notes) may not work-    in an offline "self-contained" `reveal.js` slide show.--`--html-q-tags[=true|false]`--:   Use `<q>` tags for quotes in HTML.  (This option only has an-    effect if the `smart` extension is enabled for the input-    format used.)--`--ascii[=true|false]`--:   Use only ASCII characters in output. Currently supported for XML-    and HTML formats (which use entities instead of UTF-8 when this-    option is selected), CommonMark, gfm, and Markdown (which use-    entities), roff man and ms (which use hexadecimal escapes), and to a-    limited degree LaTeX (which uses standard commands for accented-    characters when possible).--`--reference-links[=true|false]`--:   Use reference-style links, rather than inline links, in writing Markdown-    or reStructuredText.  By default inline links are used.  The-    placement of link references is affected by the-    `--reference-location` option.--`--reference-location=block`|`section`|`document`--:   Specify whether footnotes (and references, if `reference-links` is-    set) are placed at the end of the current (top-level) block, the-    current section, or the document. The default is-    `document`. Currently this option only affects the-    `markdown`, `muse`, `html`, `epub`, `slidy`, `s5`, `slideous`,-    `dzslides`, and `revealjs` writers.  In slide formats,-    specifying `--reference-location=section` will cause notes-    to be rendered at the bottom of a slide.--`--markdown-headings=setext`|`atx`--:   Specify whether to use ATX-style (`#`-prefixed) or-    Setext-style (underlined) headings for level 1 and 2-    headings in Markdown output.  (The default is `atx`.)-    ATX-style headings are always used for levels 3+.-    This option also affects Markdown cells in `ipynb` output.--`--list-tables[=true|false]`--:   Render tables as list tables in RST output.--`--top-level-division=default`|`section`|`chapter`|`part`--:   Treat top-level headings as the given division type in-    LaTeX, ConTeXt, DocBook, and  TEI output. The hierarchy-    order is part, chapter, then section; all headings are-    shifted such that the top-level heading becomes the-    specified type. The default behavior is to determine the-    best division type via heuristics: unless other conditions-    apply, `section` is chosen. When the `documentclass`-    variable is set to `report`, `book`, or `memoir` (unless the-    `article` option is specified), `chapter` is implied as the-    setting for this option. If `beamer` is the output format,-    specifying either `chapter` or `part` will cause top-level-    headings to become `\part{..}`, while second-level headings-    remain as their default type.--`-N`, `--number-sections`--:   Number section headings in LaTeX, ConTeXt, HTML, Docx, ms, or EPUB-    output.  By default, sections are not numbered.  Sections with class-    `unnumbered` will never be numbered, even if `--number-sections`-    is specified.--`--number-offset=`*NUMBER*[`,`*NUMBER*`,`*...*]--:   Offset for section headings in HTML output (ignored in other-    output formats).  The first number is added to the section number for-    top-level headings, the second for second-level headings, and so on.-    So, for example, if you want the first top-level heading in your-    document to be numbered "6", specify `--number-offset=5`.-    If your document starts with a level-2 heading which you want to-    be numbered "1.5", specify `--number-offset=1,4`.-    Offsets are 0 by default.  Implies `--number-sections`.--`--listings[=true|false]`--:   Use the [`listings`] package for LaTeX code blocks. The package-    does not support multi-byte encoding for source code. To handle UTF-8-    you would need to use a custom template. This issue is fully-    documented here: [Encoding issue with the listings package].--`-i`, `--incremental[=true|false]`--:   Make list items in slide shows display incrementally (one by one).-    The default is for lists to be displayed all at once.--`--slide-level=`*NUMBER*--:   Specifies that headings with the specified level create-    slides (for `beamer`, `s5`, `slidy`, `slideous`, `dzslides`).  Headings-    above this level in the hierarchy are used to divide the slide show-    into sections; headings below this level create subheads within a slide.-    Valid values are 0-6.  If a slide level of 0 is specified, slides will-    not be split automatically on headings, and horizontal rules must be used-    to indicate slide boundaries.  If a slide level is not specified-    explicitly, the slide level will be set automatically based on-    the contents of the document; see [Structuring the slide show].--`--section-divs[=true|false]`--:   Wrap sections in `<section>` tags (or `<div>` tags for `html4`),-    and attach identifiers to the enclosing `<section>` (or `<div>`)-    rather than the heading itself (see-    [Heading identifiers], below). This option only affects-    HTML output (and does not affect HTML slide formats).--`--email-obfuscation=none`|`javascript`|`references`--:   Specify a method for obfuscating `mailto:` links in HTML documents.-    `none` leaves `mailto:` links as they are.  `javascript` obfuscates-    them using JavaScript. `references` obfuscates them by printing their-    letters as decimal or hexadecimal character references.  The default-    is `none`.--`--id-prefix=`*STRING*--:   Specify a prefix to be added to all identifiers and internal links-    in HTML and DocBook output, and to footnote numbers in Markdown-    and Haddock output. This is useful for preventing duplicate-    identifiers when generating fragments to be included in other pages.--`-T` *STRING*, `--title-prefix=`*STRING*--:   Specify *STRING* as a prefix at the beginning of the title-    that appears in the HTML header (but not in the title as it-    appears at the beginning of the HTML body).  Implies `--standalone`.--`-c` *URL*, `--css=`*URL*--:   Link to a CSS style sheet. This option can be used repeatedly to-    include multiple files. They will be included in the order specified.-    This option only affects HTML (including HTML slide shows)-    and EPUB output.  It should be used together with-    `-s/--standalone`, because the link to the stylesheet goes-    in the document header.--    A stylesheet is required for generating EPUB.  If none is-    provided using this option (or the `css` or `stylesheet`-    metadata fields), pandoc will look for a file `epub.css` in the-    user data directory (see `--data-dir`).  If it is not-    found there, sensible defaults will be used.--`--reference-doc=`*FILE*|*URL*--:   Use the specified file as a style reference in producing a-    docx or ODT file.--    Docx--    :   For best results, the reference docx should be a modified-        version of a docx file produced using pandoc.  The contents-        of the reference docx are ignored, but its stylesheets and-        document properties (including margins, page size, header,-        and footer) are used in the new docx. If no reference docx-        is specified on the command line, pandoc will look for a-        file `reference.docx` in the user data directory (see-        `--data-dir`). If this is not found either, sensible-        defaults will be used.--        To produce a custom `reference.docx`, first get a copy of-        the default `reference.docx`: `pandoc-        -o custom-reference.docx --print-default-data-file reference.docx`.-        Then open `custom-reference.docx` in Word, modify the-        styles as you wish, and save the file.  For best-        results, do not make changes to this file other than-        modifying the styles used by pandoc:--        Paragraph styles:--        - Normal-        - Body Text-        - First Paragraph-        - Compact-        - Title-        - Subtitle-        - Author-        - Date-        - Abstract-        - AbstractTitle-        - Bibliography-        - Heading 1-        - Heading 2-        - Heading 3-        - Heading 4-        - Heading 5-        - Heading 6-        - Heading 7-        - Heading 8-        - Heading 9-        - Block Text [for block quotes]-        - Footnote Block Text [for block quotes in footnotes]-        - Source Code-        - Footnote Text-        - Definition Term-        - Definition-        - Caption-        - Table Caption-        - Image Caption-        - Figure-        - Captioned Figure-        - TOC Heading--        Character styles:--        - Default Paragraph Font-        - Body Text Char-        - Verbatim Char-        - Footnote Reference-        - Hyperlink-        - Section Number--        Table style:--        - Table--    ODT--    :   For best results, the reference ODT should be a modified-        version of an ODT produced using pandoc.  The contents of-        the reference ODT are ignored, but its stylesheets are used-        in the new ODT. If no reference ODT is specified on the-        command line, pandoc will look for a file `reference.odt` in-        the user data directory (see `--data-dir`). If this is not-        found either, sensible defaults will be used.--        To produce a custom `reference.odt`, first get a copy of-        the default `reference.odt`: `pandoc-        -o custom-reference.odt --print-default-data-file reference.odt`.-        Then open `custom-reference.odt` in LibreOffice, modify-        the styles as you wish, and save the file.--    PowerPoint--    :   Templates included with Microsoft PowerPoint 2013 (either with-        `.pptx` or `.potx` extension) are known to work, as are most-        templates derived from these.--        The specific requirement is that the template should contain layouts-        with the following names (as seen within PowerPoint):--        - Title Slide-        - Title and Content-        - Section Header-        - Two Content-        - Comparison-        - Content with Caption-        - Blank--        For each name, the first layout found with that name will be used.-        If no layout is found with one of the names, pandoc will output a-        warning and use the layout with that name from the default reference-        doc instead. (How these layouts are used is described in [PowerPoint-        layout choice](#powerpoint-layout-choice).)--        All templates included with a recent version of MS PowerPoint-        will fit these criteria. (You can click on `Layout` under the-        `Home` menu to check.)--        You can also modify the default `reference.pptx`: first run-        `pandoc -o custom-reference.pptx --print-default-data-file-        reference.pptx`, and then modify `custom-reference.pptx`-        in MS PowerPoint (pandoc will use the layouts with the names-        listed above).--`--split-level=`*NUMBER*--:   Specify the heading level at which to split an EPUB or-    chunked HTML document into separate files. The default is to split-    into chapters at level-1 headings. In the case of EPUB, this-    option only affects the internal composition of the EPUB, not the way-    chapters and sections are displayed to users. Some-    readers may be slow if the chapter files are too large, so for large-    documents with few level-1 headings, one might want to use a chapter-    level of 2 or 3. For chunked HTML, this option determines-    how much content goes in each "chunk."--`--chunk-template=`*PATHTEMPLATE*--:   Specify a template for the filenames in a `chunkedhtml` document.-    In the template, `%n` will be replaced by the chunk number (padded-    with leading 0s to 3 digits), `%s` with the section number of the chunk,-    `%h` with the heading text (with formatting removed), `%i` with-    the section identifier. For example, `%section-%s-%i.html` might-    be resolved to `section-1.1-introduction.html`. The characters-    `/` and `\` are not allowed in chunk templates and will be-    ignored. The default is `%s-%i.html`.--`--epub-chapter-level=`*NUMBER*--:   *Deprecated synonym for `--split-level`.*--`--epub-cover-image=`*FILE*--:   Use the specified image as the EPUB cover.  It is recommended-    that the image be less than 1000px in width and height. Note that-    in a Markdown source document you can also specify `cover-image`-    in a YAML metadata block (see [EPUB Metadata], below).--`--epub-title-page=true`|`false`--:   Determines whether a the title page is included in the EPUB-    (default is `true`).--`--epub-metadata=`*FILE*--:   Look in the specified XML file for metadata for the EPUB.-    The file should contain a series of [Dublin Core elements].-    For example:--         <dc:rights>Creative Commons</dc:rights>-         <dc:language>es-AR</dc:language>--    By default, pandoc will include the following metadata elements:-    `<dc:title>` (from the document title), `<dc:creator>` (from the-    document authors), `<dc:date>` (from the document date, which should-    be in [ISO 8601 format]), `<dc:language>` (from the `lang`-    variable, or, if is not set, the locale), and `<dc:identifier-    id="BookId">` (a randomly generated UUID). Any of these may be-    overridden by elements in the metadata file.--    Note: if the source document is Markdown, a YAML metadata block-    in the document can be used instead.  See below under-    [EPUB Metadata].--`--epub-embed-font=`*FILE*--:   Embed the specified font in the EPUB. This option can be repeated-    to embed multiple fonts.  Wildcards can also be used: for example,-    `DejaVuSans-*.ttf`.  However, if you use wildcards on the command-    line, be sure to escape them or put the whole filename in single quotes,-    to prevent them from being interpreted by the shell. To use the-    embedded fonts, you will need to add declarations like the following-    to your CSS (see `--css`):--        @font-face {-           font-family: DejaVuSans;-           font-style: normal;-           font-weight: normal;-           src:url("../fonts/DejaVuSans-Regular.ttf");-        }-        @font-face {-           font-family: DejaVuSans;-           font-style: normal;-           font-weight: bold;-           src:url("../fonts/DejaVuSans-Bold.ttf");-        }-        @font-face {-           font-family: DejaVuSans;-           font-style: italic;-           font-weight: normal;-           src:url("../fonts/DejaVuSans-Oblique.ttf");-        }-        @font-face {-           font-family: DejaVuSans;-           font-style: italic;-           font-weight: bold;-           src:url("../fonts/DejaVuSans-BoldOblique.ttf");-        }-        body { font-family: "DejaVuSans"; }--`--epub-subdirectory=`*DIRNAME*--:   Specify the subdirectory in the OCF container that is to hold-    the EPUB-specific contents.  The default is `EPUB`.  To put-    the EPUB contents in the top level, use an empty string.--`--ipynb-output=all|none|best`--:   Determines how ipynb output cells are treated. `all` means-    that all of the data formats included in the original are-    preserved.  `none` means that the contents of data cells-    are omitted.  `best` causes pandoc to try to pick the-    richest data block in each output cell that is compatible-    with the output format.  The default is `best`.--`--pdf-engine=`*PROGRAM*--:   Use the specified engine when producing PDF output.-    Valid values are `pdflatex`, `lualatex`, `xelatex`, `latexmk`,-    `tectonic`, `wkhtmltopdf`, `weasyprint`, `pagedjs-cli`,-    `prince`, `context`, `pdfroff`, and `typst`. If the engine is not in-    your PATH, the full path of the engine may be specified here.-    If this option is not specified, pandoc uses the following-    defaults depending on the output format specified using-    `-t/--to`:--    - `-t latex` or none: `pdflatex` (other options: `xelatex`, `lualatex`,-        `tectonic`, `latexmk`)-    - `-t context`: `context`-    - `-t html`:  `wkhtmltopdf` (other options: `prince`, `weasyprint`,-        `pagedjs-cli`;-        see [print-css.rocks](https://print-css.rocks) for a good-        introduction to PDF generation from HTML/CSS)-    - `-t ms`:  `pdfroff`-    - `-t typst`: `typst`--`--pdf-engine-opt=`*STRING*--:   Use the given string as a command-line argument to the `pdf-engine`.-    For example, to use a persistent directory `foo` for `latexmk`'s-    auxiliary files, use `--pdf-engine-opt=-outdir=foo`.-    Note that no check for duplicate options is done.--[Dublin Core elements]: https://www.dublincore.org/specifications/dublin-core/dces/-[ISO 8601 format]: https://www.w3.org/TR/NOTE-datetime-[Encoding issue with the listings package]:-  https://en.wikibooks.org/wiki/LaTeX/Source_Code_Listings#Encoding_issue--## Citation rendering {.options}--`-C`, `--citeproc`--:   Process the citations in the file, replacing them with-    rendered citations and adding a bibliography.-    Citation processing will not take place unless bibliographic-    data is supplied, either through an external file specified-    using the `--bibliography` option or the `bibliography`-    field in metadata, or via a `references` section in metadata-    containing a list of citations in CSL YAML format with-    Markdown formatting.  The style is controlled by a [CSL]-    stylesheet specified using the `--csl` option or the `csl`-    field in metadata. (If no stylesheet is specified,-    the `chicago-author-date` style will be used by default.)-    The citation processing transformation may be applied before-    or after filters or Lua filters (see `--filter`,-    `--lua-filter`): these transformations are applied in the-    order they appear on the command line.  For more-    information, see the section on [Citations].--`--bibliography=`*FILE*--:   Set the `bibliography` field in the document's metadata to *FILE*,-    overriding any value set in the metadata.  If you supply-    this argument multiple times, each *FILE* will be added to-    bibliography.  If *FILE* is a URL, it will be fetched-    via HTTP. If *FILE* is not found relative to the-    working directory, it will be sought in the resource path-    (see `--resource-path`).--`--csl=`*FILE*--:   Set the `csl` field in the document's metadata to *FILE*,-    overriding any value set in the metadata.  (This is equivalent to-    `--metadata csl=FILE`.)  If *FILE* is a URL, it will be-    fetched via HTTP.  If *FILE* is not found relative to the-    working directory, it will be sought in the resource path-    (see `--resource-path`) and finally in the `csl`-    subdirectory of the pandoc user data directory.--`--citation-abbreviations=`*FILE*--:   Set the `citation-abbreviations` field in the document's metadata to-    *FILE*, overriding any value set in the metadata.  (This is equivalent to-    `--metadata citation-abbreviations=FILE`.)-    If *FILE* is a URL, it will be fetched via HTTP.  If *FILE* is not-    found relative to the working directory, it will be sought-    in the resource path (see `--resource-path`) and finally in-    the `csl` subdirectory of the pandoc user data directory.--`--natbib`--:   Use [`natbib`] for citations in LaTeX output.  This option-    is not for use with the `--citeproc` option or with PDF-    output.  It is intended for use in producing a LaTeX file-    that can be processed with [`bibtex`].--`--biblatex`--:   Use [`biblatex`] for citations in LaTeX output.  This option-    is not for use with the `--citeproc` option or with PDF-    output. It is intended for use in producing a LaTeX file-    that can be processed with [`bibtex`] or [`biber`].--## Math rendering in HTML {.options}--The default is to render TeX math as far as possible using-Unicode characters.  Formulas are put inside a `span` with-`class="math"`, so that they may be styled differently from the-surrounding text if needed. However, this gives acceptable-results only for basic math, usually you will want to use-`--mathjax` or another of the following options.--`--mathjax`[`=`*URL*]--:   Use [MathJax] to display embedded TeX math in HTML output.-    TeX math will be put between `\(...\)` (for inline math)-    or `\[...\]` (for display math) and wrapped in `<span>` tags-    with class `math`. Then the MathJax JavaScript will render it.-    The *URL* should point to the `MathJax.js` load script.-    If a *URL* is not provided, a link to the Cloudflare CDN will-    be inserted.--`--mathml`--:   Convert TeX math to [MathML] (in `epub3`, `docbook4`,-    `docbook5`, `jats`, `html4` and `html5`).  This is the-    default in `odt` output. MathML is supported natively by-    the main web browsers and select e-book readers.--`--webtex`[`=`*URL*]--:   Convert TeX formulas to `<img>` tags that link to an external script-    that converts formulas to images. The formula will be URL-encoded-    and concatenated with the URL provided. For SVG images you can for-    example use `--webtex https://latex.codecogs.com/svg.latex?`.-    If no URL is specified, the CodeCogs URL generating PNGs-    will be used (`https://latex.codecogs.com/png.latex?`).-    Note:  the `--webtex` option will affect Markdown output-    as well as HTML, which is useful if you're targeting a-    version of Markdown without native math support.--`--katex`[`=`*URL*]--:   Use [KaTeX] to display embedded TeX math in HTML output.-    The *URL* is the base URL for the KaTeX library. That directory-    should contain a `katex.min.js` and a `katex.min.css` file.-    If a *URL* is not provided, a link to the KaTeX CDN will be inserted.--`--gladtex`--:   Enclose TeX math in `<eq>` tags in HTML output.  The resulting HTML-    can then be processed by [GladTeX] to produce SVG images of the typeset-    formulas and an HTML file with these images embedded.--        pandoc -s --gladtex input.md -o myfile.htex-        gladtex -d image_dir myfile.htex-        # produces myfile.html and images in image_dir--[MathML]: https://www.w3.org/Math/-[MathJax]: https://www.mathjax.org-[KaTeX]: https://github.com/Khan/KaTeX-[GladTeX]: https://humenda.github.io/GladTeX/--## Options for wrapper scripts {.options}--`--dump-args[=true|false]`--:   Print information about command-line arguments to *stdout*, then exit.-    This option is intended primarily for use in wrapper scripts.-    The first line of output contains the name of the output file specified-    with the `-o` option, or `-` (for *stdout*) if no output file was-    specified.  The remaining lines contain the command-line arguments,-    one per line, in the order they appear.  These do not include regular-    pandoc options and their arguments, but do include any options appearing-    after a `--` separator at the end of the line.--`--ignore-args[=true|false]`--:   Ignore command-line arguments (for use in wrapper scripts).-    Regular pandoc options are not ignored.  Thus, for example,--        pandoc --ignore-args -o foo.html -s foo.txt -- -e latin1--    is equivalent to--        pandoc -o foo.html -s--# Exit codes--If pandoc completes successfully, it will return exit code 0.-Nonzero exit codes have the following meanings:-- Code Error------ -------------------------------------    1 PandocIOError-    3 PandocFailOnWarningError-    4 PandocAppError-    5 PandocTemplateError-    6 PandocOptionError-   21 PandocUnknownReaderError-   22 PandocUnknownWriterError-   23 PandocUnsupportedExtensionError-   24 PandocCiteprocError-   25 PandocBibliographyError-   31 PandocEpubSubdirectoryError-   43 PandocPDFError-   44 PandocXMLError-   47 PandocPDFProgramNotFoundError-   61 PandocHttpError-   62 PandocShouldNeverHappenError-   63 PandocSomeError-   64 PandocParseError-   66 PandocMakePDFError-   67 PandocSyntaxMapError-   83 PandocFilterError-   84 PandocLuaError-   89 PandocNoScriptingEngine-   91 PandocMacroLoop-   92 PandocUTF8DecodingError-   93 PandocIpynbDecodingError-   94 PandocUnsupportedCharsetError-   97 PandocCouldNotFindDataFileError-   98 PandocCouldNotFindMetadataFileError-   99 PandocResourceNotFound------ --------------------------------------# Defaults files--The `--defaults` option may be used to specify a package-of options, in the form of a YAML file.--Fields that are omitted will just have their regular-default values.  So a defaults file can be as simple as-one line:--``` yaml-verbosity: INFO-```--In fields that expect a file path (or list of file paths), the-following syntax may be used to interpolate environment variables:--``` yaml-csl:  ${HOME}/mycsldir/special.csl-```--`${USERDATA}` may also be used; this will always resolve to the-user data directory that is current when the defaults file is-parsed, regardless of the setting of the environment-variable `USERDATA`.--`${.}` will resolve to the directory containing the defaults-file itself.  This allows you to refer to resources contained-in that directory:--``` yaml-epub-cover-image: ${.}/cover.jpg-epub-metadata: ${.}/meta.xml-resource-path:-- .             # the working directory from which pandoc is run-- ${.}/images   # the images subdirectory of the directory-                # containing this defaults file-```--This environment variable interpolation syntax *only* works in-fields that expect file paths.--Defaults files can be placed in the `defaults` subdirectory of-the user data directory and used from any directory.  For-example, one could create a file specifying defaults for writing-letters, save it as `letter.yaml` in the `defaults` subdirectory-of the user data directory, and then invoke these defaults-from any directory using `pandoc --defaults letter`-or `pandoc -dletter`.--When multiple defaults are used, their contents will be combined.--Note that, where command-line arguments may be repeated-(`--metadata-file`, `--css`, `--include-in-header`,-`--include-before-body`, `--include-after-body`, `--variable`,-`--metadata`, `--syntax-definition`), the values specified on-the command line will combine with values specified in the-defaults file, rather than replacing them.--The following tables show the mapping between the command line and-defaults file entries.--+----------------------------------+-----------------------------------+-| command line                     | defaults file                     |-+:=================================+:==================================+-| ```                              | ``` yaml                          |-| foo.md                           | input-file: foo.md                |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| foo.md bar.md                    | input-files:                      |-|                                  |   - foo.md                        |-|                                  |   - bar.md                        |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+--The value of `input-files` may be left empty to indicate input from-stdin, and it can be an empty sequence `[]` for no input.--## General options--+----------------------------------+-----------------------------------+-| command line                     | defaults file                     |-+:=================================+:==================================+-| ```                              | ``` yaml                          |-| --from markdown+emoji            | from: markdown+emoji              |-| ```                              | ```                               |-|                                  | ``` yaml                          |-|                                  | reader: markdown+emoji            |-|                                  | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --to markdown+hard_line_breaks   | to: markdown+hard_line_breaks     |-| ```                              | ```                               |-|                                  | ``` yaml                          |-|                                  | writer: markdown+hard_line_breaks |-|                                  | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --output foo.pdf                 | output-file: foo.pdf              |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --output -                       | output-file:                      |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --data-dir dir                   | data-dir: dir                     |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --defaults file                  | defaults:                         |-| ```                              | - file                            |-|                                  | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --verbose                        | verbosity: INFO                   |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --quiet                          | verbosity: ERROR                  |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --fail-if-warnings               | fail-if-warnings: true            |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --sandbox                        | sandbox: true                     |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --log=FILE                       | log-file: FILE                    |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+--Options specified in a defaults file itself always have priority over-those in another file included with a `defaults:` entry.--`verbosity` can have the values `ERROR`, `WARNING`, or `INFO`.--## Reader options--+----------------------------------+-----------------------------------+-| command line                     | defaults file                     |-+:=================================+:==================================+-| ```                              | ``` yaml                          |-| --shift-heading-level-by -1      | shift-heading-level-by: -1        |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --indented-code-classes python   | indented-code-classes:            |-|                                  |   - python                        |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --default-image-extension ".jpg" | default-image-extension: '.jpg'   |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --file-scope                     | file-scope: true                  |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --citeproc \                     | filters:                          |-|  --lua-filter count-words.lua \  |   - citeproc                      |-|  --filter special.lua            |   - count-words.lua               |-|                                  |   - type: json                    |-|                                  |     path: special.lua             |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --metadata key=value \           | metadata:                         |-|  --metadata key2                 |   key: value                      |-|                                  |   key2: true                      |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --metadata-file meta.yaml        | metadata-files:                   |-|                                  |   - meta.yaml                     |-| ```                              | ```                               |-|                                  | ``` yaml                          |-|                                  | metadata-file: meta.yaml          |-|                                  | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --preserve-tabs                  | preserve-tabs: true               |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --tab-stop 8                     | tab-stop: 8                       |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --track-changes accept           | track-changes: accept             |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --extract-media dir              | extract-media: dir                |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --abbreviations abbrevs.txt      | abbreviations: abbrevs.txt        |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --trace                          | trace: true                       |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+--Metadata values specified in a defaults file are parsed as literal-string text, not Markdown.--Filters will be assumed to be Lua filters if they have the `.lua`-extension, and JSON filters otherwise.  But the filter type can also be-specified explicitly, as shown.  Filters are run in the order specified.-To include the built-in citeproc filter, use either `citeproc` or-`{type: citeproc}`.--## General writer options--+----------------------------------+-----------------------------------+-| command line                     | defaults file                     |-+:=================================+:==================================+-| ```                              | ``` yaml                          |-| --standalone                     | standalone: true                  |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --template letter                | template: letter                  |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --variable key=val \             | variables:                        |-|   --variable key2                |   key: val                        |-|                                  |   key2: true                      |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --eol nl                         | eol: nl                           |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --dpi 300                        | dpi: 300                          |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --wrap 60                        | wrap: 60                          |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --columns 72                     | columns: 72                       |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --table-of-contents              | table-of-contents: true           |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --toc                            | toc: true                         |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --toc-depth 3                    | toc-depth: 3                      |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --strip-comments                 | strip-comments: true              |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --no-highlight                   | highlight-style: null             |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --highlight-style kate           | highlight-style: kate             |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --syntax-definition mylang.xml   | syntax-definitions:               |-|                                  |   - mylang.xml                    |-| ```                              | ```                               |-|                                  | ``` yaml                          |-|                                  | syntax-definition: mylang.xml     |-|                                  | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --include-in-header inc.tex      | include-in-header:                |-|                                  |   - inc.tex                       |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --include-before-body inc.tex    | include-before-body:              |-|                                  |   - inc.tex                       |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --include-after-body inc.tex     | include-after-body:               |-|                                  |   - inc.tex                       |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --resource-path .:foo            | resource-path: ['.','foo']        |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --request-header foo:bar         | request-headers:                  |-|                                  |   - ["User-Agent", "Mozilla/5.0"] |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --no-check-certificate           | no-check-certificate: true        |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+---## Options affecting specific writers--+----------------------------------+-----------------------------------+-| command line                     | defaults file                     |-+:=================================+:==================================+-| ```                              | ``` yaml                          |-| --self-contained                 | self-contained: true              |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --html-q-tags                    | html-q-tags: true                 |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --ascii                          | ascii: true                       |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --reference-links                | reference-links: true             |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --reference-location block       | reference-location: block         |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --markdown-headings atx          | markdown-headings: atx            |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --list-tables                    | list-tables: true                 |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --top-level-division chapter     | top-level-division: chapter       |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --number-sections                | number-sections: true             |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --number-offset=1,4              | number-offset: \[1,4\]            |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --listings                       | listings: true                    |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --incremental                    | incremental: true                 |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --slide-level 2                  | slide-level: 2                    |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --section-divs                   | section-divs: true                |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --email-obfuscation references   | email-obfuscation: references     |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --id-prefix ch1                  | identifier-prefix: ch1            |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --title-prefix MySite            | title-prefix: MySite              |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --css styles/screen.css  \       | css:                              |-|   --css styles/special.css       |   - styles/screen.css             |-|                                  |   - styles/special.css            |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --reference-doc my.docx          | reference-doc: my.docx            |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --epub-cover-image cover.jpg     | epub-cover-image: cover.jpg       |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --epub-title-page=false          | epub-title-page: false            |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --epub-metadata meta.xml         | epub-metadata: meta.xml           |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --epub-embed-font special.otf \  | epub-fonts:                       |-|   --epub-embed-font headline.otf |   - special.otf                   |-|                                  |   - headline.otf                  |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --split-level 2                  | split-level: 2                    |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --chunk-template="%i.html"       | chunk-template: "%i.html"         |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --epub-subdirectory=""           | epub-subdirectory: ''             |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --ipynb-output best              | ipynb-output: best                |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --pdf-engine xelatex             | pdf-engine: xelatex               |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --pdf-engine-opt=--shell-escape  | pdf-engine-opts:                  |-|                                  |   - '-shell-escape'               |-| ```                              | ```                               |-|                                  | ``` yaml                          |-|                                  | pdf-engine-opt: '-shell-escape'   |-|                                  | ```                               |-+----------------------------------+-----------------------------------+--## Citation rendering--+----------------------------------+-----------------------------------+-| command line                     | defaults file                     |-+:=================================+:==================================+-| ```                              | ``` yaml                          |-| --citeproc                       | citeproc: true                    |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --bibliography logic.bib         | bibliography: logic.bib           |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --csl ieee.csl                   | csl: ieee.csl                     |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --citation-abbreviations ab.json | citation-abbreviations: ab.json   |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --natbib                         | cite-method: natbib               |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --biblatex                       | cite-method: biblatex             |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+--`cite-method` can be `citeproc`, `natbib`, or `biblatex`. This only-affects LaTeX output.  If you want to use citeproc to format citations,-you should also set 'citeproc: true'.--If you need control over when the citeproc processing is done relative-to other filters, you should instead use `citeproc` in the list-of `filters` (see [Reader options](#reader-options-1)).--## Math rendering in HTML--+----------------------------------+-----------------------------------+-| command line                     | defaults file                     |-+:=================================+:==================================+-| ```                              | ``` yaml                          |-| --mathjax                        | html-math-method:                 |-|                                  |   method: mathjax                 |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --mathml                         | html-math-method:                 |-|                                  |   method: mathml                  |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --webtex                         | html-math-method:                 |-|                                  |   method: webtex                  |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --katex                          | html-math-method:                 |-|                                  |   method: katex                   |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --gladtex                        | html-math-method:                 |-|                                  |   method: gladtex                 |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+--In addition to the values listed above, `method` can have the-value `plain`.--If the command line option accepts a URL argument, an `url:` field can-be added to `html-math-method:`.--## Options for wrapper scripts--+----------------------------------+-----------------------------------+-| command line                     | defaults file                     |-+:=================================+:==================================+-| ```                              | ``` yaml                          |-| --dump-args                      | dump-args: true                   |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+-| ```                              | ``` yaml                          |-| --ignore-args                    | ignore-args: true                 |-| ```                              | ```                               |-+----------------------------------+-----------------------------------+--# Templates--When the `-s/--standalone` option is used, pandoc uses a template to-add header and footer material that is needed for a self-standing-document.  To see the default template that is used, just type--    pandoc -D *FORMAT*--where *FORMAT* is the name of the output format. A custom template-can be specified using the `--template` option.  You can also override-the system default templates for a given output format *FORMAT*-by putting a file `templates/default.*FORMAT*` in the user data-directory (see `--data-dir`, above). *Exceptions:*--- For `odt` output, customize the `default.opendocument`-  template.-- For `pdf` output, customize the `default.latex` template-  (or the `default.context` template, if you use `-t context`,-  or the `default.ms` template, if you use `-t ms`, or the-  `default.html` template, if you use `-t html`).-- `docx` and `pptx` have no template (however, you can use-  `--reference-doc` to customize the output).--Templates contain *variables*, which allow for the inclusion of-arbitrary information at any point in the file. They may be set at the-command line using the `-V/--variable` option. If a variable is not set,-pandoc will look for the key in the document's metadata, which can be set-using either [YAML metadata blocks][Extension: `yaml_metadata_block`]-or with the `-M/--metadata` option.  In addition, some variables-are given default values by pandoc.  See [Variables] below for-a list of variables used in pandoc's default templates.--If you use custom templates, you may need to revise them as pandoc-changes.  We recommend tracking the changes in the default templates,-and modifying your custom templates accordingly. An easy way to do this-is to fork the [pandoc-templates] repository and merge in-changes after each pandoc release.--  [pandoc-templates]: https://github.com/jgm/pandoc-templates--## Template syntax--### Comments--Anything between the sequence `$--` and the end of the-line will be treated as a comment and omitted from the output.--### Delimiters--To mark variables and control structures in the template,-either `$`...`$` or `${`...`}` may be used as delimiters.-The styles may also be mixed in the same template, but the-opening and closing delimiter must match in each case.  The-opening delimiter may be followed by one or more spaces-or tabs, which will be ignored. The closing delimiter may-be preceded by one or more spaces or tabs, which will be-ignored.--To include a literal `$` in the document, use `$$`.--### Interpolated variables--A slot for an interpolated variable is a variable name surrounded-by matched delimiters.  Variable names must begin with a letter-and can contain letters, numbers, `_`, `-`, and `.`.  The-keywords `it`, `if`, `else`, `endif`, `for`, `sep`, and `endfor` may-not be used as variable names. Examples:--```-$foo$-$foo.bar.baz$-$foo_bar.baz-bim$-$ foo $-${foo}-${foo.bar.baz}-${foo_bar.baz-bim}-${ foo }-```--Variable names with periods are used to get at structured-variable values.  So, for example, `employee.salary` will return the-value of the `salary` field of the object that is the value of-the `employee` field.--- If the value of the variable is a simple value, it will be-  rendered verbatim.  (Note that no escaping is done;-  the assumption is that the calling program will escape-  the strings appropriately for the output format.)-- If the value is a list, the values will be concatenated.-- If the value is a map, the string `true` will be rendered.-- Every other value will be rendered as the empty string.--### Conditionals--A conditional begins with `if(variable)` (enclosed in-matched delimiters) and ends with `endif` (enclosed in matched-delimiters).  It may optionally contain an `else` (enclosed in-matched delimiters).  The `if` section is used if-`variable` has a non-empty value, otherwise the `else`-section is used (if present).  Examples:--```-$if(foo)$bar$endif$--$if(foo)$-  $foo$-$endif$--$if(foo)$-part one-$else$-part two-$endif$--${if(foo)}bar${endif}--${if(foo)}-  ${foo}-${endif}--${if(foo)}-${ foo.bar }-${else}-no foo!-${endif}-```--The keyword `elseif` may be used to simplify complex nested-conditionals:--```-$if(foo)$-XXX-$elseif(bar)$-YYY-$else$-ZZZ-$endif$-```--### For loops--A for loop begins with `for(variable)` (enclosed in-matched delimiters) and ends with `endfor` (enclosed in matched-delimiters).--- If `variable` is an array, the material inside the loop will-  be evaluated repeatedly, with `variable` being set to each-  value of the array in turn, and concatenated.-- If `variable` is a map, the material inside will be set to-  the map.-- If the value of the associated variable is not an array or-  a map, a single iteration will be performed on its value.--Examples:--```-$for(foo)$$foo$$sep$, $endfor$--$for(foo)$-  - $foo.last$, $foo.first$-$endfor$--${ for(foo.bar) }-  - ${ foo.bar.last }, ${ foo.bar.first }-${ endfor }--$for(mymap)$-$it.name$: $it.office$-$endfor$-```--You may optionally specify a separator between consecutive-values using `sep` (enclosed in matched delimiters).  The-material between `sep` and the `endfor` is the separator.--```-${ for(foo) }${ foo }${ sep }, ${ endfor }-```--Instead of using `variable` inside the loop, the special-anaphoric keyword `it` may be used.--```-${ for(foo.bar) }-  - ${ it.last }, ${ it.first }-${ endfor }-```--### Partials--Partials (subtemplates stored in different files) may be-included by using the name of the partial, followed-by `()`, for example:--```-${ styles() }-```--Partials will be sought in the directory containing-the main template. The file name will be assumed to-have the same extension as the main template if it-lacks an extension. When calling the partial, the-full name including file extension can also be used:--```-${ styles.html() }-```--(If a partial is not found in the directory of the-template and the template path is given as a relative-path, it will also be sought in the `templates`-subdirectory of the user data directory.)--Partials may optionally be applied to variables using-a colon:--```-${ date:fancy() }--${ articles:bibentry() }-```--If `articles` is an array, this will iterate over its-values, applying the partial `bibentry()` to each one.  So the-second example above is equivalent to--```-${ for(articles) }-${ it:bibentry() }-${ endfor }-```--Note that the anaphoric keyword `it` must be used when-iterating over partials.  In the above examples,-the `bibentry` partial should contain `it.title`-(and so on) instead of `articles.title`.--Final newlines are omitted from included partials.--Partials may include other partials.--A separator between values of an array may be specified-in square brackets, immediately after the variable name-or partial:--```-${months[, ]}$--${articles:bibentry()[; ]$-```--The separator in this case is literal and (unlike with `sep`-in an explicit `for` loop) cannot contain interpolated-variables or other template directives.--### Nesting--To ensure that content is "nested," that is, subsequent lines-indented, use the `^` directive:--```-$item.number$  $^$$item.description$ ($item.price$)-```--In this example, if `item.description` has multiple lines,-they will all be indented to line up with the first line:--```-00123  A fine bottle of 18-year old-       Oban whiskey. ($148)-```--To nest multiple lines to the same level, align them-with the `^` directive in the template. For example:--```-$item.number$  $^$$item.description$ ($item.price$)-               (Available til $item.sellby$.)-```--will produce--```-00123  A fine bottle of 18-year old-       Oban whiskey. ($148)-       (Available til March 30, 2020.)-```--If a variable occurs by itself on a line, preceded by whitespace-and not followed by further text or directives on the same line,-and the variable's value contains multiple lines, it will be-nested automatically.--### Breakable spaces--Normally, spaces in the template itself (as opposed to values of-the interpolated variables) are not breakable, but they can be-made breakable in part of the template by using the `~` keyword-(ended with another `~`).--```-$~$This long line may break if the document is rendered-with a short line length.$~$-```--### Pipes--A pipe transforms the value of a variable or partial. Pipes are-specified using a slash (`/`) between the variable name (or partial)-and the pipe name. Example:--```-$for(name)$-$name/uppercase$-$endfor$--$for(metadata/pairs)$-- $it.key$: $it.value$-$endfor$--$employee:name()/uppercase$-```--Pipes may be chained:--```-$for(employees/pairs)$-$it.key/alpha/uppercase$. $it.name$-$endfor$-```--Some pipes take parameters:--```-|----------------------|------------|-$for(employee)$-$it.name.first/uppercase/left 20 "| "$$it.name.salary/right 10 " | " " |"$-$endfor$-|----------------------|------------|-```--Currently the following pipes are predefined:--- `pairs`:  Converts a map or array to an array of maps,-  each with `key` and `value` fields.  If the original-  value was an array, the `key` will be the array index,-  starting with 1.--- `uppercase`:  Converts text to uppercase.--- `lowercase`:  Converts text to lowercase.--- `length`:  Returns the length of the value:  number-  of characters for a textual value, number of elements-  for a map or array.--- `reverse`:  Reverses a textual value or array,-  and has no effect on other values.--- `first`: Returns the first value of an array, if-  applied to a non-empty array; otherwise returns-  the original value.--- `last`: Returns the last value of an array, if-  applied to a non-empty array; otherwise returns-  the original value.--- `rest`: Returns all but the first value of an array, if-  applied to a non-empty array; otherwise returns-  the original value.--- `allbutlast`: Returns all but the last value of an array, if-  applied to a non-empty array; otherwise returns-  the original value.--- `chomp`:  Removes trailing newlines (and breakable space).--- `nowrap`:  Disables line wrapping on breakable spaces.--- `alpha`:  Converts textual values that can be-  read as an integer into lowercase alphabetic-  characters `a..z` (mod 26). This can be used to get lettered-  enumeration from array indices.  To get uppercase-  letters, chain with `uppercase`.--- `roman`:  Converts textual values that can be-  read as an integer into lowercase roman numerals.-  This can be used to get lettered enumeration from array indices.-  To get uppercase roman, chain with `uppercase`.--- `left n "leftborder" "rightborder"`:  Renders a textual value-  in a block of width `n`, aligned to the left, with an optional-  left and right border.  Has no effect on other values. This-  can be used to align material in tables.  Widths are positive-  integers indicating the number of characters.  Borders-  are strings inside double quotes; literal `"` and `\` characters-  must be backslash-escaped.--- `right n "leftborder" "rightborder"`:  Renders a textual value-  in a block of width `n`, aligned to the right, and has no-  effect on other values.--- `center n "leftborder" "rightborder"`:  Renders a textual-  value in a block of width `n`, aligned to the center, and has-  no effect on other values.---## Variables--### Metadata variables--`title`, `author`, `date`-:   allow identification of basic aspects of the document.  Included-    in PDF metadata through LaTeX and ConTeXt.  These can be set-    through a [pandoc title block][Extension: `pandoc_title_block`],-    which allows for multiple authors, or through a-    [YAML metadata block][Extension: `yaml_metadata_block`]:--        ----        author:-        - Aristotle-        - Peter Abelard-        ...--    Note that if you just want to set PDF or HTML metadata, without-    including a title block in the document itself, you can-    set the `title-meta`, `author-meta`, and `date-meta`-    variables.  (By default these are set automatically, based-    on `title`, `author`, and `date`.) The page title in HTML-    is set by `pagetitle`, which is equal to `title` by default.--`subtitle`-:   document subtitle, included in HTML, EPUB, LaTeX, ConTeXt, and docx-    documents--`abstract`-:   document summary, included in HTML, LaTeX, ConTeXt, AsciiDoc, and docx-    documents--`abstract-title`-:   title of abstract, currently used only in HTML, EPUB, and docx.-    This will be set automatically to a localized value,-    depending on `lang`, but can be manually overridden.--`keywords`-:   list of keywords to be included in HTML, PDF, ODT, pptx, docx-    and AsciiDoc metadata; repeat as for `author`, above--`subject`-:   document subject, included in ODT, PDF, docx, EPUB, and pptx metadata--`description`-:   document description, included in ODT, docx and pptx metadata. Some-    applications show this as `Comments` metadata.--`category`-:   document category, included in docx and pptx metadata--Additionally,-any root-level string metadata, not included in ODT, docx-or pptx metadata is added as a *custom property*.-The following [YAML] metadata block for instance:--    ----    title:  'This is the title'-    subtitle: "This is the subtitle"-    author:-    - Author One-    - Author Two-    description: |-        This is a long-        description.--        It consists of two paragraphs-    ...--will include `title`, `author` and `description` as standard document-properties and `subtitle` as a custom property when converting to docx,-ODT or pptx.--### Language variables--`lang`-:   identifies the main language of the document using IETF language-    tags (following the [BCP 47] standard), such as `en` or `en-GB`.-    The [Language subtag lookup] tool can look up or verify these tags.-    This affects most formats, and controls hyphenation in PDF output-    when using LaTeX (through [`babel`] and [`polyglossia`]) or ConTeXt.--    Use native pandoc [Divs and Spans] with the `lang` attribute to-    switch the language:--        ----        lang: en-GB-        ...--        Text in the main document language (British English).--        ::: {lang=fr-CA}-        > Cette citation est écrite en français canadien.-        :::--        More text in English. ['Zitat auf Deutsch.']{lang=de}--`dir`-:   the base script direction, either `rtl` (right-to-left)-    or `ltr` (left-to-right).--    For bidirectional documents, native pandoc `span`s and-    `div`s with the `dir` attribute (value `rtl` or `ltr`) can-    be used to override the base direction in some output-    formats.  This may not always be necessary if the final-    renderer (e.g. the browser, when generating HTML) supports-    the [Unicode Bidirectional Algorithm].--    When using LaTeX for bidirectional documents, only the-    `xelatex` engine is fully supported (use-    `--pdf-engine=xelatex`).--[BCP 47]: https://tools.ietf.org/html/bcp47-[Unicode Bidirectional Algorithm]: https://www.w3.org/International/articles/inline-bidi-markup/uba-basics-[Language subtag lookup]: https://r12a.github.io/app-subtags/--### Variables for HTML--`document-css`-:   Enables inclusion of most of the [CSS] in the `styles.html`-    [partial](#partials) (have a look with-    `pandoc --print-default-data-file=templates/styles.html`).-    Unless you use [`--css`](#option--css), this variable-    is set to `true` by default. You can disable it with-    e.g. `pandoc -M document-css=false`.--`mainfont`-:   sets the CSS `font-family` property on the `html` element.--`fontsize`-:   sets the base CSS `font-size`, which you'd usually set-    to e.g. `20px`, but it also accepts `pt`-    (12pt = 16px in most browsers).--`fontcolor`-:   sets the CSS `color` property on the `html` element.--`linkcolor`-:   sets the CSS `color` property on all links.--`monofont`-:   sets the CSS `font-family` property on `code` elements.--`monobackgroundcolor`-:   sets the CSS `background-color` property on `code` elements-    and adds extra padding.--`linestretch`-:   sets the CSS `line-height` property on the `html` element,-    which is preferred to be unitless.--`maxwidth`-:   sets the CSS `max-width` property (default is 32em).--`backgroundcolor`-:   sets the CSS `background-color` property on the `html` element.--`margin-left`, `margin-right`, `margin-top`, `margin-bottom`-:   sets the corresponding CSS `padding` properties on the `body` element.--To override or extend some [CSS] for just one document, include for example:--    ----    header-includes: |-      <style>-      blockquote {-        font-style: italic;-      }-      tr.even {-        background-color: #f0f0f0;-      }-      td, th {-        padding: 0.5em 2em 0.5em 0.5em;-      }-      tbody {-        border-bottom: none;-      }-      </style>-    -----[CSS]: https://developer.mozilla.org/en-US/docs/Learn/CSS--### Variables for HTML math--`classoption`-:   when using [KaTeX](#option--katex), you can render display-math equations flush left using [YAML metadata](#layout) or with-`-M classoption=fleqn`.--### Variables for HTML slides--These affect HTML output when [producing slide shows with-pandoc](#slide-shows).--`institute`-:   author affiliations: can be a list when there are multiple authors--`revealjs-url`-:   base URL for reveal.js documents (defaults to-    `https://unpkg.com/reveal.js@^4/`)--`s5-url`-:   base URL for S5 documents (defaults to `s5/default`)--`slidy-url`-:   base URL for Slidy documents (defaults to-    `https://www.w3.org/Talks/Tools/Slidy2`)--`slideous-url`-:   base URL for Slideous documents (defaults to `slideous`)--`title-slide-attributes`-:   additional attributes for the title slide of reveal.js slide shows.-    See [background in reveal.js, beamer, and pptx] for an example.--All [reveal.js configuration options] are available as variables.-To turn off boolean flags that default to true in reveal.js, use `0`.--[reveal.js configuration options]: https://revealjs.com/config/--### Variables for Beamer slides--These variables change the appearance of PDF slides using [`beamer`].--`aspectratio`-:   slide aspect ratio (`43` for 4:3 [default], `169` for 16:9,-    `1610` for 16:10, `149` for 14:9, `141` for 1.41:1, `54` for 5:4,-    `32` for 3:2)--`beameroption`-:   add extra beamer option with `\setbeameroption{}`--`institute`-:   author affiliations: can be a list when there are multiple authors--`logo`-:   logo image for slides--`navigation`-:   controls navigation symbols (default is `empty` for no navigation-    symbols; other valid values are `frame`, `vertical`, and `horizontal`)--`section-titles`-:   enables "title pages" for new sections (default is true)--`theme`, `colortheme`, `fonttheme`, `innertheme`, `outertheme`-:   beamer themes--`themeoptions`-:   options for LaTeX beamer themes (a list).--`titlegraphic`-:   image for title slide--### Variables for PowerPoint--These variables control the visual aspects of a slide show that-are not easily controlled via templates.--`monofont`-:   font to use for code.--### Variables for LaTeX--Pandoc uses these variables when [creating a PDF] with a LaTeX engine.--#### Layout--`block-headings`-:   make `\paragraph` and `\subparagraph` (fourth- and-    fifth-level headings, or fifth- and sixth-level with book-    classes) free-standing rather than run-in; requires further-    formatting to distinguish from `\subsubsection` (third- or-    fourth-level headings). Instead of using this option,-    [KOMA-Script] can adjust headings more extensively:--        ----        documentclass: scrartcl-        header-includes: |-          \RedeclareSectionCommand[-            beforeskip=-10pt plus -2pt minus -1pt,-            afterskip=1sp plus -1sp minus 1sp,-            font=\normalfont\itshape]{paragraph}-          \RedeclareSectionCommand[-            beforeskip=-10pt plus -2pt minus -1pt,-            afterskip=1sp plus -1sp minus 1sp,-            font=\normalfont\scshape,-            indent=0pt]{subparagraph}-        ...--`classoption`-:   option for document class, e.g. `oneside`; repeat for multiple options:--        ----        classoption:-        - twocolumn-        - landscape-        ...--`documentclass`-:   document class: usually one of the standard classes,-    [`article`], [`book`], and [`report`]; the [KOMA-Script]-    equivalents, `scrartcl`, `scrbook`, and `scrreprt`, which-    default to smaller margins; or [`memoir`]--`geometry`-:   option for [`geometry`] package, e.g. `margin=1in`;-    repeat for multiple options:--        ----        geometry:-        - top=30mm-        - left=20mm-        - heightrounded-        ...--`hyperrefoptions`-:   option for [`hyperref`] package, e.g. `linktoc=all`;-    repeat for multiple options:--        ----        hyperrefoptions:-        - linktoc=all-        - pdfwindowui-        - pdfpagemode=FullScreen-        ...--`indent`-:   if true, pandoc will use document class settings for-    indentation (the default LaTeX template otherwise removes-    indentation and adds space between paragraphs)--`linestretch`-:   adjusts line spacing using the [`setspace`]-    package, e.g. `1.25`, `1.5`--`margin-left`, `margin-right`, `margin-top`, `margin-bottom`-:   sets margins if `geometry` is not used (otherwise `geometry`-    overrides these)--`pagestyle`-:   control `\pagestyle{}`: the default article class-    supports `plain` (default), `empty` (no running heads or page numbers),-    and `headings` (section titles in running heads)--`papersize`-:   paper size, e.g. `letter`, `a4`--`secnumdepth`-:   numbering depth for sections (with `--number-sections` option-    or `numbersections` variable)--`beamerarticle`-:   produce an article from Beamer slides--#### Fonts--`fontenc`-:   allows font encoding to be specified through `fontenc` package (with-    `pdflatex`); default is `T1` (see [LaTeX font encodings guide])--`fontfamily`-:   font package for use with `pdflatex`:-    [TeX Live] includes many options, documented in the [LaTeX Font Catalogue].-    The default is [Latin Modern][`lm`].--`fontfamilyoptions`-:   options for package used as `fontfamily`; repeat for multiple options.-    For example, to use the Libertine font with proportional lowercase-    (old-style) figures through the [`libertinus`] package:--        ----        fontfamily: libertinus-        fontfamilyoptions:-        - osf-        - p-        ...--`fontsize`-:   font size for body text. The standard classes allow 10pt, 11pt, and-    12pt.  To use another size, set `documentclass` to one of-    the [KOMA-Script] classes, such as `scrartcl` or `scrbook`.--`mainfont`, `sansfont`, `monofont`, `mathfont`, `CJKmainfont`, `CJKsansfont`, `CJKmonofont`-:   font families for use with `xelatex` or-    `lualatex`: take the name of any system font, using the-    [`fontspec`] package.  `CJKmainfont` uses the [`xecjk`] package.--`mainfontoptions`, `sansfontoptions`, `monofontoptions`, `mathfontoptions`, `CJKoptions`-:   options to use with `mainfont`, `sansfont`, `monofont`, `mathfont`,-    `CJKmainfont` in `xelatex` and `lualatex`.  Allow for any-    choices available through [`fontspec`]; repeat for multiple-    options. For example, to use the [TeX Gyre] version of-    Palatino with lowercase figures:--        ----        mainfont: TeX Gyre Pagella-        mainfontoptions:-        - Numbers=Lowercase-        - Numbers=Proportional-        ...--`mainfontfallback`, `sansfontfallback`, `monofontfallback`-:   fonts to try if a glyph isn't found in `mainfont`, `sansfont`, or `monofont`-    respectively. These are lists. The font name must be followed by a colon-    and optionally a set of options, for example:--        ----        mainfontfallback:-          - "FreeSans:"-          - "NotoColorEmoji:mode=harf"-        ...--    Font fallbacks currently only work with `lualatex`.--`babelfonts`-:    a map of Babel language names (e.g. `chinese`) to the font-     to be used with the language:--     ----     babelfonts:-       chinese-hant: "Noto Serif CJK TC"-       russian: "Noto Serif"-     ...--`microtypeoptions`-:    options to pass to the microtype package--#### Links--`colorlinks`-:   add color to link text; automatically enabled if any of-    `linkcolor`, `filecolor`, `citecolor`, `urlcolor`, or `toccolor` are set--`boxlinks`-:   add visible box around links (has no effect if `colorlinks` is set)--`linkcolor`, `filecolor`, `citecolor`, `urlcolor`, `toccolor`-:   color for internal links, external links, citation links, linked-    URLs, and links in table of contents, respectively: uses options-    allowed by [`xcolor`], including the `dvipsnames`, `svgnames`, and-    `x11names` lists--`links-as-notes`-:   causes links to be printed as footnotes--`urlstyle`-:   style for URLs (e.g., `tt`, `rm`, `sf`, and, the default, `same`)--#### Front matter--`lof`, `lot`-:   include list of figures, list of tables--`thanks`-:   contents of acknowledgments footnote after document title--`toc`-:   include table of contents (can also be set using-    `--toc/--table-of-contents`)--`toc-depth`-:   level of section to include in table of contents--#### BibLaTeX Bibliographies--These variables function when using BibLaTeX for [citation rendering].--`biblatexoptions`-:   list of options for biblatex--`biblio-style`-:   bibliography style, when used with `--natbib` and `--biblatex`--`biblio-title`-:   bibliography title, when used with `--natbib` and `--biblatex`--`bibliography`-:   bibliography to use for resolving references--`natbiboptions`-:   list of options for natbib--[KOMA-Script]: https://ctan.org/pkg/koma-script-[LaTeX Font Catalogue]: https://tug.org/FontCatalogue/-[LaTeX font encodings guide]: https://ctan.org/pkg/encguide-[TeX Gyre]: http://www.gust.org.pl/projects/e-foundry/tex-gyre-[`article`]: https://ctan.org/pkg/article-[`book`]: https://ctan.org/pkg/book-[`libertinus`]: https://ctan.org/pkg/libertinus-[`memoir`]: https://ctan.org/pkg/memoir-[`report`]: https://ctan.org/pkg/report--### Variables for ConTeXt--Pandoc uses these variables when [creating a PDF] with ConTeXt.--`fontsize`-:   font size for body text (e.g. `10pt`, `12pt`)--`headertext`, `footertext`-:   text to be placed in running header or footer (see [ConTeXt Headers and-    Footers]); repeat up to four times for different placement--`indenting`-:   controls indentation of paragraphs, e.g. `yes,small,next` (see-    [ConTeXt Indentation]); repeat for multiple options--`interlinespace`-:   adjusts line spacing, e.g. `4ex` (using [`setupinterlinespace`]);-    repeat for multiple options--`layout`-:   options for page margins and text arrangement (see [ConTeXt Layout]);-    repeat for multiple options--`linkcolor`, `contrastcolor`-:   color for links outside and inside a page, e.g. `red`, `blue` (see-    [ConTeXt Color])--`linkstyle`-:   typeface style for links, e.g. `normal`, `bold`, `slanted`, `boldslanted`,-    `type`, `cap`, `small`--`lof`, `lot`-:   include list of figures, list of tables--`mainfont`, `sansfont`, `monofont`, `mathfont`-:   font families: take the name of any system font (see-    [ConTeXt Font Switching])--`mainfontfallback`, `sansfontfallback`, `monofontfallback`-:   list of fonts to try, in order, if a glyph is not found in the-    main font. Use `\definefallbackfamily`-compatible font name syntax.-    Emoji fonts are unsupported.--`margin-left`, `margin-right`, `margin-top`, `margin-bottom`-:   sets margins, if `layout` is not used (otherwise `layout`-    overrides these)--`pagenumbering`-:   page number style and location (using [`setuppagenumbering`]);-    repeat for multiple options--`papersize`-:   paper size, e.g. `letter`, `A4`, `landscape` (see [ConTeXt Paper Setup]);-    repeat for multiple options--`pdfa`-:   adds to the preamble the setup necessary to generate PDF/A-    of the type specified, e.g. `1a:2005`, `2a`. If no type is-    specified (i.e. the value is set to True, by e.g.-    `--metadata=pdfa` or `pdfa: true` in a YAML metadata block),-    `1b:2005` will be used as default, for reasons of backwards-    compatibility. Using `--variable=pdfa` without specified value-    is not supported.  To successfully generate PDF/A the required-    ICC color profiles have to be available and the content and all-    included files (such as images) have to be standard-conforming.-    The ICC profiles and output intent may be specified using the-    variables `pdfaiccprofile` and `pdfaintent`.  See also [ConTeXt-    PDFA] for more details.--`pdfaiccprofile`-:   when used in conjunction with `pdfa`, specifies the ICC profile to use-    in the PDF, e.g. `default.cmyk`. If left unspecified, `sRGB.icc` is-    used as default. May be repeated to include multiple profiles. Note that-    the profiles have to be available on the system. They can be obtained-    from [ConTeXt ICC Profiles].--`pdfaintent`-:   when used in conjunction with `pdfa`, specifies the output intent for-    the colors, e.g. `ISO coated v2 300\letterpercent\space (ECI)`-    If left unspecified, `sRGB IEC61966-2.1` is used as default.--`toc`-:   include table of contents (can also be set using-    `--toc/--table-of-contents`)--`urlstyle`-:   typeface style for links without link text, e.g. `normal`, `bold`, `slanted`, `boldslanted`,-    `type`, `cap`, `small`--`whitespace`-:   spacing between paragraphs, e.g. `none`, `small` (using-    [`setupwhitespace`])--`includesource`-:   include all source documents as file attachments in the PDF file--[ConTeXt Paper Setup]: https://wiki.contextgarden.net/PaperSetup-[ConTeXt Layout]: https://wiki.contextgarden.net/Layout-[ConTeXt Font Switching]: https://wiki.contextgarden.net/Font_Switching-[ConTeXt Color]: https://wiki.contextgarden.net/Color-[ConTeXt Headers and Footers]: https://wiki.contextgarden.net/Headers_and_Footers-[ConTeXt Indentation]: https://wiki.contextgarden.net/Indentation-[ConTeXt ICC Profiles]: https://wiki.contextgarden.net/PDFX#ICC_profiles-[ConTeXt PDFA]: https://wiki.contextgarden.net/PDF/A-[`setupwhitespace`]: https://wiki.contextgarden.net/Command/setupwhitespace-[`setupinterlinespace`]: https://wiki.contextgarden.net/Command/setupinterlinespace-[`setuppagenumbering`]: https://wiki.contextgarden.net/Command/setuppagenumbering--### Variables for `wkhtmltopdf`--Pandoc uses these variables when [creating a PDF] with [`wkhtmltopdf`].-The `--css` option also affects the output.--`footer-html`, `header-html`-:   add information to the header and footer--`margin-left`, `margin-right`, `margin-top`, `margin-bottom`-:   set the page margins--`papersize`-:   sets the PDF paper size--### Variables for man pages--`adjusting`-:   adjusts text to left (`l`), right (`r`), center (`c`),-    or both (`b`) margins--`footer`-:   footer in man pages--`header`-:   header in man pages--`section`-:   section number in man pages--### Variables for Typst--`margin`-:   A dictionary with the fields defined in the Typst documentation:-    `x`, `y`, `top`, `bottom`, `left`, `right`.--`papersize`-:    Paper size: `a4`, `us-letter`, etc.--`mainfont`-:    Name of system font to use for the main font.--`fontsize`-:    Font size (e.g., `12pt`).--`section-numbering`-:    Schema to use for numbering sections, e.g. `1.A.1`.--`columns`-:    Number of columns for body text.--### Variables for ms--`fontfamily`-:   `A` (Avant Garde), `B` (Bookman), `C` (Helvetica), `HN`-    (Helvetica Narrow), `P` (Palatino), or `T` (Times New Roman).-    This setting does not affect source code, which is always-    displayed using monospace Courier. These built-in fonts are-    limited in their coverage of characters. Additional fonts may-    be installed using the script [`install-font.sh`] provided-    by Peter Schaffter and documented in detail on [his web-    site][ms-font-steps].--`indent`-:   paragraph indent (e.g. `2m`)--`lineheight`-:   line height (e.g. `12p`)--`pointsize`-:   point size (e.g. `10p`)--[`install-font.sh`]: https://www.schaffter.ca/mom/bin/install-font.sh-[ms-font-steps]: https://www.schaffter.ca/mom/momdoc/appendices.html#steps--### Variables set automatically--Pandoc sets these variables automatically in response to [options] or-document contents; users can also modify them. These vary depending-on the output format, and include the following:--`body`-:   body of document--`date-meta`-:   the `date` variable converted to ISO 8601 YYYY-MM-DD,-    included in all HTML based formats (dzslides, epub,-    html, html4, html5, revealjs, s5, slideous, slidy).-    The recognized formats for `date` are: `mm/dd/yyyy`,-    `mm/dd/yy`, `yyyy-mm-dd` (ISO 8601), `dd MM yyyy`-    (e.g. either `02 Apr 2018` or `02 April 2018`),-    `MM dd, yyyy` (e.g. `Apr. 02, 2018` or `April 02, 2018),-    `yyyy[mm[dd]]` (e.g. `20180402, `201804` or `2018`).--`header-includes`-:   contents specified by `-H/--include-in-header` (may have multiple-    values)--`include-before`-:   contents specified by `-B/--include-before-body` (may have-    multiple values)--`include-after`-:   contents specified by `-A/--include-after-body` (may have-    multiple values)--`meta-json`-:   JSON representation of all of the document's metadata. Field-    values are transformed to the selected output format.--`numbersections`-:   non-null value if `-N/--number-sections` was specified--`sourcefile`, `outputfile`-:   source and destination filenames, as given on the command line.-    `sourcefile` can also be a list if input comes from multiple files,-    or empty if input is from stdin. You can use the following snippet in-    your template to distinguish them:--        $if(sourcefile)$-        $for(sourcefile)$-        $sourcefile$-        $endfor$-        $else$-        (stdin)-        $endif$--    Similarly, `outputfile` can be `-` if output goes to the terminal.--    If you need absolute paths, use e.g. `$curdir$/$sourcefile$`.--`curdir`-:   working directory from which pandoc is run.--`pandoc-version`-:   pandoc version.--`toc`-:   non-null value if `--toc/--table-of-contents` was specified--`toc-title`-:   title of table of contents (works only with EPUB,-    HTML, revealjs, opendocument, odt, docx, pptx, beamer, LaTeX)--[pandoc-templates]: https://github.com/jgm/pandoc-templates--# Extensions--The behavior of some of the readers and writers can be adjusted by-enabling or disabling various extensions.--An extension can be enabled by adding `+EXTENSION`-to the format name and disabled by adding `-EXTENSION`. For example,-`--from markdown_strict+footnotes` is strict Markdown with footnotes-enabled, while `--from markdown-footnotes-pipe_tables` is pandoc's-Markdown without footnotes or pipe tables.--The Markdown reader and writer make by far the most use of extensions.-Extensions only used by them are therefore covered in the-section [Pandoc's Markdown] below (see [Markdown variants] for-`commonmark` and `gfm`). In the following, extensions that also work-for other formats are covered.--Note that Markdown extensions added to the `ipynb` format-affect Markdown cells in Jupyter notebooks (as do command-line-options like `--markdown-headings`).--## Typography--#### Extension: `smart` ####--Interpret straight quotes as curly quotes, `---` as em-dashes,-`--` as en-dashes, and `...` as ellipses. Nonbreaking spaces are-inserted after certain abbreviations, such as "Mr."--This extension can be enabled/disabled for the following formats:--input formats-:  `markdown`, `commonmark`, `latex`, `mediawiki`, `org`, `rst`, `twiki`,-   `html`--output formats-:  `markdown`, `latex`, `context`, `rst`--enabled by default in-:  `markdown`, `latex`, `context` (both input and output)--Note: If you are *writing* Markdown, then the `smart` extension-has the reverse effect: what would have been curly quotes comes-out straight.--In LaTeX, `smart` means to use the standard TeX ligatures-for quotation marks (` `` ` and ` '' ` for double quotes,-`` ` `` and `` ' `` for single quotes) and dashes (`--` for-en-dash and `---` for em-dash).  If `smart` is disabled,-then in reading LaTeX pandoc will parse these characters-literally.  In writing LaTeX, enabling `smart` tells pandoc-to use the ligatures when possible; if `smart` is disabled-pandoc will use unicode quotation mark and dash characters.--## Headings and sections--#### Extension: `auto_identifiers` ####--A heading without an explicitly specified identifier will be-automatically assigned a unique identifier based on the heading text.--This extension can be enabled/disabled for the following formats:--input formats-:  `markdown`, `latex`, `rst`, `mediawiki`, `textile`--output formats-:  `markdown`, `muse`--enabled by default in-:  `markdown`, `muse`--The default algorithm used to derive the identifier from the-heading text is:--  - Remove all formatting, links, etc.-  - Remove all footnotes.-  - Remove all non-alphanumeric characters,-    except underscores, hyphens, and periods.-  - Replace all spaces and newlines with hyphens.-  - Convert all alphabetic characters to lowercase.-  - Remove everything up to the first letter (identifiers may-    not begin with a number or punctuation mark).-  - If nothing is left after this, use the identifier `section`.--Thus, for example,--  Heading                           Identifier-  -------------------------------   -----------------------------  `Heading identifiers in HTML`     `heading-identifiers-in-html`-  `Maître d'hôtel`                  `maître-dhôtel`-  `*Dogs*?--in *my* house?`         `dogs--in-my-house`-  `[HTML], [S5], or [RTF]?`         `html-s5-or-rtf`-  `3. Applications`                 `applications`-  `33`                              `section`--These rules should, in most cases, allow one to determine the identifier-from the heading text. The exception is when several headings have the-same text; in this case, the first will get an identifier as described-above; the second will get the same identifier with `-1` appended; the-third with `-2`; and so on.--(However, a different algorithm is used if-`gfm_auto_identifiers` is enabled; see below.)--These identifiers are used to provide link targets in the table of-contents generated by the `--toc|--table-of-contents` option. They-also make it easy to provide links from one section of a document to-another. A link to this section, for example, might look like this:--    See the section on-    [heading identifiers](#heading-identifiers-in-html-latex-and-context).--Note, however, that this method of providing links to sections works-only in HTML, LaTeX, and ConTeXt formats.--If the `--section-divs` option is specified, then each section will-be wrapped in a `section` (or a `div`, if `html4` was specified),-and the identifier will be attached to the enclosing `<section>`-(or `<div>`) tag rather than the heading itself. This allows entire-sections to be manipulated using JavaScript or treated differently in-CSS.--#### Extension: `ascii_identifiers` ####--Causes the identifiers produced by `auto_identifiers` to be pure ASCII.-Accents are stripped off of accented Latin letters, and non-Latin-letters are omitted.--#### Extension: `gfm_auto_identifiers` ####--Changes the algorithm used by `auto_identifiers` to conform to-GitHub's method.  Spaces are converted to dashes (`-`),-uppercase characters to lowercase characters, and punctuation-characters other than `-` and `_` are removed.-Emojis are replaced by their names.--## Math Input--The extensions [`tex_math_dollars`](#extension-tex_math_dollars),-[`tex_math_gfm`](#extension-tex_math_gfm),-[`tex_math_single_backslash`](#extension-tex_math_single_backslash), and-[`tex_math_double_backslash`](#extension-tex_math_double_backslash)-are described in the section about Pandoc's Markdown.--However, they can also be used with HTML input. This is handy for-reading web pages formatted using MathJax, for example.--## Raw HTML/TeX--The following extensions are described in more detail in-their respective sections of [Pandoc's Markdown]:--- [`raw_html`](#extension-raw_html) allows HTML elements which-  are not representable in pandoc's AST to be parsed as raw HTML.-  By default, this is disabled for HTML input.--- [`raw_tex`](#extension-raw_tex) allows raw LaTeX, TeX, and ConTeXt-  to be included in a document.  This extension can be enabled/disabled-  for the following formats (in addition to `markdown`):--  input formats-  :  `latex`, `textile`, `html` (environments, `\ref`, and-     `\eqref` only), `ipynb`--  output formats-  :  `textile`, `commonmark`--  Note: as applied to `ipynb`, `raw_html` and `raw_tex` affect not-  only raw TeX in Markdown cells, but data with mime type-  `text/html` in output cells.  Since the `ipynb` reader attempts-  to preserve the richest possible outputs when several options-  are given, you will get best results if you disable `raw_html`-  and `raw_tex` when converting to formats like `docx` which don't-  allow raw `html` or `tex`.--- [`native_divs`](#extension-native_divs) causes HTML `div`-  elements to be parsed as native pandoc Div blocks.-  If you want them to be parsed as raw HTML, use-  `-f html-native_divs+raw_html`.--- [`native_spans`](#extension-native_spans) causes HTML `span`-  elements to be parsed as native pandoc Span inlines.-  If you want them to be parsed as raw HTML, use-  `-f html-native_spans+raw_html`.  If you want to drop all-  `div`s and `span`s when converting HTML to Markdown, you-  can use `pandoc -f html-native_divs-native_spans -t markdown`.--## Literate Haskell support--#### Extension: `literate_haskell` ####--Treat the document as literate Haskell source.--This extension can be enabled/disabled for the following formats:--input formats-:  `markdown`, `rst`, `latex`--output formats-:  `markdown`, `rst`, `latex`, `html`--If you append `+lhs` (or `+literate_haskell`) to one of the formats-above, pandoc will treat the document as literate Haskell source.-This means that--  - In Markdown input, "bird track" sections will be parsed as Haskell-    code rather than block quotations.  Text between `\begin{code}`-    and `\end{code}` will also be treated as Haskell code.  For-    ATX-style headings the character '=' will be used instead of '#'.--  - In Markdown output, code blocks with classes `haskell` and `literate`-    will be rendered using bird tracks, and block quotations will be-    indented one space, so they will not be treated as Haskell code.-    In addition, headings will be rendered setext-style (with underlines)-    rather than ATX-style (with '#' characters). (This is because ghc-    treats '#' characters in column 1 as introducing line numbers.)--  - In restructured text input, "bird track" sections will be parsed-    as Haskell code.--  - In restructured text output, code blocks with class `haskell` will-    be rendered using bird tracks.--  - In LaTeX input, text in `code` environments will be parsed as-    Haskell code.--  - In LaTeX output, code blocks with class `haskell` will be rendered-    inside `code` environments.--  - In HTML output, code blocks with class `haskell` will be rendered-    with class `literatehaskell` and bird tracks.--Examples:--    pandoc -f markdown+lhs -t html--reads literate Haskell source formatted with Markdown conventions and writes-ordinary HTML (without bird tracks).--    pandoc -f markdown+lhs -t html+lhs--writes HTML with the Haskell code in bird tracks, so it can be copied-and pasted as literate Haskell source.--Note that GHC expects the bird tracks in the first column, so indented-literate code blocks (e.g. inside an itemized environment) will not be-picked up by the Haskell compiler.--## Other extensions--#### Extension: `empty_paragraphs` ####--Allows empty paragraphs.  By default empty paragraphs are-omitted.--This extension can be enabled/disabled for the following formats:--input formats-:  `docx`, `html`--output formats-:  `docx`, `odt`, `opendocument`, `html`, `latex`--#### Extension: `native_numbering` ####--Enables native numbering of figures and tables. Enumeration-starts at 1.--This extension can be enabled/disabled for the following formats:--output formats-:  `odt`, `opendocument`, `docx`--#### Extension: `xrefs_name` ####--Links to headings, figures and tables inside the document are-substituted with cross-references that will use the name or caption-of the referenced item. The original link text is replaced once-the generated document is refreshed. This extension can be combined-with `xrefs_number` in which case numbers will appear before the-name.--Text in cross-references is only made consistent with the referenced-item once the document has been refreshed.--This extension can be enabled/disabled for the following formats:--output formats-:  `odt`, `opendocument`--#### Extension: `xrefs_number` ####--Links to headings, figures and tables inside the document are-substituted with cross-references that will use the number-of the referenced item. The original link text is discarded.-This extension can be combined with `xrefs_name` in which case-the name or caption numbers will appear after the number.--For the `xrefs_number` to be useful heading numbers must be enabled-in the generated document, also table and figure captions must be enabled-using for example the `native_numbering` extension.--Numbers in cross-references are only visible in the final document once-it has been refreshed.--This extension can be enabled/disabled for the following formats:--output formats-:  `odt`, `opendocument`--#### Extension: `styles` #### {#ext-styles}--When converting from docx, read all docx styles as divs (for-paragraph styles) and spans (for character styles) regardless-of whether pandoc understands the meaning of these styles.-This can be used with [docx custom styles](#custom-styles).-Disabled by default.--input formats-:  `docx`--#### Extension: `amuse` ####--In the `muse` input format, this enables Text::Amuse-extensions to Emacs Muse markup.--#### Extension: `raw_markdown` ####--In the `ipynb` input format, this causes Markdown cells-to be included as raw Markdown blocks (allowing lossless-round-tripping) rather than being parsed.  Use this only-when you are targeting `ipynb` or a Markdown-based-output format.--#### Extension: `citations` {#org-citations}--When the `citations` extension is enabled in `org`,-org-cite and org-ref style citations will be parsed as-native pandoc citations.--  [org-cite]: https://orgmode.org/manual/Citations.html-  [org-ref]:  https://github.com/jkitchin/org-ref--When `citations` is enabled in `docx`, citations inserted-by Zotero or Mendeley or EndNote plugins will be parsed as native-pandoc citations.  (Otherwise, the formatted citations generated-by the bibliographic software will be parsed as regular text.)--#### Extension: `fancy_lists` {#org-fancy-lists}--Some aspects of [Pandoc's Markdown fancy lists](#extension-fancy_lists) are also-accepted in `org` input, mimicking the option `org-list-allow-alphabetical` in-Emacs. As in Org Mode, enabling this extension allows lowercase and uppercase-alphabetical markers for ordered lists to be parsed in addition to arabic ones.-Note that for Org, this does not include roman numerals or the `#` placeholder-that are enabled by the extension in Pandoc's Markdown.--#### Extension: `element_citations` ####--In the `jats` output formats, this causes reference items to-be replaced with `<element-citation>` elements. These-elements are not influenced by CSL styles, but all information-on the item is included in tags.--#### Extension: `ntb` ####--In the `context` output format this enables the use of [Natural Tables-(TABLE)](https://wiki.contextgarden.net/TABLE) instead of the default-[Extreme Tables (xtables)](https://wiki.contextgarden.net/xtables).-Natural tables allow more fine-grained global customization but come-at a performance penalty compared to extreme tables.--#### Extension: `tagging` ####--Enabling this extension with `context` output will produce markup-suitable for the production of tagged PDFs. This includes-additional markers for paragraphs and alternative markup for-emphasized text. The `emphasis-command` template variable is set-if the extension is enabled.---# Pandoc's Markdown--Pandoc understands an extended and slightly revised version of-John Gruber's [Markdown] syntax.  This document explains the syntax,-noting differences from original Markdown. Except where noted, these-differences can be suppressed by using the `markdown_strict` format instead-of `markdown`. Extensions can be enabled or disabled to specify the-behavior more granularly. They are described in the following. See also-[Extensions] above, for extensions that work also on other formats.--## Philosophy--Markdown is designed to be easy to write, and, even more importantly,-easy to read:--> A Markdown-formatted document should be publishable as-is, as plain-> text, without looking like it's been marked up with tags or formatting-> instructions.-> -- [John Gruber](https://daringfireball.net/projects/markdown/syntax#philosophy)--This principle has guided pandoc's decisions in finding syntax for-tables, footnotes, and other extensions.--There is, however, one respect in which pandoc's aims are different-from the original aims of Markdown.  Whereas Markdown was originally-designed with HTML generation in mind, pandoc is designed for multiple-output formats.  Thus, while pandoc allows the embedding of raw HTML,-it discourages it, and provides other, non-HTMLish ways of representing-important document elements like definition lists, tables, mathematics, and-footnotes.--## Paragraphs--A paragraph is one or more lines of text followed by one or more blank lines.-Newlines are treated as spaces, so you can reflow your paragraphs as you like.-If you need a hard line break, put two or more spaces at the end of a line.--#### Extension: `escaped_line_breaks` ####--A backslash followed by a newline is also a hard line break.-Note:  in multiline and grid table cells, this is the only way-to create a hard line break, since trailing spaces in the cells-are ignored.--## Headings--There are two kinds of headings: Setext and ATX.--### Setext-style headings ###--A setext-style heading is a line of text "underlined" with a row of `=` signs-(for a level-one heading) or `-` signs (for a level-two heading):--    A level-one heading-    ===================--    A level-two heading-    ---------------------The heading text can contain inline formatting, such as emphasis (see-[Inline formatting], below).---### ATX-style headings ###--An ATX-style heading consists of one to six `#` signs and a line of-text, optionally followed by any number of `#` signs.  The number of-`#` signs at the beginning of the line is the heading level:--    ## A level-two heading--    ### A level-three heading ###--As with setext-style headings, the heading text can contain formatting:--    # A level-one heading with a [link](/url) and *emphasis*--#### Extension: `blank_before_header` ####--Original Markdown syntax does not require a blank line before a heading.-Pandoc does require this (except, of course, at the beginning of the-document). The reason for the requirement is that it is all too easy for a-`#` to end up at the beginning of a line by accident (perhaps through line-wrapping). Consider, for example:--    I like several of their flavors of ice cream:-    #22, for example, and #5.--#### Extension: `space_in_atx_header` ####--Many Markdown implementations do not require a space between the-opening `#`s of an ATX heading and the heading text, so that-`#5 bolt` and `#hashtag` count as headings.  With this extension,-pandoc does require the space.--### Heading identifiers ###--See also the [`auto_identifiers`-extension](#extension-auto_identifiers) above.--#### Extension: `header_attributes` ####--Headings can be assigned attributes using this syntax at the end-of the line containing the heading text:--    {#identifier .class .class key=value key=value}--Thus, for example, the following headings will all be assigned the identifier-`foo`:--    # My heading {#foo}--    ## My heading ##    {#foo}--    My other heading   {#foo}-    -----------------(This syntax is compatible with [PHP Markdown Extra].)--Note that although this syntax allows assignment of classes and key/value-attributes, writers generally don't use all of this information.  Identifiers,-classes, and key/value attributes are used in HTML and HTML-based formats such-as EPUB and slidy.  Identifiers are used for labels and link anchors in the-LaTeX, ConTeXt, Textile, Jira markup, and AsciiDoc writers.--Headings with the class `unnumbered` will not be numbered, even if-`--number-sections` is specified.  A single hyphen (`-`) in an attribute-context is equivalent to `.unnumbered`, and preferable in non-English-documents.  So,--    # My heading {-}--is just the same as--    # My heading {.unnumbered}--If the `unlisted` class is present in addition to `unnumbered`,-the heading will not be included in a table of contents.-(Currently this feature is only implemented for certain-formats: those based on LaTeX and HTML, PowerPoint, and RTF.)--#### Extension: `implicit_header_references` ####--Pandoc behaves as if reference links have been defined for each heading.-So, to link to a heading--    # Heading identifiers in HTML--you can simply write--    [Heading identifiers in HTML]--or--    [Heading identifiers in HTML][]--or--    [the section on heading identifiers][heading identifiers in-    HTML]--instead of giving the identifier explicitly:--    [Heading identifiers in HTML](#heading-identifiers-in-html)--If there are multiple headings with identical text, the corresponding-reference will link to the first one only, and you will need to use explicit-links to link to the others, as described above.--Like regular reference links, these references are case-insensitive.--Explicit link reference definitions always take priority over-implicit heading references.  So, in the following example, the-link will point to `bar`, not to `#foo`:--    # Foo--    [foo]: bar--    See [foo]--## Block quotations--Markdown uses email conventions for quoting blocks of text.-A block quotation is one or more paragraphs or other block elements-(such as lists or headings), with each line preceded by a `>` character-and an optional space. (The `>` need not start at the left margin, but-it should not be indented more than three spaces.)--    > This is a block quote. This-    > paragraph has two lines.-    >-    > 1. This is a list inside a block quote.-    > 2. Second item.--A "lazy" form, which requires the `>` character only on the first-line of each block, is also allowed:--    > This is a block quote. This-    paragraph has two lines.--    > 1. This is a list inside a block quote.-    2. Second item.--Among the block elements that can be contained in a block quote are-other block quotes. That is, block quotes can be nested:--    > This is a block quote.-    >-    > > A block quote within a block quote.--If the `>` character is followed by an optional space, that space-will be considered part of the block quote marker and not part of-the indentation of the contents.  Thus, to put an indented code-block in a block quote, you need five spaces after the `>`:--    >     code--#### Extension: `blank_before_blockquote` ####--Original Markdown syntax does not require a blank line before a-block quote.  Pandoc does require this (except, of course, at-the beginning of the document). The reason for the requirement-is that it is all too easy for a `>` to end up at the beginning-of a line by accident (perhaps through line wrapping). So,-unless the `markdown_strict` format is used, the following does-not produce a nested block quote in pandoc:--    > This is a block quote.-    >> Not nested, since `blank_before_blockquote` is enabled by default---## Verbatim (code) blocks--### Indented code blocks ###--A block of text indented four spaces (or one tab) is treated as verbatim-text: that is, special characters do not trigger special formatting,-and all spaces and line breaks are preserved.  For example,--        if (a > 3) {-          moveShip(5 * gravity, DOWN);-        }--The initial (four space or one tab) indentation is not considered part-of the verbatim text, and is removed in the output.--Note: blank lines in the verbatim text need not begin with four spaces.---### Fenced code blocks ###--#### Extension: `fenced_code_blocks` ####--In addition to standard indented code blocks, pandoc supports-*fenced* code blocks.  These begin with a row of three or more-tildes (`~`) and end with a row of tildes that must be at least as long as-the starting row. Everything between these lines is treated as code. No-indentation is necessary:--    ~~~~~~~-    if (a > 3) {-      moveShip(5 * gravity, DOWN);-    }-    ~~~~~~~--Like regular code blocks, fenced code blocks must be separated-from surrounding text by blank lines.--If the code itself contains a row of tildes or backticks, just use a longer-row of tildes or backticks at the start and end:--    ~~~~~~~~~~~~~~~~-    ~~~~~~~~~~-    code including tildes-    ~~~~~~~~~~-    ~~~~~~~~~~~~~~~~--#### Extension: `backtick_code_blocks` ####--Same as `fenced_code_blocks`, but uses backticks (`` ` ``) instead of tildes-(`~`).--#### Extension: `fenced_code_attributes` ####--Optionally, you may attach attributes to fenced or backtick code block using-this syntax:--    ~~~~ {#mycode .haskell .numberLines startFrom="100"}-    qsort []     = []-    qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++-                   qsort (filter (>= x) xs)-    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--Here `mycode` is an identifier, `haskell` and `numberLines` are-classes, and `startFrom` is an attribute with value `100`. Some-output formats can use this information to do syntax-highlighting. Currently, the only output formats that use this-information are HTML, LaTeX, Docx, Ms, and PowerPoint. If-highlighting is supported for your output format and language,-then the code block above will appear highlighted, with numbered-lines. (To see which languages are supported, type `pandoc---list-highlight-languages`.) Otherwise, the code block above-will appear as follows:--    <pre id="mycode" class="haskell numberLines" startFrom="100">-      <code>-      ...-      </code>-    </pre>--The `numberLines` (or `number-lines`) class will cause the lines-of the code block to be numbered, starting with `1` or the value-of the `startFrom` attribute.  The `lineAnchors` (or-`line-anchors`) class will cause the lines to be clickable-anchors in HTML output.--A shortcut form can also be used for specifying the language of-the code block:--    ```haskell-    qsort [] = []-    ```--This is equivalent to:--    ``` {.haskell}-    qsort [] = []-    ```--This shortcut form may be combined with attributes:--    ```haskell {.numberLines}-    qsort [] = []-    ```--Which is equivalent to:--    ``` {.haskell .numberLines}-    qsort [] = []-    ```--If the `fenced_code_attributes` extension is disabled, but-input contains class attribute(s) for the code block, the first-class attribute will be printed after the opening fence as a bare-word.--To prevent all highlighting, use the `--no-highlight` flag.-To set the highlighting style, use `--highlight-style`.-For more information on highlighting, see [Syntax highlighting],-below.--## Line blocks--#### Extension: `line_blocks` ####--A line block is a sequence of lines beginning with a vertical bar (`|`)-followed by a space.  The division into lines will be preserved in-the output, as will any leading spaces; otherwise, the lines will-be formatted as Markdown.  This is useful for verse and addresses:--    | The limerick packs laughs anatomical-    | In space that is quite economical.-    |    But the good ones I've seen-    |    So seldom are clean-    | And the clean ones so seldom are comical--    | 200 Main St.-    | Berkeley, CA 94718--The lines can be hard-wrapped if needed, but the continuation-line must begin with a space.--    | The Right Honorable Most Venerable and Righteous Samuel L.-      Constable, Jr.-    | 200 Main St.-    | Berkeley, CA 94718--Inline formatting (such as emphasis) is allowed in the content-(though it can't cross line boundaries). Block-level formatting-(such as block quotes or lists) is not recognized.--This syntax is borrowed from [reStructuredText].--## Lists--### Bullet lists ###--A bullet list is a list of bulleted list items.  A bulleted list-item begins with a bullet (`*`, `+`, or `-`).  Here is a simple-example:--    * one-    * two-    * three--This will produce a "compact" list. If you want a "loose" list, in which-each item is formatted as a paragraph, put spaces between the items:--    * one--    * two--    * three--The bullets need not be flush with the left margin; they may be-indented one, two, or three spaces. The bullet must be followed-by whitespace.--List items look best if subsequent lines are flush with the first-line (after the bullet):--    * here is my first-      list item.-    * and my second.--But Markdown also allows a "lazy" format:--    * here is my first-    list item.-    * and my second.--### Block content in list items ###--A list item may contain multiple paragraphs and other block-level-content. However, subsequent paragraphs must be preceded by a blank line-and indented to line up with the first non-space content after-the list marker.--      * First paragraph.--        Continued.--      * Second paragraph. With a code block, which must be indented-        eight spaces:--            { code }--Exception: if the list marker is followed by an indented code-block, which must begin 5 spaces after the list marker, then-subsequent paragraphs must begin two columns after the last-character of the list marker:--    *     code--      continuation paragraph--List items may include other lists.  In this case the preceding blank-line is optional.  The nested list must be indented to line up with-the first non-space character after the list marker of the-containing list item.--    * fruits-      + apples-        - macintosh-        - red delicious-      + pears-      + peaches-    * vegetables-      + broccoli-      + chard--As noted above, Markdown allows you to write list items "lazily," instead of-indenting continuation lines. However, if there are multiple paragraphs or-other blocks in a list item, the first line of each must be indented.--    + A lazy, lazy, list-    item.--    + Another one; this looks-    bad but is legal.--        Second paragraph of second-    list item.--### Ordered lists ###--Ordered lists work just like bulleted lists, except that the items-begin with enumerators rather than bullets.--In original Markdown, enumerators are decimal numbers followed-by a period and a space.  The numbers themselves are ignored, so-there is no difference between this list:--    1.  one-    2.  two-    3.  three--and this one:--    5.  one-    7.  two-    1.  three--#### Extension: `fancy_lists` ####--Unlike original Markdown, pandoc allows ordered list items to be marked-with uppercase and lowercase letters and roman numerals, in addition to-Arabic numerals. List markers may be enclosed in parentheses or followed by a-single right-parenthesis or period. They must be separated from the-text that follows by at least one space, and, if the list marker is a-capital letter with a period, by at least two spaces.[^2]--[^2]:  The point of this rule is to ensure that normal paragraphs-    starting with people's initials, like--        B. Russell won a Nobel Prize (but not for "On Denoting").--    do not get treated as list items.--    This rule will not prevent--        (C) 2007 Joe Smith--    from being interpreted as a list item.  In this case, a backslash-    escape can be used:--        (C\) 2007 Joe Smith--The `fancy_lists` extension also allows '`#`' to be used as an-ordered list marker in place of a numeral:--    #. one-    #. two--Note:  the '`#`' ordered list marker doesn't work with `commonmark`.--#### Extension: `startnum` ####--Pandoc also pays attention to the type of list marker used, and to the-starting number, and both of these are preserved where possible in the-output format. Thus, the following yields a list with numbers followed-by a single parenthesis, starting with 9, and a sublist with lowercase-roman numerals:--     9)  Ninth-    10)  Tenth-    11)  Eleventh-           i. subone-          ii. subtwo-         iii. subthree--Pandoc will start a new list each time a different type of list-marker is used.  So, the following will create three lists:--    (2) Two-    (5) Three-    1.  Four-    *   Five--If default list markers are desired, use `#.`:--    #.  one-    #.  two-    #.  three--#### Extension: `task_lists` ####--Pandoc supports task lists, using the syntax of GitHub-Flavored Markdown.--    - [ ] an unchecked task list item-    - [x] checked item--### Definition lists ###--#### Extension: `definition_lists` ####--Pandoc supports definition lists, using the syntax of-[PHP Markdown Extra] with some extensions.[^3]--    Term 1--    :   Definition 1--    Term 2 with *inline markup*--    :   Definition 2--            { some code, part of Definition 2 }--        Third paragraph of definition 2.--Each term must fit on one line, which may optionally be followed by-a blank line, and must be followed by one or more definitions.-A definition begins with a colon or tilde, which may be indented one-or two spaces.--A term may have multiple definitions, and each definition may-consist of one or more block elements (paragraph, code block,-list, etc.), each indented four spaces or one tab stop.  The-body of the definition (not including the first line)-should be indented four spaces. However, as with-other Markdown lists, you can "lazily" omit indentation except-at the beginning of a paragraph or other block element:--    Term 1--    :   Definition-    with lazy continuation.--        Second paragraph of the definition.--If you leave space before the definition (as in the example above),-the text of the definition will be treated as a paragraph.  In some-output formats, this will mean greater spacing between term/definition-pairs. For a more compact definition list, omit the space before the-definition:--    Term 1-      ~ Definition 1--    Term 2-      ~ Definition 2a-      ~ Definition 2b--Note that space between items in a definition list is required.-(A variant that loosens this requirement, but disallows "lazy"-hard wrapping, can be activated with the [`compact_definition_lists`-extension][Extension: `compact_definition_lists`].)--[^3]:  I have been influenced by the suggestions of [David-  Wheeler](https://justatheory.com/2009/02/modest-markdown-proposal/).--### Numbered example lists ###--#### Extension: `example_lists` ####--The special list marker `@` can be used for sequentially numbered-examples. The first list item with a `@` marker will be numbered '1',-the next '2', and so on, throughout the document. The numbered examples-need not occur in a single list; each new list using `@` will take up-where the last stopped. So, for example:--    (@)  My first example will be numbered (1).-    (@)  My second example will be numbered (2).--    Explanation of examples.--    (@)  My third example will be numbered (3).--Numbered examples can be labeled and referred to elsewhere in the-document:--    (@good)  This is a good example.--    As (@good) illustrates, ...--The label can be any string of alphanumeric characters, underscores,-or hyphens.--Note:  continuation paragraphs in example lists must always-be indented four spaces, regardless of the length of the-list marker.  That is, example lists always behave as if the-`four_space_rule` extension is set.  This is because example-labels tend to be long, and indenting content to the-first non-space character after the label would be awkward.---### Ending a list ###--What if you want to put an indented code block after a list?--    -   item one-    -   item two--        { my code block }--Trouble! Here pandoc (like other Markdown implementations) will treat-`{ my code block }` as the second paragraph of item two, and not as-a code block.--To "cut off" the list after item two, you can insert some non-indented-content, like an HTML comment, which won't produce visible output in-any format:--    -   item one-    -   item two--    <!-- end of list -->--        { my code block }--You can use the same trick if you want two consecutive lists instead-of one big list:--    1.  one-    2.  two-    3.  three--    <!-- -->--    1.  uno-    2.  dos-    3.  tres--## Horizontal rules--A line containing a row of three or more `*`, `-`, or `_` characters-(optionally separated by spaces) produces a horizontal rule:--    *  *  *  *--    -----------------We strongly recommend that horizontal rules be separated from-surrounding text by blank lines.  If a horizontal rule is not-followed by a blank line, pandoc may try to interpret the-lines that follow as a YAML metadata block or a table.--## Tables--Four kinds of tables may be used. The first three kinds presuppose the use of-a fixed-width font, such as Courier. The fourth kind can be used with-proportionally spaced fonts, as it does not require lining up columns.--#### Extension: `table_captions` ####--A caption may optionally be provided with all 4 kinds of tables (as-illustrated in the examples below). A caption is a paragraph beginning-with the string `Table:` (or `table:` or just `:`), which will be stripped-off. It may appear either before or after the table.--#### Extension: `simple_tables` ####--Simple tables look like this:--      Right     Left     Center     Default-    -------     ------ ----------   --------         12     12        12            12-        123     123       123          123-          1     1          1             1--    Table:  Demonstration of simple table syntax.--The header and table rows must each fit on one line.  Column-alignments are determined by the position of the header text relative-to the dashed line below it:[^4]--  - If the dashed line is flush with the header text on the right side-    but extends beyond it on the left, the column is right-aligned.-  - If the dashed line is flush with the header text on the left side-    but extends beyond it on the right, the column is left-aligned.-  - If the dashed line extends beyond the header text on both sides,-    the column is centered.-  - If the dashed line is flush with the header text on both sides,-    the default alignment is used (in most cases, this will be left).--[^4]:  This scheme is due to Michel Fortin, who proposed it on the-       [Markdown discussion list](http://six.pairlist.net/pipermail/markdown-discuss/2005-March/001097.html).--The table must end with a blank line, or a line of dashes followed by-a blank line.--The column header row may be omitted, provided a dashed line is used-to end the table. For example:--    -------     ------ ----------   --------         12     12        12             12-        123     123       123           123-          1     1          1              1-    -------     ------ ----------   ---------When the header row is omitted, column alignments are determined on the basis-of the first line of the table body. So, in the tables above, the columns-would be right, left, center, and right aligned, respectively.--#### Extension: `multiline_tables` ####--Multiline tables allow header and table rows to span multiple lines-of text (but cells that span multiple columns or rows of the table are-not supported).  Here is an example:--    --------------------------------------------------------------     Centered   Default           Right Left-      Header    Aligned         Aligned Aligned-    ----------- ------- --------------- --------------------------       First    row                12.0 Example of a row that-                                        spans multiple lines.--      Second    row                 5.0 Here's another one. Note-                                        the blank line between-                                        rows.-    ---------------------------------------------------------------    Table: Here's the caption. It, too, may span-    multiple lines.--These work like simple tables, but with the following differences:--  - They must begin with a row of dashes, before the header text-    (unless the header row is omitted).-  - They must end with a row of dashes, then a blank line.-  - The rows must be separated by blank lines.--In multiline tables, the table parser pays attention to the widths of-the columns, and the writers try to reproduce these relative widths in-the output. So, if you find that one of the columns is too narrow in the-output, try widening it in the Markdown source.--The header may be omitted in multiline tables as well as simple tables:--    ----------- ------- --------------- --------------------------       First    row                12.0 Example of a row that-                                        spans multiple lines.--      Second    row                 5.0 Here's another one. Note-                                        the blank line between-                                        rows.-    ----------- ------- --------------- ---------------------------    : Here's a multiline table without a header.--It is possible for a multiline table to have just one row, but the row-should be followed by a blank line (and then the row of dashes that ends-the table), or the table may be interpreted as a simple table.--#### Extension: `grid_tables` ####--Grid tables look like this:--    : Sample grid table.--    +---------------+---------------+--------------------+-    | Fruit         | Price         | Advantages         |-    +===============+===============+====================+-    | Bananas       | $1.34         | - built-in wrapper |-    |               |               | - bright color     |-    +---------------+---------------+--------------------+-    | Oranges       | $2.10         | - cures scurvy     |-    |               |               | - tasty            |-    +---------------+---------------+--------------------+--The row of `=`s separates the header from the table body,-and can be omitted for a headerless table. The cells of grid-tables may contain arbitrary block elements (multiple-paragraphs, code blocks, lists, etc.).--Cells can span multiple columns or rows:--    +---------------------+----------+-    | Property            | Earth    |-    +=============+=======+==========+-    |             | min   | -89.2 °C |-    | Temperature +-------+----------+-    | 1961-1990   | mean  | 14 °C    |-    |             +-------+----------+-    |             | max   | 56.7 °C  |-    +-------------+-------+----------+--A table header may contain more than one row:--    +---------------------+-----------------------+-    | Location            | Temperature 1961-1990 |-    |                     | in degree Celsius     |-    |                     +-------+-------+-------+-    |                     | min   | mean  | max   |-    +=====================+=======+=======+=======+-    | Antarctica          | -89.2 | N/A   | 19.8  |-    +---------------------+-------+-------+-------+-    | Earth               | -89.2 | 14    | 56.7  |-    +---------------------+-------+-------+-------+--Alignments can be specified as with pipe tables, by putting-colons at the boundaries of the separator line after the-header:--    +---------------+---------------+--------------------+-    | Right         | Left          | Centered           |-    +==============:+:==============+:==================:+-    | Bananas       | $1.34         | built-in wrapper   |-    +---------------+---------------+--------------------+--For headerless tables, the colons go on the top line instead:--    +--------------:+:--------------+:------------------:+-    | Right         | Left          | Centered           |-    +---------------+---------------+--------------------+--A table foot can be defined by enclosing it with separator lines-that use `=` instead of `-`:--     +---------------+---------------+-     | Fruit         | Price         |-     +===============+===============+-     | Bananas       | $1.34         |-     +---------------+---------------+-     | Oranges       | $2.10         |-     +===============+===============+-     | Sum           | $3.44         |-     +===============+===============+--The foot must always be placed at the very bottom of the table.--Grid tables can be created easily using Emacs' table-mode-(`M-x table-insert`).--#### Extension: `pipe_tables` ####--Pipe tables look like this:--    | Right | Left | Default | Center |-    |------:|:-----|---------|:------:|-    |   12  |  12  |    12   |    12  |-    |  123  |  123 |   123   |   123  |-    |    1  |    1 |     1   |     1  |--      : Demonstration of pipe table syntax.--The syntax is identical to [PHP Markdown Extra tables].  The beginning and-ending pipe characters are optional, but pipes are required between all-columns.  The colons indicate column alignment as shown.  The header-cannot be omitted.  To simulate a headerless table, include a header-with blank cells.--Since the pipes indicate column boundaries, columns need not be vertically-aligned, as they are in the above example.  So, this is a perfectly-legal (though ugly) pipe table:--    fruit| price-    -----|-----:-    apple|2.05-    pear|1.37-    orange|3.09--The cells of pipe tables cannot contain block elements like paragraphs-and lists, and cannot span multiple lines.  If any line of the-Markdown source is longer than the column width (see `--columns`),-then the table will take up the full text width and the cell-contents will wrap, with the relative cell widths determined by-the number of dashes in the line separating the table header-from the table body. (For example `---|-` would make the first column 3/4-and the second column 1/4 of the full text width.)-On the other hand, if no lines are wider than column width, then-cell contents will not be wrapped, and the cells will be sized-to their contents.--Note:  pandoc also recognizes pipe tables of the following-form, as can be produced by Emacs' orgtbl-mode:--    | One | Two   |-    |-----+-------|-    | my  | table |-    | is  | nice  |--The difference is that `+` is used instead of `|`. Other orgtbl features-are not supported. In particular, to get non-default column alignment,-you'll need to add colons as above.--[PHP Markdown Extra tables]: https://michelf.ca/projects/php-markdown/extra/#table--## Metadata blocks--#### Extension: `pandoc_title_block` ####--If the file begins with a title block--    % title-    % author(s) (separated by semicolons)-    % date--it will be parsed as bibliographic information, not regular text.  (It-will be used, for example, in the title of standalone LaTeX or HTML-output.)  The block may contain just a title, a title and an author,-or all three elements. If you want to include an author but no-title, or a title and a date but no author, you need a blank line:--```-%-% Author-```--```-% My title-%-% June 15, 2006-```--The title may occupy multiple lines, but continuation lines must-begin with leading space, thus:--```-% My title-  on multiple lines-```--If a document has multiple authors, the authors may be put on-separate lines with leading space, or separated by semicolons, or-both.  So, all of the following are equivalent:--```-% Author One-  Author Two-```--```-% Author One; Author Two-```--```-% Author One;-  Author Two-```--The date must fit on one line.--All three metadata fields may contain standard inline formatting-(italics, links, footnotes, etc.).--Title blocks will always be parsed, but they will affect the output only-when the `--standalone` (`-s`) option is chosen. In HTML output, titles-will appear twice: once in the document head -- this is the title that-will appear at the top of the window in a browser -- and once at the-beginning of the document body. The title in the document head can have-an optional prefix attached (`--title-prefix` or `-T` option). The title-in the body appears as an H1 element with class "title", so it can be-suppressed or reformatted with CSS. If a title prefix is specified with-`-T` and no title block appears in the document, the title prefix will-be used by itself as the HTML title.--The man page writer extracts a title, man page section number, and-other header and footer information from the title line. The title-is assumed to be the first word on the title line, which may optionally-end with a (single-digit) section number in parentheses. (There should-be no space between the title and the parentheses.)  Anything after-this is assumed to be additional footer and header text. A single pipe-character (`|`) should be used to separate the footer text from the header-text.  Thus,--    % PANDOC(1)--will yield a man page with the title `PANDOC` and section 1.--    % PANDOC(1) Pandoc User Manuals--will also have "Pandoc User Manuals" in the footer.--    % PANDOC(1) Pandoc User Manuals | Version 4.0--will also have "Version 4.0" in the header.--#### Extension: `yaml_metadata_block` ####--A [YAML] metadata block is a valid YAML object, delimited by a line of three-hyphens (`---`) at the top and a line of three hyphens (`---`) or three dots-(`...`) 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, because of the way pandoc concatenates input files-when several are provided, you may also keep the metadata in a-separate YAML file and pass it to pandoc as an argument, along-with your Markdown files:--    pandoc chap1.md chap2.md chap3.md metadata.yaml -s -o book.html--Just be sure that the YAML file begins with `---` and ends with `---` or-`...`. Alternatively, you can use the `--metadata-file` option. Using-that approach however, you cannot reference content (like footnotes)-from the main Markdown input document.--Metadata will be taken from the fields of the YAML object and added to any-existing document metadata.  Metadata can contain lists and objects (nested-arbitrarily), but all string scalars will be interpreted as Markdown.  Fields-with names ending in an underscore will be ignored by pandoc.  (They may be-given a role by external processors.)  Field names must not be-interpretable as YAML numbers or boolean values (so, for-example, `yes`, `True`, and `15` cannot be used as field names).--A document may contain multiple metadata blocks.  If two-metadata blocks attempt to set the same field, the value from-the second block will be taken.--Each metadata block is handled internally as an independent YAML document.-This means, for example, that any YAML anchors defined in a block cannot be-referenced in another block.--When pandoc is used with `-t markdown` to create a Markdown document,-a YAML metadata block will be produced only if the `-s/--standalone`-option is used.  All of the metadata will appear in a single block-at the beginning of the document.--Note that [YAML] escaping rules must be followed. Thus, for example,-if a title contains a colon, it must be quoted, and if it contains a-backslash escape, then it must be ensured that it is not treated as a-[YAML escape sequence]. The pipe character (`|`) can be used to begin-an indented block that will be interpreted literally, without need for-escaping. This form is necessary when the field contains blank lines-or block-level formatting:--    ----    title:  'This is the title: it contains a colon'-    author:-    - Author One-    - Author Two-    keywords: [nothing, nothingness]-    abstract: |-      This is the abstract.--      It consists of two paragraphs.-    ...--The literal block after the `|` must be indented relative to the-line containing the `|`.  If it is not, the YAML will be invalid-and pandoc will not interpret it as metadata.  For an overview-of the complex rules governing YAML, see the [Wikipedia entry on-YAML syntax].--Template variables will be set automatically from the metadata.  Thus, for-example, in writing HTML, the variable `abstract` will be set to the HTML-equivalent of the Markdown in the `abstract` field:--    <p>This is the abstract.</p>-    <p>It consists of two paragraphs.</p>--Variables can contain arbitrary YAML structures, but the template must match-this structure.  The `author` variable in the default templates expects a-simple list or string, but can be changed to support more complicated-structures.  The following combination, for example, would add an affiliation-to the author if one is given:--    ----    title: The document title-    author:-    - name: Author One-      affiliation: University of Somewhere-    - name: Author Two-      affiliation: University of Nowhere-    ...--To use the structured authors in the example above, you would need a custom-template:--    $for(author)$-    $if(author.name)$-    $author.name$$if(author.affiliation)$ ($author.affiliation$)$endif$-    $else$-    $author$-    $endif$-    $endfor$--Raw content to include in the document's header may be specified-using `header-includes`; however, it is important to mark up-this content as raw code for a particular output format, using-the [`raw_attribute` extension](#extension-raw_attribute), or it-will be interpreted as Markdown. For example:--    header-includes:-    - |-      ```{=latex}-      \let\oldsection\section-      \renewcommand{\section}[1]{\clearpage\oldsection{#1}}-      ```--Note:  the `yaml_metadata_block` extension works with-`commonmark` as well as `markdown` (and it is enabled by default-in `gfm` and `commonmark_x`).  However, in these formats the-following restrictions apply:--- The YAML metadata block must occur at the beginning of the-  document (and there can be only one).  If multiple files are-  given as arguments to pandoc, only the first can be a YAML-  metadata block.--- The leaf nodes of the YAML structure are parsed in isolation from-  each other and from the rest of the document.  So, for-  example,  you can't use a reference link in these contexts-  if the link definition is somewhere else in the document.--[YAML escape sequence]: https://yaml.org/spec/1.2/spec.html#id2776092-[Wikipedia entry on YAML syntax]:  https://en.wikipedia.org/wiki/YAML#Syntax--## Backslash escapes--#### Extension: `all_symbols_escapable` ####--Except inside a code block or inline code, any punctuation or space-character preceded by a backslash will be treated literally, even if it-would normally indicate formatting.  Thus, for example, if one writes--    *\*hello\**--one will get--    <em>*hello*</em>--instead of--    <strong>hello</strong>--This rule is easier to remember than original Markdown's rule,-which allows only the following characters to be backslash-escaped:--    \`*_{}[]()>#+-.!--(However, if the `markdown_strict` format is used, the original Markdown rule-will be used.)--A backslash-escaped space is parsed as a nonbreaking space. In TeX output,-it will appear as `~`. In HTML and XML output, it will appear as a-literal unicode nonbreaking space character (note that it will thus-actually look "invisible" in the generated HTML source; you can still-use the `--ascii` command-line option to make it appear as an explicit-entity).--A backslash-escaped newline (i.e. a backslash occurring at the end of-a line) is parsed as a hard line break.  It will appear in TeX output as-`\\` and in HTML as `<br />`.  This is a nice alternative to-Markdown's "invisible" way of indicating hard line breaks using-two trailing spaces on a line.--Backslash escapes do not work in verbatim contexts.--## Inline formatting--### Emphasis ###--To *emphasize* some text, surround it with `*`s or `_`, like this:--    This text is _emphasized with underscores_, and this-    is *emphasized with asterisks*.--Double `*` or `_` produces **strong emphasis**:--    This is **strong emphasis** and __with underscores__.--A `*` or `_` character surrounded by spaces, or backslash-escaped,-will not trigger emphasis:--    This is * not emphasized *, and \*neither is this\*.--#### Extension: `intraword_underscores` ####--Because `_` is sometimes used inside words and identifiers,-pandoc does not interpret a `_` surrounded by alphanumeric-characters as an emphasis marker.  If you want to emphasize-just part of a word, use `*`:--    feas*ible*, not feas*able*.--### Strikeout ###--#### Extension: `strikeout` ####--To strike out a section of text with a horizontal line, begin and end it-with `~~`. Thus, for example,--    This ~~is deleted text.~~---### Superscripts and subscripts ###--#### Extension: `superscript`, `subscript` ####--Superscripts may be written by surrounding the superscripted text by `^`-characters; subscripts may be written by surrounding the subscripted-text by `~` characters.  Thus, for example,--    H~2~O is a liquid.  2^10^ is 1024.--The text between `^...^` or `~...~` may not contain spaces or-newlines.  If the superscripted or subscripted text contains-spaces, these spaces must be escaped with backslashes.  (This is-to prevent accidental superscripting and subscripting through-the ordinary use of `~` and `^`, and also bad interactions with-footnotes.) Thus, if you want the letter P with 'a cat' in-subscripts, use `P~a\ cat~`, not `P~a cat~`.--### Verbatim ###--To make a short span of text verbatim, put it inside backticks:--    What is the difference between `>>=` and `>>`?--If the verbatim text includes a backtick, use double backticks:--    Here is a literal backtick `` ` ``.--(The spaces after the opening backticks and before the closing-backticks will be ignored.)--The general rule is that a verbatim span starts with a string-of consecutive backticks (optionally followed by a space)-and ends with a string of the same number of backticks (optionally-preceded by a space).--Note that backslash-escapes (and other Markdown constructs) do not-work in verbatim contexts:--    This is a backslash followed by an asterisk: `\*`.--#### Extension: `inline_code_attributes` ####--Attributes can be attached to verbatim text, just as with-[fenced code blocks]:--    `<$>`{.haskell}--### Underline ###--To underline text, use the `underline` class:--    [Underline]{.underline}--Or, without the `bracketed_spans` extension (but with `native_spans`):--    <span class="underline">Underline</span>--This will work in all output formats that support underline.--### Small caps ###--To write small caps, use the `smallcaps` class:--    [Small caps]{.smallcaps}--Or, without the `bracketed_spans` extension:--    <span class="smallcaps">Small caps</span>--For compatibility with other Markdown flavors, CSS is also supported:--    <span style="font-variant:small-caps;">Small caps</span>--This will work in all output formats that support small caps.--### Highlighting ###--To highlight text, use the `mark` class:--    [Mark]{.mark}--Or, without the `bracketed_spans` extension (but with `native_spans`):--    <span class="mark">Mark</span>--This will work in all output formats that support highlighting.---## Math--#### Extension: `tex_math_dollars` ####--Anything between two `$` characters will be treated as TeX math.  The-opening `$` must have a non-space character immediately to its right,-while the closing `$` must have a non-space character immediately to its-left, and must not be followed immediately by a digit.  Thus,-`$20,000 and $30,000` won't parse as math.  If for some reason-you need to enclose text in literal `$` characters, backslash-escape-them and they won't be treated as math delimiters.--For display math, use `$$` delimiters.  (In this case, the delimiters-may be separated from the formula by whitespace.  However, there can be-no blank lines between the opening and closing `$$` delimiters.)--TeX math will be printed in all output formats. How it is rendered-depends on the output format:--LaTeX-  ~ It will appear verbatim surrounded by `\(...\)` (for inline-    math) or `\[...\]` (for display math).--Markdown, Emacs Org mode, ConTeXt, ZimWiki-  ~ It will appear verbatim surrounded by `$...$` (for inline-    math) or `$$...$$` (for display math).--XWiki-  ~ It will appear verbatim surrounded by `{{formula}}..{{/formula}}`.--reStructuredText-  ~ It will be rendered using an [interpreted text role `:math:`].--AsciiDoc-  ~ For AsciiDoc output math will appear verbatim surrounded by-    `latexmath:[...]`. For `asciidoc_legacy` the bracketed-    material will also include inline or display math delimiters.--Texinfo-  ~ It will be rendered inside a `@math` command.--roff man, Jira markup-  ~ It will be rendered verbatim without `$`'s.--MediaWiki, DokuWiki-  ~ It will be rendered inside `<math>` tags.--Textile-  ~ It will be rendered inside `<span class="math">` tags.--RTF, OpenDocument-  ~ It will be rendered, if possible, using Unicode characters,-    and will otherwise appear verbatim.--ODT-  ~ It will be rendered, if possible, using MathML.--DocBook-  ~ If the `--mathml` flag is used, it will be rendered using MathML-    in an `inlineequation` or `informalequation` tag.  Otherwise it-    will be rendered, if possible, using Unicode characters.--Docx and PowerPoint-  ~ It will be rendered using OMML math markup.--FictionBook2-  ~ If the `--webtex` option is used, formulas are rendered as images-    using CodeCogs or other compatible web service, downloaded-    and embedded in the e-book. Otherwise, they will appear verbatim.--HTML, Slidy, DZSlides, S5, EPUB-  ~ The way math is rendered in HTML will depend on the-    command-line options selected. Therefore see [Math rendering in HTML]-    above.--[interpreted text role `:math:`]: https://docutils.sourceforge.io/docs/ref/rst/roles.html#math--## Raw HTML--#### Extension: `raw_html` ####--Markdown allows you to insert raw HTML (or DocBook) anywhere in a document-(except verbatim contexts, where `<`, `>`, and `&` are interpreted-literally).  (Technically this is not an extension, since standard-Markdown allows it, but it has been made an extension so that it can-be disabled if desired.)--The raw HTML is passed through unchanged in HTML, S5, Slidy, Slideous,-DZSlides, EPUB, Markdown, CommonMark, Emacs Org mode, and Textile-output, and suppressed in other formats.--For a more explicit way of including raw HTML in a Markdown-document, see the [`raw_attribute` extension][Extension: `raw_attribute`].--In the CommonMark format, if `raw_html` is enabled, superscripts,-subscripts, strikeouts and small capitals will be represented as HTML.-Otherwise, plain-text fallbacks will be used. Note that even if-`raw_html` is disabled, tables will be rendered with HTML syntax if-they cannot use pipe syntax.--#### Extension: `markdown_in_html_blocks` ####--Original Markdown allows you to include HTML "blocks":  blocks-of HTML between balanced tags that are separated from the surrounding text-with blank lines, and start and end at the left margin.  Within-these blocks, everything is interpreted as HTML, not Markdown;-so (for example), `*` does not signify emphasis.--Pandoc behaves this way when the `markdown_strict` format is used; but-by default, pandoc interprets material between HTML block tags as Markdown.-Thus, for example, pandoc will turn--    <table>-    <tr>-    <td>*one*</td>-    <td>[a link](https://google.com)</td>-    </tr>-    </table>--into--    <table>-    <tr>-    <td><em>one</em></td>-    <td><a href="https://google.com">a link</a></td>-    </tr>-    </table>--whereas `Markdown.pl` will preserve it as is.--There is one exception to this rule:  text between `<script>`,-`<style>`, `<pre>`, and `<textarea>` tags is not interpreted as Markdown.--This departure from original Markdown should make it easier to mix-Markdown with HTML block elements.  For example, one can surround-a block of Markdown text with `<div>` tags without preventing it-from being interpreted as Markdown.--#### Extension: `native_divs` ####--Use native pandoc `Div` blocks for content inside `<div>` tags.-For the most part this should give the same output as-`markdown_in_html_blocks`, but it makes it easier to write pandoc-filters to manipulate groups of blocks.--#### Extension: `native_spans` ####--Use native pandoc `Span` blocks for content inside `<span>` tags.-For the most part this should give the same output as `raw_html`,-but it makes it easier to write pandoc filters to manipulate groups-of inlines.--#### Extension: `raw_tex` ####--In addition to raw HTML, pandoc allows raw LaTeX, TeX, and ConTeXt to be-included in a document. Inline TeX commands will be preserved and passed-unchanged to the LaTeX and ConTeXt writers. Thus, for example, you can use-LaTeX to include BibTeX citations:--    This result was proved in \cite{jones.1967}.--Note that in LaTeX environments, like--    \begin{tabular}{|l|l|}\hline-    Age & Frequency \\ \hline-    18--25  & 15 \\-    26--35  & 33 \\-    36--45  & 22 \\ \hline-    \end{tabular}--the material between the begin and end tags will be interpreted as raw-LaTeX, not as Markdown.--For a more explicit and flexible way of including raw TeX in a-Markdown document, see the [`raw_attribute`-extension][Extension: `raw_attribute`].--Inline LaTeX is ignored in output formats other than Markdown, LaTeX,-Emacs Org mode, and ConTeXt.--### Generic raw attribute ###--#### Extension: `raw_attribute` ####--Inline spans and fenced code blocks with a special-kind of attribute will be parsed as raw content with the-designated format.  For example, the following produces a raw-roff `ms` block:--    ```{=ms}-    .MYMACRO-    blah blah-    ```-And the following produces a raw `html` inline element:--    This is `<a>html</a>`{=html}--This can be useful to insert raw xml into `docx` documents, e.g.-a pagebreak:--    ```{=openxml}-    <w:p>-      <w:r>-        <w:br w:type="page"/>-      </w:r>-    </w:p>-    ```--The format name should match the target format name (see-`-t/--to`, above, for a list, or use `pandoc---list-output-formats`). Use `openxml` for `docx` output,-`opendocument` for `odt` output, `html5` for `epub3` output,-`html4` for `epub2` output, and `latex`, `beamer`,-`ms`, or `html5` for `pdf` output (depending on what you-use for `--pdf-engine`).--This extension presupposes that the relevant kind of-inline code or fenced code block is enabled.  Thus, for-example, to use a raw attribute with a backtick code block,-`backtick_code_blocks` must be enabled.--The raw attribute cannot be combined with regular attributes.--## LaTeX macros--#### Extension: `latex_macros` ####--When this extension is enabled, pandoc will parse LaTeX-macro definitions and apply the resulting macros to all LaTeX-math and raw LaTeX.  So, for example, the following will work in-all output formats, not just LaTeX:--    \newcommand{\tuple}[1]{\langle #1 \rangle}--    $\tuple{a, b, c}$--Note that LaTeX macros will not be applied if they occur-inside a raw span or block marked with the-[`raw_attribute` extension](#extension-raw_attribute).--When `latex_macros` is disabled, the raw LaTeX and math will-not have macros applied. This is usually a better approach when-you are targeting LaTeX or PDF.--Macro definitions in LaTeX will be passed through as raw LaTeX-only if `latex_macros` is not enabled.  Macro definitions in-Markdown source (or other formats allowing `raw_tex`) will-be passed through regardless of whether `latex_macros` is-enabled.--## Links--Markdown allows links to be specified in several ways.--### Automatic links ###--If you enclose a URL or email address in pointy brackets, it-will become a link:--    <https://google.com>-    <sam@green.eggs.ham>--### Inline links ###--An inline link consists of the link text in square brackets,-followed by the URL in parentheses. (Optionally, the URL can-be followed by a link title, in quotes.)--    This is an [inline link](/url), and here's [one with-    a title](https://fsf.org "click here for a good time!").--There can be no space between the bracketed part and the parenthesized part.-The link text can contain formatting (such as emphasis), but the title cannot.--Email addresses in inline links are not autodetected, so they have to be-prefixed with `mailto`:--    [Write me!](mailto:sam@green.eggs.ham)--### Reference links ###--An *explicit* reference link has two parts, the link itself and the link-definition, which may occur elsewhere in the document (either-before or after the link).--The link consists of link text in square brackets, followed by a label in-square brackets. (There cannot be space between the two unless the-`spaced_reference_links` extension is enabled.) The link definition-consists of the bracketed label, followed by a colon and a space, followed by-the URL, and optionally (after a space) a link title either in quotes or in-parentheses.  The label must not be parseable as a citation (assuming-the `citations` extension is enabled):  citations take precedence over-link labels.--Here are some examples:--    [my label 1]: /foo/bar.html  "My title, optional"-    [my label 2]: /foo-    [my label 3]: https://fsf.org (The Free Software Foundation)-    [my label 4]: /bar#special  'A title in single quotes'--The URL may optionally be surrounded by angle brackets:--    [my label 5]: <http://foo.bar.baz>--The title may go on the next line:--    [my label 3]: https://fsf.org-      "The Free Software Foundation"--Note that link labels are not case sensitive.  So, this will work:--    Here is [my link][FOO]--    [Foo]: /bar/baz--In an *implicit* reference link, the second pair of brackets is-empty:--    See [my website][].--    [my website]: http://foo.bar.baz--Note:  In `Markdown.pl` and most other Markdown implementations,-reference link definitions cannot occur in nested constructions-such as list items or block quotes.  Pandoc lifts this-arbitrary-seeming restriction.  So the following is fine in pandoc,-though not in most other implementations:--    > My block [quote].-    >-    > [quote]: /foo--#### Extension: `shortcut_reference_links` ####--In a *shortcut* reference link, the second pair of brackets may-be omitted entirely:--    See [my website].--    [my website]: http://foo.bar.baz--### Internal links ###--To link to another section of the same document, use the automatically-generated identifier (see [Heading identifiers]). For example:--    See the [Introduction](#introduction).--or--    See the [Introduction].--    [Introduction]: #introduction--Internal links are currently supported for HTML formats (including-HTML slide shows and EPUB), LaTeX, and ConTeXt.--## Images--A link immediately preceded by a `!` will be treated as an image.-The link text will be used as the image's alt text:--    ![la lune](lalune.jpg "Voyage to the moon")--    ![movie reel]--    [movie reel]: movie.gif--#### Extension: `implicit_figures` ####--An image with nonempty alt text, occurring by itself in a-paragraph, will be rendered as a figure with a caption.  The-image's alt text will be used as the caption.--    ![This is the caption](/url/of/image.png)--How this is rendered depends on the output format. Some output-formats (e.g. RTF) do not yet support figures.  In those-formats, you'll just get an image in a paragraph by itself, with-no caption.--If you just want a regular inline image, just make sure it is not-the only thing in the paragraph. One way to do this is to insert a-nonbreaking space after the image:--    ![This image won't be a figure](/url/of/image.png)\--Note that in reveal.js slide shows, an image in a paragraph-by itself that has the `r-stretch` class will fill the screen,-and the caption and figure tags will be omitted.--#### Extension: `link_attributes` ####--Attributes can be set on links and images:--    An inline ![image](foo.jpg){#id .class width=30 height=20px}-    and a reference ![image][ref] with attributes.--    [ref]: foo.jpg "optional title" {#id .class key=val key2="val 2"}--(This syntax is compatible with [PHP Markdown Extra] when only `#id`-and `.class` are used.)--For HTML and EPUB, all known HTML5 attributes except `width` and-`height` (but including `srcset` and `sizes`) are passed through-as is. Unknown attributes are passed through as custom-attributes, with `data-` prepended. The other writers ignore-attributes that are not specifically supported by their output format.--The `width` and `height` attributes on images are treated specially. When-used without a unit, the unit is assumed to be pixels. However, any of-the following unit identifiers can be used: `px`, `cm`, `mm`, `in`, `inch`-and `%`. There must not be any spaces between the number and the unit.-For example:--```-![](file.jpg){ width=50% }-```--- Dimensions may be converted to a form that is compatible with-  the output format (for example, dimensions given in pixels will-  be converted to inches when converting HTML to LaTeX). Conversion-  between pixels and physical measurements is affected by the-  `--dpi` option (by default, 96 dpi is assumed, unless the image-  itself contains dpi information).-- The `%` unit is generally relative to some available space.-  For example the above example will render to the following.-  - HTML: `<img href="file.jpg" style="width: 50%;" />`-  - LaTeX: `\includegraphics[width=0.5\textwidth,height=\textheight]{file.jpg}`-    (If you're using a custom template, you need to configure `graphicx`-    as in the default template.)-  - ConTeXt: `\externalfigure[file.jpg][width=0.5\textwidth]`-- Some output formats have a notion of a class-  ([ConTeXt](https://wiki.contextgarden.net/Using_Graphics#Multiple_Image_Settings))-  or a unique identifier (LaTeX `\caption`), or both (HTML).-- When no `width` or `height` attributes are specified, the fallback-  is to look at the image resolution and the dpi metadata embedded in-  the image file.--## Divs and Spans--Using the `native_divs` and `native_spans` extensions-(see [above][Extension: `native_divs`]), HTML syntax can-be used as part of Markdown to create native `Div` and `Span`-elements in the pandoc AST (as opposed to raw HTML).-However, there is also nicer syntax available:--#### Extension: `fenced_divs` ####--Allow special fenced syntax for native `Div` blocks.  A Div-starts with a fence containing at least three consecutive-colons plus some attributes. The attributes may optionally-be followed by another string of consecutive colons.--Note:  the `commonmark` parser doesn't permit colons after-the attributes.--The attribute syntax is exactly as in fenced code blocks (see-[Extension: `fenced_code_attributes`]).  As with fenced-code blocks, one can use either attributes in curly braces-or a single unbraced word, which will be treated as a class-name.  The Div ends with another line containing a string of at-least three consecutive colons.  The fenced Div should be-separated by blank lines from preceding and following blocks.--Example:--    ::::: {#special .sidebar}-    Here is a paragraph.--    And another.-    :::::--Fenced divs can be nested.  Opening fences are distinguished-because they *must* have attributes:--    ::: Warning ::::::-    This is a warning.--    ::: Danger-    This is a warning within a warning.-    :::-    ::::::::::::::::::--Fences without attributes are always closing fences.  Unlike-with fenced code blocks, the number of colons in the closing-fence need not match the number in the opening fence.  However,-it can be helpful for visual clarity to use fences of different-lengths to distinguish nested divs from their parents.---#### Extension: `bracketed_spans` ####--A bracketed sequence of inlines, as one would use to begin-a link, will be treated as a `Span` with attributes if it is-followed immediately by attributes:--    [This is *some text*]{.class key="val"}--## Footnotes--#### Extension: `footnotes` ####--Pandoc's Markdown allows footnotes, using the following syntax:--    Here is a footnote reference,[^1] and another.[^longnote]--    [^1]: Here is the footnote.--    [^longnote]: Here's one with multiple blocks.--        Subsequent paragraphs are indented to show that they-    belong to the previous footnote.--            { some.code }--        The whole paragraph can be indented, or just the first-        line.  In this way, multi-paragraph footnotes work like-        multi-paragraph list items.--    This paragraph won't be part of the note, because it-    isn't indented.--The identifiers in footnote references may not contain spaces, tabs,-newlines, or the characters `^`, `[`, or `]`. These identifiers-are used only to correlate the footnote reference with the note-itself; in the output, footnotes will be numbered sequentially.--The footnotes themselves need not be placed at the end of the-document.  They may appear anywhere except inside other block elements-(lists, block quotes, tables, etc.).  Each footnote should be-separated from surrounding content (including other footnotes)-by blank lines.--#### Extension: `inline_notes` ####--Inline footnotes are also allowed (though, unlike regular notes,-they cannot contain multiple paragraphs).  The syntax is as follows:--    Here is an inline note.^[Inline notes are easier to write, since-    you don't have to pick an identifier and move down to type the-    note.]--Inline and regular footnotes may be mixed freely.--## Citation syntax--#### Extension: `citations` ####--To cite a bibliographic item with an identifier foo, use the-syntax `@foo`.  Normal citations should be included in square-brackets, with semicolons separating distinct items:--    Blah blah [@doe99; @smith2000; @smith2004].--How this is rendered depends on the citation style.  In an-author-date style, it might render as--    Blah blah (Doe 1999, Smith 2000, 2004).--In a footnote style, it might render as--    Blah blah.[^1]--    [^1]:  John Doe, "Frogs," *Journal of Amphibians* 44 (1999);-    Susan Smith, "Flies," *Journal of Insects* (2000);-    Susan Smith, "Bees," *Journal of Insects* (2004).--See the [CSL user documentation] for more information about CSL-styles and how they affect rendering.--Unless a citation key starts with a letter, digit, or `_`,-and contains only alphanumerics and single internal punctuation-characters (`:.#$%&-+?<>~/`), it must be surrounded-by curly braces, which are not considered part of the key.-In `@Foo_bar.baz.`, the key is `Foo_bar.baz` because the final-period is not *internal* punctuation, so it is not included in-the key.  In `@{Foo_bar.baz.}`, the key is `Foo_bar.baz.`, including-the final period.-In `@Foo_bar--baz`, the key is `Foo_bar` because the repeated internal-punctuation characters terminate the key.-The curly braces are recommended if you use URLs as-keys: `[@{https://example.com/bib?name=foobar&date=2000}, p.  33]`.--Citation items may optionally include a prefix, a locator, and-a suffix.  In--    Blah blah [see @doe99, pp. 33-35 and *passim*; @smith04, chap. 1].--the first item (`doe99`) has prefix `see `, locator `pp.  33-35`,-and suffix `and *passim*`.  The second item (`smith04`) has-locator `chap. 1` and no prefix or suffix.--Pandoc uses some heuristics to separate the locator from the-rest of the subject.  It is sensitive to the locator terms-defined in the [CSL locale files].  Either abbreviated or-unabbreviated forms are accepted. In the `en-US` locale, locator-terms can be written in either singular or plural forms, as-`book`, `bk.`/`bks.`; `chapter`, `chap.`/`chaps.`; `column`,-`col.`/`cols.`; `figure`, `fig.`/`figs.`; `folio`,-`fol.`/`fols.`; `number`, `no.`/`nos.`; `line`, `l.`/`ll.`;-`note`, `n.`/`nn.`; `opus`, `op.`/`opp.`; `page`, `p.`/`pp.`;-`paragraph`, `para.`/`paras.`; `part`, `pt.`/`pts.`; `section`,-`sec.`/`secs.`; `sub verbo`, `s.v.`/`s.vv.`; `verse`,-`v.`/`vv.`; `volume`, `vol.`/`vols.`; `¶`/`¶¶`; `§`/`§§`. If no-locator term is used, "page" is assumed.--In complex cases, you can force something to be treated as-a locator by enclosing it in curly braces or prevent parsing-the suffix as locator by prepending curly braces:--    [@smith{ii, A, D-Z}, with a suffix]-    [@smith, {pp. iv, vi-xi, (xv)-(xvii)} with suffix here]-    [@smith{}, 99 years later]--A minus sign (`-`) before the `@` will suppress mention of-the author in the citation.  This can be useful when the-author is already mentioned in the text:--    Smith says blah [-@smith04].--You can also write an author-in-text citation, by omitting the-square brackets:--    @smith04 says blah.--    @smith04 [p. 33] says blah.--This will cause the author's name to be rendered, followed by-the bibliographical details.  Use this form when you want to-make the citation the subject of a sentence.--When you are using a note style, it is usually better to let-citeproc create the footnotes from citations rather than writing-an explicit note.  If you do write an explicit note that-contains a citation, note that normal citations will be put in-parentheses, while author-in-text citations will not.  For-this reason, it is sometimes preferable to use the-author-in-text style inside notes when using a note style.--[CSL user documentation]: https://citationstyles.org/authors/-[CSL]: https://docs.citationstyles.org/en/stable/specification.html-[CSL markup specs]: https://docs.citationstyles.org/en/1.0/release-notes.html#rich-text-markup-within-fields-[Chicago Manual of Style]: https://chicagomanualofstyle.org-[Citation Style Language]: https://citationstyles.org-[Zotero Style Repository]: https://www.zotero.org/styles-[finding and editing styles]: https://citationstyles.org/authors/-[CSL locale files]: https://github.com/citation-style-language/locales--## Non-default extensions--The following Markdown syntax extensions are not enabled by default-in pandoc, but may be enabled by adding `+EXTENSION` to the format-name, where `EXTENSION` is the name of the extension.  Thus, for-example, `markdown+hard_line_breaks` is Markdown with hard line breaks.--#### Extension: `rebase_relative_paths` ####--Rewrite relative paths for Markdown links and images, depending-on the path of the file containing the link or image link.  For-each link or image, pandoc will compute the directory of the-containing file, relative to the working directory, and prepend-the resulting path to the link or image path.--The use of this extension is best understood by example.-Suppose you have a subdirectory for each chapter of a book,-`chap1`, `chap2`, `chap3`. Each contains a file `text.md` and a-number of images used in the chapter.  You would like to have-`![image](spider.jpg)` in `chap1/text.md` refer to-`chap1/spider.jpg` and `![image](spider.jpg)` in `chap2/text.md`-refer to `chap2/spider.jpg`.  To do this, use--    pandoc chap*/*.md -f markdown+rebase_relative_paths--Without this extension, you would have to use-`![image](chap1/spider.jpg)` in `chap1/text.md` and-`![image](chap2/spider.jpg)` in `chap2/text.md`.  Links with-relative paths will be rewritten in the same way as images.--Absolute paths and URLs are not changed.  Neither are empty-paths or paths consisting entirely of a fragment, e.g., `#foo`.--Note that relative paths in reference links and images will-be rewritten relative to the file containing the link-reference definition, not the file containing the reference link-or image itself, if these differ.--#### Extension: `mark` ####--To highlight out a section of text, begin and end it with-with `==`. Thus, for example,--    This ==is deleted text.==--#### Extension: `attributes` ####--Allows attributes to be attached to any inline or block-level-element when parsing `commonmark`.-The syntax for the attributes is the same as that-used in [`header_attributes`][Extension: `header_attributes`].--- Attributes that occur immediately after an inline-  element affect that element.  If they follow a space, then they-  belong to the space.  (Hence, this option subsumes-  `inline_code_attributes` and `link_attributes`.)-- Attributes that occur immediately before a block-  element, on a line by themselves, affect that-  element.-- Consecutive attribute specifiers may be used,-  either for blocks or for inlines.  Their attributes-  will be combined.-- Attributes that occur at the end of the text of-  a Setext or ATX heading (separated by whitespace-  from the text) affect the heading element. (Hence, this-  option subsumes `header_attributes`.)-- Attributes that occur after the opening fence-  in a fenced code block affect the code block element. (Hence,-  this option subsumes `fenced_code_attributes`.)-- Attributes that occur at the end of a reference-  link definition affect links that refer to that-  definition.--Note that pandoc's AST does not currently allow attributes-to be attached to arbitrary elements.  Hence a Span or Div-container will be added if needed.--#### Extension: `old_dashes` ####--Selects the pandoc <= 1.8.2.1 behavior for parsing smart dashes:-`-` before a numeral is an en-dash, and `--` is an em-dash.-This option only has an effect if `smart` is enabled. It is-selected automatically for `textile` input.--#### Extension: `angle_brackets_escapable` ####--Allow `<` and `>` to be backslash-escaped, as they can be in-GitHub flavored Markdown but not original Markdown.  This is-implied by pandoc's default `all_symbols_escapable`.--#### Extension: `lists_without_preceding_blankline` ####--Allow a list to occur right after a paragraph, with no intervening-blank space.--#### Extension: `four_space_rule` ####--Selects the pandoc <= 2.0 behavior for parsing lists, so that-four spaces indent are needed for list item continuation-paragraphs.--#### Extension: `spaced_reference_links` ####--Allow whitespace between the two components of a reference link,-for example,--    [foo] [bar].--#### Extension: `hard_line_breaks` ####--Causes all newlines within a paragraph to be interpreted as hard line-breaks instead of spaces.--#### Extension: `ignore_line_breaks` ####--Causes newlines within a paragraph to be ignored, rather than being-treated as spaces or as hard line breaks.  This option is intended for-use with East Asian languages where spaces are not used between words,-but text is divided into lines for readability.--#### Extension: `east_asian_line_breaks` ####--Causes newlines within a paragraph to be ignored, rather than-being treated as spaces or as hard line breaks, when they occur-between two East Asian wide characters.  This is a better choice-than `ignore_line_breaks` for texts that include a mix of East-Asian wide characters and other characters.--#### Extension: `emoji` ####--Parses textual emojis like `:smile:` as Unicode emoticons.--#### Extension: `tex_math_gfm` ####--Supports two GitHub-specific formats for math.-Inline math: ``$`e=mc^2`$``.--Display math:--````-``` math-e=mc^2-```-````--#### Extension: `tex_math_single_backslash` ####--Causes anything between `\(` and `\)` to be interpreted as inline-TeX math, and anything between `\[` and `\]` to be interpreted-as display TeX math.  Note: a drawback of this extension is that-it precludes escaping `(` and `[`.--#### Extension: `tex_math_double_backslash` ####--Causes anything between `\\(` and `\\)` to be interpreted as inline-TeX math, and anything between `\\[` and `\\]` to be interpreted-as display TeX math.--#### Extension: `markdown_attribute` ####--By default, pandoc interprets material inside block-level tags as Markdown.-This extension changes the behavior so that Markdown is only parsed-inside block-level tags if the tags have the attribute `markdown=1`.--#### Extension: `mmd_title_block` ####--Enables a [MultiMarkdown] style title block at the top of-the document, for example:--    Title:   My title-    Author:  John Doe-    Date:    September 1, 2008-    Comment: This is a sample mmd title block, with-             a field spanning multiple lines.--See the MultiMarkdown documentation for details.  If `pandoc_title_block` or-`yaml_metadata_block` is enabled, it will take precedence over-`mmd_title_block`.--#### Extension: `abbreviations` ####--Parses PHP Markdown Extra abbreviation keys, like--    *[HTML]: Hypertext Markup Language--Note that the pandoc document model does not support-abbreviations, so if this extension is enabled, abbreviation keys are-simply skipped (as opposed to being parsed as paragraphs).--#### Extension: `alerts` ####--Supports [GitHub-style Markdown alerts], like--    > [!INFO]-    > This is an informational message.--  [GitHub-style Markdown alerts]: https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts--#### Extension: `autolink_bare_uris` ####--Makes all absolute URIs into links, even when not surrounded by-pointy braces `<...>`.--#### Extension: `mmd_link_attributes` ####--Parses MultiMarkdown-style key-value attributes on link-and image references. This extension should not be confused with the-[`link_attributes`](#extension-link_attributes) extension.--    This is a reference ![image][ref] with MultiMarkdown attributes.--    [ref]: https://path.to/image "Image title" width=20px height=30px-           id=myId class="myClass1 myClass2"--#### Extension: `mmd_header_identifiers` ####--Parses MultiMarkdown-style heading identifiers (in square brackets,-after the heading but before any trailing `#`s in an ATX heading).--#### Extension: `compact_definition_lists` ####--Activates the definition list syntax of pandoc 1.12.x and earlier.-This syntax differs from the one described above under [Definition lists]-in several respects:--  - No blank line is required between consecutive items of the-    definition list.-  - To get a "tight" or "compact" list, omit space between consecutive-    items; the space between a term and its definition does not affect-    anything.-  - Lazy wrapping of paragraphs is not allowed:  the entire definition must-    be indented four spaces.[^6]--[^6]:  To see why laziness is incompatible with relaxing the requirement-    of a blank line between items, consider the following example:--        bar-        :    definition-        foo-        :    definition--    Is this a single list item with two definitions of "bar," the first of-    which is lazily wrapped, or two list items?  To remove the ambiguity-    we must either disallow lazy wrapping or require a blank line between-    list items.--#### Extension: `gutenberg` ####--Use [Project Gutenberg] conventions for `plain` output:-all-caps for strong emphasis, surround by underscores-for regular emphasis, add extra blank space around headings.--  [Project Gutenberg]: https://www.gutenberg.org--#### Extension: `sourcepos` ####--Include source position attributes when parsing `commonmark`.-For elements that accept attributes, a `data-pos` attribute-is added; other elements are placed in a surrounding-Div or Span element with a `data-pos` attribute.--#### Extension: `short_subsuperscripts` ####--Parse MultiMarkdown-style subscripts and superscripts, which start with-a '~' or '^' character, respectively, and include the alphanumeric sequence-that follows. For example:--    x^2 = 4--or--    Oxygen is O~2.--#### Extension: `wikilinks_title_after_pipe` ####--Pandoc supports multiple Markdown wikilink syntaxes, regardless of-whether the title is before or after the pipe.--Using `--from=markdown+wikilinks_title_after_pipe` results in-```[[Wiki]]-[[URL|title]]-```--while using `--from=markdown+wikilinks_title_before_pipe` results-in-```[[Wiki]]-[[title|URL]]-```--## Markdown variants--In addition to pandoc's extended Markdown, the following Markdown-variants are supported:--- `markdown_phpextra` (PHP Markdown Extra)-- `markdown_github` (deprecated GitHub-Flavored Markdown)-- `markdown_mmd` (MultiMarkdown)-- `markdown_strict` (Markdown.pl)-- `commonmark` (CommonMark)-- `gfm` (Github-Flavored Markdown)-- `commonmark_x` (CommonMark with many pandoc extensions)--To see which extensions are supported for a given format,-and which are enabled by default, you can use the command--    pandoc --list-extensions=FORMAT--where `FORMAT` is replaced with the name of the format.--Note that the list of extensions for `commonmark`,-`gfm`, and `commonmark_x` are defined relative to default-commonmark.  So, for example, `backtick_code_blocks`-does not appear as an extension, since it is enabled by-default and cannot be disabled.--# Citations--When the `--citeproc` option is used, pandoc can automatically generate-citations and a bibliography in a number of styles.  Basic usage is--    pandoc --citeproc myinput.txt--To use this feature, you will need to have--- a document containing citations (see [Citation syntax]);-- a source of bibliographic data: either an external bibliography-  file or a list of `references` in the document's YAML metadata;-- optionally, a [CSL] citation style.--## Specifying bibliographic data--You can specify an external bibliography using the-`bibliography` metadata field in a YAML metadata section or the-`--bibliography` command line argument. If you want to use-multiple bibliography files, you can supply multiple-`--bibliography` arguments or set `bibliography` metadata field-to YAML array.  A bibliography may have any of these formats:--  Format            File extension-  ------------      ---------------  BibLaTeX          .bib-  BibTeX            .bibtex-  CSL JSON          .json-  CSL YAML          .yaml-  RIS               .ris--Note that `.bib` can be used with both BibTeX and BibLaTeX files;-use the extension `.bibtex` to force interpretation as BibTeX.--In BibTeX and BibLaTeX databases, pandoc parses LaTeX markup-inside fields such as `title`; in CSL YAML databases, pandoc-Markdown; and in CSL JSON databases, an [HTML-like markup][CSL-markup specs]:--`<i>...</i>`-:   italics--`<b>...</b>`-:   bold--`<span style="font-variant:small-caps;">...</span>` or `<sc>...</sc>`-:   small capitals--`<sub>...</sub>`-:   subscript--`<sup>...</sup>`-:   superscript--`<span class="nocase">...</span>`-:   prevent a phrase from being capitalized as title case--As an alternative to specifying a bibliography file using-`--bibliography` or the YAML metadata field `bibliography`, you-can include the citation data directly in the `references` field-of the document's YAML metadata. The field should contain an-array of YAML-encoded references, for example:--    ----    references:-    - type: article-journal-      id: WatsonCrick1953-      author:-      - family: Watson-        given: J. D.-      - family: Crick-        given: F. H. C.-      issued:-        date-parts:-        - - 1953-          - 4-          - 25-      title: 'Molecular structure of nucleic acids: a structure for-        deoxyribose nucleic acid'-      title-short: Molecular structure of nucleic acids-      container-title: Nature-      volume: 171-      issue: 4356-      page: 737-738-      DOI: 10.1038/171737a0-      URL: https://www.nature.com/articles/171737a0-      language: en-GB-    ...--If both an external bibliography and inline (YAML metadata)-references are provided, both will be used. In case of-conflicting `id`s, the inline references will take precedence.--Note that pandoc can be used to produce such a YAML metadata-section from a BibTeX, BibLaTeX, or CSL JSON bibliography:--    pandoc chem.bib -s -f biblatex -t markdown-    pandoc chem.json -s -f csljson -t markdown--Indeed, pandoc can convert between any of these-citation formats:--    pandoc chem.bib -s -f biblatex -t csljson-    pandoc chem.yaml -s -f markdown -t biblatex--Running pandoc on a bibliography file with the `--citeproc`-option will create a formatted bibliography in the format-of your choice:--    pandoc chem.bib -s --citeproc -o chem.html-    pandoc chem.bib -s --citeproc -o chem.pdf--### Capitalization in titles--If you are using a bibtex or biblatex bibliography, then observe-the following rules:--  - English titles should be in title case.  Non-English titles should-    be in sentence case, and the `langid` field in biblatex should be-    set to the relevant language.  (The following values are treated-    as English:  `american`, `british`, `canadian`, `english`,-    `australian`, `newzealand`, `USenglish`, or `UKenglish`.)--  - As is standard with bibtex/biblatex, proper names should be-    protected with curly braces so that they won't be lowercased-    in styles that call for sentence case.  For example:--        title = {My Dinner with {Andre}}--  - In addition, words that should remain lowercase (or camelCase)-    should be protected:--        title = {Spin Wave Dispersion on the {nm} Scale}--    Though this is not necessary in bibtex/biblatex, it is necessary-    with citeproc, which stores titles internally in sentence case,-    and converts to title case in styles that require it.  Here we-    protect "nm" so that it doesn't get converted to "Nm" at this stage.--If you are using a CSL bibliography (either JSON or YAML), then observe-the following rules:--  - All titles should be in sentence case.--  - Use the `language` field for non-English titles to prevent their-    conversion to title case in styles that call for this. (Conversion-    happens only if `language` begins with `en` or is left empty.)--  - Protect words that should not be converted to title case using-    this syntax:--        Spin wave dispersion on the <span class="nocase">nm</span> scale--### Conference Papers, Published vs. Unpublished--For a formally published conference paper, use the biblatex entry type-`inproceedings` (which will be mapped to CSL `paper-conference`).--For an unpublished manuscript, use the biblatex entry type-`unpublished` without an `eventtitle` field (this entry type-will be mapped to CSL `manuscript`).--For a talk, an unpublished conference paper, or a poster-presentation, use the biblatex entry type `unpublished` with an-`eventtitle` field (this entry type will be mapped to CSL-`speech`). Use the biblatex `type` field to indicate the type,-e.g. "Paper", or "Poster". `venue` and `eventdate` may be useful-too, though `eventdate` will not be rendered by most CSL styles.-Note that `venue` is for the event's venue, unlike `location`-which describes the publisher's location; do not use the latter-for an unpublished conference paper.---## Specifying a citation style--Citations and references can be formatted using any style supported by the-[Citation Style Language], listed in the [Zotero Style Repository].-These files are specified using the `--csl` option or the `csl`-(or `citation-style`) metadata field.  By default, pandoc will-use the [Chicago Manual of Style] author-date format.  (You can-override this default by copying a CSL style of your choice-to `default.csl` in your user data directory.)-The CSL project provides further information on [finding and-editing styles].--The `--citation-abbreviations` option (or the-`citation-abbreviations` metadata field) may be used to specify-a JSON file containing abbreviations of journals that should be-used in formatted bibliographies when `form="short"` is-specified.  The format of the file can be illustrated with an-example:---    { "default": {-        "container-title": {-                "Lloyd's Law Reports": "Lloyd's Rep",-                "Estates Gazette": "EG",-                "Scots Law Times": "SLT"-        }-      }-    }---## Citations in note styles--Pandoc's citation processing is designed to allow you to-move between author-date, numerical, and note styles without-modifying the Markdown source.  When you're using a note-style, avoid inserting footnotes manually. Instead, insert-citations just as you would in an author-date style---for-example,--    Blah blah [@foo, p. 33].--The footnote will be created automatically. Pandoc will take-care of removing the space and moving the note before or-after the period, depending on the setting of-`notes-after-punctuation`, as described below in [Other relevant-metadata fields].--In some cases you may need to put a citation inside a regular-footnote.  Normal citations in footnotes (such as `[@foo, p.-33]`) will be rendered in parentheses.  In-text citations (such-as `@foo [p. 33]`) will be rendered without parentheses. (A-comma will be added if appropriate.)  Thus:--    [^1]:  Some studies [@foo; @bar, p. 33] show that-    frubulicious zoosnaps are quantical.  For a survey-    of the literature, see @baz [chap. 1].---## Placement of the bibliography--If the style calls for a list of works cited, it will be placed-in a div with id `refs`, if one exists:--    ::: {#refs}-    :::--Otherwise, it will be placed at the end of the document.-Generation of the bibliography can be suppressed by setting-`suppress-bibliography: true` in the YAML metadata.--If you wish the bibliography to have a section heading, you can-set `reference-section-title` in the metadata, or put the heading-at the beginning of the div with id `refs` (if you are using it)-or at the end of your document:--    last paragraph...--    # References--The bibliography will be inserted after this heading.  Note that-the `unnumbered` class will be added to this heading, so that the-section will not be numbered.--If you want to put the bibliography into a variable in your-template, one way to do that is to put the div with id `refs`-into a metadata field, e.g.--    ----    refs: |-       ::: {#refs}-       :::-    ...--You can then put the variable `$refs$` into your template where-you want the bibliography to be placed.--## Including uncited items in the bibliography--If you want to include items in the bibliography without actually-citing them in the body text, you can define a dummy `nocite` metadata-field and put the citations there:--    ----    nocite: |-      @item1, @item2-    ...--    @item3--In this example, the document will contain a citation for `item3`-only, but the bibliography will contain entries for `item1`, `item2`, and-`item3`.--It is possible to create a bibliography with all the citations,-whether or not they appear in the document, by using a wildcard:--    ----    nocite: |-      @*-    ...--For LaTeX output, you can also use [`natbib`] or [`biblatex`] to-render the bibliography. In order to do so, specify bibliography-files as outlined above, and add `--natbib` or `--biblatex`-argument to pandoc invocation. Bear in mind that bibliography-files have to be in either BibTeX (for `--natbib`)-or BibLaTeX (for `--biblatex`) format.--## Other relevant metadata fields--A few other metadata fields affect bibliography formatting:--`link-citations`-:   If true, citations will be hyperlinked to the-    corresponding bibliography entries (for author-date and-    numerical styles only).  Defaults to false.--`link-bibliography`-:   If true, DOIs, PMCIDs, PMID, and URLs in bibliographies will-    be rendered as hyperlinks.  (If an entry contains a DOI, PMCID,-    PMID, or URL, but none of these fields are rendered by the style,-    then the title, or in the absence of a title the whole entry, will-    be hyperlinked.)  Defaults to true.--`lang`-:   The `lang` field will affect how the style is localized,-    for example in the translation of labels, the use-    of quotation marks, and the way items are sorted.-    (For backwards compatibility, `locale` may be used instead-    of `lang`, but this use is deprecated.)--    A BCP 47 language tag is expected:  for example, `en`,-    `de`, `en-US`, `fr-CA`, `ug-Cyrl`.  The unicode extension-    syntax (after `-u-`) may be used to specify options for-    collation (sorting) more precisely. Here are some examples:--    - `zh-u-co-pinyin` -- Chinese with the Pinyin collation.-    - `es-u-co-trad` -- Spanish with the traditional collation-      (with `Ch` sorting after `C`).-    - `fr-u-kb` -- French with "backwards" accent sorting-      (with `coté` sorting after `côte`).-    - `en-US-u-kf-upper` -- English with uppercase letters sorting-       before lower (default is lower before upper).--`notes-after-punctuation`-:    If true (the default for note styles), pandoc will put-     footnote references or superscripted numerical citations-     after following punctuation.  For example, if the source-     contains `blah blah [@jones99].`, the result will look like-     `blah blah.[^1]`, with the note moved after the period and-     the space collapsed.  If false, the space will still be-     collapsed, but the footnote will not be moved after the-     punctuation.  The option may also be used in numerical styles-     that use superscripts for citation numbers (but for these-     styles the default is not to move the citation).---# Slide shows--You can use pandoc to produce an HTML + JavaScript slide presentation-that can be viewed via a web browser.  There are five ways to do this,-using [S5], [DZSlides], [Slidy], [Slideous], or [reveal.js].-You can also produce a PDF slide show using LaTeX [`beamer`], or-slide shows in Microsoft [PowerPoint] format.--Here's the Markdown source for a simple slide show, `habits.txt`:--    % Habits-    % John Doe-    % March 22, 2005--    # In the morning--    ## Getting up--    - Turn off alarm-    - Get out of bed--    ## Breakfast--    - Eat eggs-    - Drink coffee--    # In the evening--    ## Dinner--    - Eat spaghetti-    - Drink wine--    --------------------    ![picture of spaghetti](images/spaghetti.jpg)--    ## Going to sleep--    - Get in bed-    - Count sheep--To produce an HTML/JavaScript slide show, simply type--    pandoc -t FORMAT -s habits.txt -o habits.html--where `FORMAT` is either `s5`, `slidy`, `slideous`, `dzslides`, or `revealjs`.--For Slidy, Slideous, reveal.js, and S5, the file produced by-pandoc with the `-s/--standalone` option embeds a link to-JavaScript and CSS files, which are assumed to be available at-the relative path `s5/default` (for S5), `slideous` (for-Slideous), `reveal.js` (for reveal.js), or at the Slidy website-at `w3.org` (for Slidy).  (These paths can be changed by setting-the `slidy-url`, `slideous-url`, `revealjs-url`, or `s5-url`-variables; see [Variables for HTML slides], above.) For-DZSlides, the (relatively short) JavaScript and CSS are included-in the file by default.--With all HTML slide formats, the `--self-contained` option can-be used to produce a single file that contains all of the data-necessary to display the slide show, including linked scripts,-stylesheets, images, and videos.--To produce a PDF slide show using beamer, type--    pandoc -t beamer habits.txt -o habits.pdf--Note that a reveal.js slide show can also be converted to a PDF-by printing it to a file from the browser.--To produce a PowerPoint slide show, type--    pandoc habits.txt -o habits.pptx--## Structuring the slide show--By default, the *slide level* is the highest heading level in-the hierarchy that is followed immediately by content, and not another-heading, somewhere in the document. In the example above, level-1 headings-are always followed by level-2 headings, which are followed by content,-so the slide level is 2. This default can be overridden using the-`--slide-level` option.--The document is carved up into slides according to the following-rules:--  * A horizontal rule always starts a new slide.--  * A heading at the slide level always starts a new slide.--  * Headings *below* the slide level in the hierarchy create-    headings *within* a slide.  (In beamer, a "block" will be-    created.  If the heading has the class `example`, an-    `exampleblock` environment will be used; if it has the class-    `alert`, an `alertblock` will be used; otherwise a regular-    `block` will be used.)--  * Headings *above* the slide level in the hierarchy create-    "title slides," which just contain the section title-    and help to break the slide show into sections.-    Non-slide content under these headings will be included-    on the title slide (for HTML slide shows) or in a-    subsequent slide with the same title (for beamer).--  * A title page is constructed automatically from the document's title-    block, if present. (In the case of beamer, this can be disabled-    by commenting out some lines in the default template.)--These rules are designed to support many different styles of slide show. If-you don't care about structuring your slides into sections and subsections,-you can either just use level-1 headings for all slides (in that case, level 1-will be the slide level) or you can set `--slide-level=0`.--Note:  in reveal.js slide shows, if slide level is 2, a two-dimensional-layout will be produced, with level-1 headings building horizontally-and level-2 headings building vertically. It is not recommended that-you use deeper nesting of section levels with reveal.js unless you set-`--slide-level=0` (which lets reveal.js produce a one-dimensional layout-and only interprets horizontal rules as slide boundaries).--### PowerPoint layout choice--When creating slides, the pptx writer chooses from a number of pre-defined-layouts, based on the content of the slide:--Title Slide-:   This layout is used for the initial slide, which is generated and-    filled from the metadata fields `date`, `author`, and `title`, if-    they are present.--Section Header-:   This layout is used for what pandoc calls “title slides”, i.e.-    slides which start with a header which is above the slide level in-    the hierarchy.--Two Content-:   This layout is used for two-column slides, i.e. slides containing a-    div with class `columns` which contains at least two divs with class-    `column`.--Comparison-:   This layout is used instead of “Two Content” for any two-column-    slides in which at least one column contains text followed by-    non-text (e.g. an image or a table).--Content with Caption-:   This layout is used for any non-two-column slides which contain text-    followed by non-text (e.g. an image or a table).--Blank-:   This layout is used for any slides which only contain blank content,-    e.g. a slide containing only speaker notes, or a slide containing-    only a non-breaking space.--Title and Content-:   This layout is used for all slides which do not match the criteria-    for another layout.--These layouts are chosen from the default pptx reference doc included with-pandoc, unless an alternative reference doc is specified using-`--reference-doc`.--## Incremental lists--By default, these writers produce lists that display "all at once."-If you want your lists to display incrementally (one item at a time),-use the `-i` option. If you want a particular list to depart from the-default, put it in a `div` block with class `incremental` or-`nonincremental`. So, for example, using the `fenced div` syntax, the-following would be incremental regardless of the document default:--    ::: incremental--    - Eat spaghetti-    - Drink wine--    :::--or--    ::: nonincremental--    - Eat spaghetti-    - Drink wine--    :::--While using `incremental` and `nonincremental` divs is the-recommended method of setting incremental lists on a per-case basis,-an older method is also supported: putting lists inside a blockquote-will depart from the document default (that is, it will display-incrementally without the `-i` option and all at once with the `-i`-option):--    > - Eat spaghetti-    > - Drink wine--Both methods allow incremental and nonincremental lists to be mixed-in a single document.--If you want to include a block-quoted list, you can work around-this behavior by putting the list inside a fenced div, so that-it is not the direct child of the block quote:--    > ::: wrapper-    > - a-    > - list in a quote-    > :::--## Inserting pauses--You can add "pauses" within a slide by including a paragraph containing-three dots, separated by spaces:--    # Slide with a pause--    content before the pause--    . . .--    content after the pause--Note: this feature is not yet implemented for PowerPoint output.--## Styling the slides--You can change the style of HTML slides by putting customized CSS files-in `$DATADIR/s5/default` (for S5), `$DATADIR/slidy` (for Slidy),-or `$DATADIR/slideous` (for Slideous),-where `$DATADIR` is the user data directory (see `--data-dir`, above).-The originals may be found in pandoc's system data directory (generally-`$CABALDIR/pandoc-VERSION/s5/default`). Pandoc will look there for any-files it does not find in the user data directory.--For dzslides, the CSS is included in the HTML file itself, and may-be modified there.--All [reveal.js configuration options] can be set through variables.-For example, themes can be used by setting the `theme` variable:--    -V theme=moon--Or you can specify a custom stylesheet using the `--css` option.--To style beamer slides, you can specify a `theme`, `colortheme`,-`fonttheme`, `innertheme`, and `outertheme`, using the `-V` option:--    pandoc -t beamer habits.txt -V theme:Warsaw -o habits.pdf--Note that heading attributes will turn into slide attributes-(on a `<div>` or `<section>`) in HTML slide formats, allowing you-to style individual slides.  In beamer, a number of heading-classes and attributes are recognized as frame options and-will be passed through as options to the frame: see-[Frame attributes in beamer], below.--## Speaker notes--Speaker notes are supported in reveal.js, PowerPoint (pptx),-and beamer output. You can add notes to your Markdown document thus:--    ::: notes--    This is my note.--    - It can contain Markdown-    - like this list--    :::--To show the notes window in reveal.js, press `s` while viewing the-presentation. Speaker notes in PowerPoint will be available, as usual,-in handouts and presenter view.--Notes are not yet supported for other slide formats, but the notes-will not appear on the slides themselves.--## Columns--To put material in side by side columns, you can use a native-div container with class `columns`, containing two or more div-containers with class `column` and a `width` attribute:--    :::::::::::::: {.columns}-    ::: {.column width="40%"}-    contents...-    :::-    ::: {.column width="60%"}-    contents...-    :::-    ::::::::::::::--### Additional columns attributes in beamer--The div containers with classes `columns` and `column` can optionally have-an `align` attribute.-The class `columns` can optionally have a `totalwidth` attribute or an-`onlytextwidth` class.--    :::::::::::::: {.columns align=center totalwidth=8em}-    ::: {.column width="40%"}-    contents...-    :::-    ::: {.column width="60%" align=bottom}-    contents...-    :::-    ::::::::::::::--The `align` attributes on `columns` and `column` can be used with the-values `top`, `top-baseline`, `center` and `bottom` to vertically align-the columns. It defaults to `top` in `columns`.--The `totalwidth` attribute limits the width of the columns to the given value.--    :::::::::::::: {.columns align=top .onlytextwidth}-    ::: {.column width="40%" align=center}-    contents...-    :::-    ::: {.column width="60%"}-    contents...-    :::-    ::::::::::::::--The class `onlytextwidth` sets the `totalwidth` to `\textwidth`.--See Section 12.7 of the [Beamer User's Guide] for more details.--## Frame attributes in beamer--Sometimes it is necessary to add the LaTeX `[fragile]` option to-a frame in beamer (for example, when using the `minted` environment).-This can be forced by adding the `fragile` class to the heading-introducing the slide:--    # Fragile slide {.fragile}--All of the other frame attributes described in Section 8.1 of-the [Beamer User's Guide] may also be used: `allowdisplaybreaks`,-`allowframebreaks`, `b`, `c`, `s`, `t`, `environment`, `label`, `plain`,-`shrink`, `standout`, `noframenumbering`, `squeeze`.-`allowframebreaks` is recommended especially for bibliographies, as-it allows multiple slides to be created if the content overfills the-frame:--    # References {.allowframebreaks}--In addition, the `frameoptions` attribute may be used to-pass arbitrary frame options to a beamer slide:--    # Heading {frameoptions="squeeze,shrink,customoption=foobar"}--## Background in reveal.js, beamer, and pptx--Background images can be added to self-contained reveal.js slide shows,-beamer slide shows, and pptx slide shows.--### On all slides (beamer, reveal.js, pptx)--With beamer and reveal.js, the configuration option `background-image` can be-used either in the YAML metadata block or as a command-line variable to get the same image on every slide.--Note that for reveal.js, the `background-image` will be used as-a `parallaxBackgroundImage` (see below).--For pptx, you can use a [reference doc](#option--reference-doc) in which-background images have been set on the [relevant-layouts](#powerpoint-layout-choice).--#### `parallaxBackgroundImage` (reveal.js)--For reveal.js, there is also the reveal.js-native option-`parallaxBackgroundImage`, which produces a parallax scrolling background.-You must also set `parallaxBackgroundSize`, and can optionally set-`parallaxBackgroundHorizontal`-and `parallaxBackgroundVertical` to configure the scrolling behaviour.-See the [reveal.js-documentation](https://revealjs.com/backgrounds/#parallax-background)-for more details about the meaning of these options.--In reveal.js's overview mode, the parallaxBackgroundImage will show up-only on the first slide.--### On individual slides (reveal.js, pptx)--To set an image for a particular reveal.js or pptx slide, add-`{background-image="/path/to/image"}` to the first slide-level heading on the-slide (which may even be empty).--As the [HTML writers pass unknown attributes-through](#extension-link_attributes), other reveal.js background settings also-work on individual slides, including `background-size`, `background-repeat`,-`background-color`, `transition`, and `transition-speed`. (The `data-` prefix-will automatically be added.)--Note: `data-background-image` is also supported in pptx for consistency with-reveal.js – if `background-image` isn’t found, `data-background-image` will be-checked.--### On the title slide (reveal.js, pptx)--To add a background image to the automatically generated title slide for-reveal.js, use the `title-slide-attributes` variable in the YAML metadata block.-It must contain a map of attribute names and values. (Note that the `data-`-prefix is required here, as it isn’t added automatically.)--For pptx, pass a [reference doc](#option--reference-doc) with the background-image set on the “Title Slide” layout.--### Example (reveal.js)--```-----title: My Slide Show-parallaxBackgroundImage: /path/to/my/background_image.png-title-slide-attributes:-    data-background-image: /path/to/title_image.png-    data-background-size: contain------## Slide One--Slide 1 has background_image.png as its background.--## {background-image="/path/to/special_image.jpg"}--Slide 2 has a special image for its background, even though the heading has no content.-```--# EPUBs--## EPUB Metadata--EPUB metadata may be specified using the `--epub-metadata` option, but-if the source document is Markdown, it is better to use a [YAML metadata-block][Extension: `yaml_metadata_block`].  Here is an example:--    ----    title:-    - type: main-      text: My Book-    - type: subtitle-      text: An investigation of metadata-    creator:-    - role: author-      text: John Smith-    - role: editor-      text: Sarah Jones-    identifier:-    - scheme: DOI-      text: doi:10.234234.234/33-    publisher:  My Press-    rights: © 2007 John Smith, CC BY-NC-    ibooks:-      version: 1.3.4-    ...--The following fields are recognized:--`identifier`-  ~ 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`.--`title`-  ~ Either a string value, or an object with fields `file-as` and-    `type`, or a list of such objects.  Valid values for `type` are-    `main`, `subtitle`, `short`, `collection`, `edition`, `extended`.--`creator`-  ~ Either a string value, or an object with fields `role`, `file-as`,-    and `text`, or a list of such objects.  Valid values for `role` are-    [MARC relators], but-    pandoc will attempt to translate the human-readable versions-    (like "author" and "editor") to the appropriate marc relators.--`contributor`-  ~ Same format as `creator`.--`date`-  ~ A string value in `YYYY-MM-DD` format.  (Only the year is necessary.)-    Pandoc will attempt to convert other common date formats.--`lang` (or legacy: `language`)-  ~ A string value in [BCP 47] format.  Pandoc will default to the local-    language if nothing is specified.--`subject`-  ~ Either a string value, or an object with fields `text`, `authority`,-    and `term`, or a list of such objects. Valid values for `authority`-    are either a [reserved authority value] (currently `AAT`, `BIC`,-    `BISAC`, `CLC`, `DDC`, `CLIL`, `EuroVoc`, `MEDTOP`, `LCSH`, `NDC`,-    `Thema`, `UDC`, and `WGS`) or an absolute IRI identifying a custom-    scheme. Valid values for `term` are defined by the scheme.--`description`-  ~ A string value.--`type`-  ~ A string value.--`format`-  ~ A string value.--`relation`-  ~ A string value.--`coverage`-  ~ A string value.--`rights`-  ~ A string value.--`belongs-to-collection`-  ~ A string value.  Identifies the name of a collection to which-    the EPUB Publication belongs.--`group-position`-  ~ The `group-position` field indicates the numeric position in which-    the EPUB Publication belongs relative to other works belonging to-    the same `belongs-to-collection` field.--`cover-image`-  ~ A string value (path to cover image).--`css` (or legacy: `stylesheet`)-  ~ A string value (path to CSS stylesheet).--`page-progression-direction`-  ~ Either `ltr` or `rtl`. Specifies the `page-progression-direction`-    attribute for the [`spine` element].--`accessModes`-  ~ An array of strings ([schema][accessibility schema]).-    Defaults to `["textual"]`.--`accessModeSufficient`-  ~ An array of strings ([schema][accessibility schema]).-    Defaults to `["textual"]`.--`accessibilityHazards`-  ~ An array of strings ([schema][accessibility schema]).-    Defaults to `["none"]`.--`accessibilityFeatures`-  ~ An array of strings ([schema][accessibility schema]).-    Defaults to--        - "alternativeText"-        - "readingOrder"-        - "structuralNavigation"-        - "tableOfContents"--`accessibilitySummary`-  ~ A string value.--`ibooks`-  ~ iBooks-specific metadata, with the following fields:--    - `version`: (string)-    - `specified-fonts`: `true`|`false` (default `false`)-    - `ipad-orientation-lock`: `portrait-only`|`landscape-only`-    - `iphone-orientation-lock`: `portrait-only`|`landscape-only`-    - `binding`: `true`|`false` (default `true`)-    - `scroll-axis`: `vertical`|`horizontal`|`default`--[accessibility schema]:  https://kb.daisy.org/publishing/docs/metadata/schema.org/index.html-[MARC relators]: https://loc.gov/marc/relators/relaterm.html-[reserved authority value]: https://idpf.github.io/epub-registries/authorities/-[`spine` element]: http://idpf.org/epub/301/spec/epub-publications.html#sec-spine-elem--## The `epub:type` attribute--For `epub3` output, you can mark up the heading that corresponds to an EPUB-chapter using the [`epub:type` attribute][epub-type]. For example, to set-the attribute to the value `prologue`, use this Markdown:--    # My chapter {epub:type=prologue}--Which will result in:--    <body epub:type="frontmatter">-      <section epub:type="prologue">-        <h1>My chapter</h1>--Pandoc will output `<body epub:type="bodymatter">`, unless-you use one of the following values, in which case either-`frontmatter` or `backmatter` will be output.--`epub:type` of first section      `epub:type` of body-----------------------------      -------------------prologue                          frontmatter-abstract                          frontmatter-acknowledgments                   frontmatter-copyright-page                    frontmatter-dedication                        frontmatter-credits                           frontmatter-keywords                          frontmatter-imprint                           frontmatter-contributors                      frontmatter-other-credits                     frontmatter-errata                            frontmatter-revision-history                  frontmatter-titlepage                         frontmatter-halftitlepage                     frontmatter-seriespage                        frontmatter-foreword                          frontmatter-preface                           frontmatter-frontispiece                      frontmatter-appendix                          backmatter-colophon                          backmatter-bibliography                      backmatter-index                             backmatter--[epub-type]: http://www.idpf.org/epub/31/spec/epub-contentdocs.html#sec-epub-type-attribute--## Linked media--By default, pandoc will download media referenced from any `<img>`, `<audio>`,-`<video>` or `<source>` element present in the generated EPUB,-and include it in the EPUB container, yielding a completely-self-contained EPUB.  If you want to link to external media resources-instead, use raw HTML in your source and add `data-external="1"` to the tag-with the `src` attribute.  For example:--    <audio controls="1">-      <source src="https://example.com/music/toccata.mp3"-              data-external="1" type="audio/mpeg">-      </source>-    </audio>--If the input format already is HTML then `data-external="1"` will work-as expected for `<img>` elements. Similarly, for Markdown, external-images can be declared with `![img](url){external=1}`. Note that this-only works for images; the other media elements have no native-representation in pandoc's AST and require the use of raw HTML.--## EPUB styling--By default, pandoc will include some basic styling-contained in its `epub.css` data file.  (To see this,-use `pandoc --print-default-data-file epub.css`.)-To use a different CSS file, just use the `--css` command-line option.  A few inline styles are defined in addition; these-are essential for correct formatting of pandoc's HTML output.--The `document-css` variable may be set if the more opinionated-styling of pandoc's default HTML templates is desired (and-in that case the variables defined in [Variables for HTML] may-be used to fine-tune the style).--# Chunked HTML--`pandoc -t chunkedhtml` will produce a zip archive of linked-HTML files, one for each section of the original document.-Internal links will automatically be adjusted to point to-the right place, images linked to under the working directory-will be incorporated, and navigation links will be added.-In addition, a JSON file `sitemap.json` will be included-describing the hierarchical structure of the files.--If an output file without an extension is specified, then-it will be interpreted as a directory and the zip archive-will be automatically unpacked into it (unless it already-exists, in which case an error will be raised).  Otherwise-a `.zip` file will be produced.--The navigation links can be customized by adjusting the-template.  By default, a table of contents is included only-on the top page. To include it on every page, set the-`toc` variable manually.--# Jupyter notebooks--When creating a [Jupyter notebook], pandoc will try to infer the-notebook structure.  Code blocks with the class `code` will be-taken as code cells, and intervening content will be taken as-Markdown cells.  Attachments will automatically be created for-images in Markdown cells. Metadata will be taken from the-`jupyter` metadata field.  For example:--````-----title: My notebook-jupyter:-  nbformat: 4-  nbformat_minor: 5-  kernelspec:-     display_name: Python 2-     language: python-     name: python2-  language_info:-     codemirror_mode:-       name: ipython-       version: 2-     file_extension: ".py"-     mimetype: "text/x-python"-     name: "python"-     nbconvert_exporter: "python"-     pygments_lexer: "ipython2"-     version: "2.7.15"------# Lorem ipsum--**Lorem ipsum** dolor sit amet, consectetur adipiscing elit. Nunc luctus-bibendum felis dictum sodales.--``` code-print("hello")-```--## Pyout--``` code-from IPython.display import HTML-HTML("""-<script>-console.log("hello");-</script>-<b>HTML</b>-""")-```--## Image--This image ![image](myimage.png) will be-included as a cell attachment.-````--If you want to add cell attributes, group cells differently, or-add output to code cells, then you need to include divs to-indicate the structure. You can use either [fenced-divs][Extension: `fenced_divs`] or [native divs][Extension:-`native_divs`] for this.  Here is an example:--````-:::::: {.cell .markdown}-# Lorem--**Lorem ipsum** dolor sit amet, consectetur adipiscing elit. Nunc luctus-bibendum felis dictum sodales.-::::::--:::::: {.cell .code execution_count=1}-``` {.python}-print("hello")-```--::: {.output .stream .stdout}-```-hello-```-:::-::::::--:::::: {.cell .code execution_count=2}-``` {.python}-from IPython.display import HTML-HTML("""-<script>-console.log("hello");-</script>-<b>HTML</b>-""")-```--::: {.output .execute_result execution_count=2}-```{=html}-<script>-console.log("hello");-</script>-<b>HTML</b>-hello-```-:::-::::::-````--If you include raw HTML or TeX in an output cell, use the-[raw attribute](#extension-raw_attribute), as shown-in the last cell of the example above.  Although pandoc can-process "bare" raw HTML and TeX, the result is often-interspersed raw elements and normal textual elements, and-in an output cell pandoc expects a single, connected raw-block.  To avoid using raw HTML or TeX except when-marked explicitly using raw attributes, we recommend-specifying the extensions `-raw_html-raw_tex+raw_attribute` when-translating between Markdown and ipynb notebooks.--Note that options and extensions that affect reading and-writing of Markdown will also affect Markdown cells in ipynb-notebooks.  For example, `--wrap=preserve` will preserve-soft line breaks in Markdown cells; `--markdown-headings=setext` will-cause Setext-style headings to be used; and `--preserve-tabs` will-prevent tabs from being turned to spaces.--# Syntax highlighting--Pandoc will automatically highlight syntax in [fenced code blocks] that-are marked with a language name.  The Haskell library [skylighting] is-used for highlighting. Currently highlighting is supported only for-HTML, EPUB, Docx, Ms, Man, and LaTeX/PDF output. To see a list-of language names that pandoc will recognize, type `pandoc---list-highlight-languages`.--The color scheme can be selected using the `--highlight-style` option.-The default color scheme is `pygments`, which imitates the default color-scheme used by the Python library pygments (though pygments is not actually-used to do the highlighting).  To see a list of highlight styles,-type `pandoc --list-highlight-styles`.--If you are not satisfied with the predefined styles, you can-use `--print-highlight-style` to generate a JSON `.theme` file which-can be modified and used as the argument to `--highlight-style`. To-get a JSON version of the `pygments` style, for example:--    pandoc --print-highlight-style pygments > my.theme--Then edit `my.theme` and use it like this:--    pandoc --highlight-style my.theme--If you are not satisfied with the built-in highlighting, or you-want to highlight a language that isn't supported, you can use the-`--syntax-definition` option to load a [KDE-style XML syntax definition-file](https://docs.kde.org/stable5/en/kate/katepart/highlight.html).-Before writing your own, have a look at KDE's [repository of syntax-definitions](https://github.com/KDE/syntax-highlighting/tree/master/data/syntax).--To disable highlighting, use the `--no-highlight` option.--[skylighting]: https://github.com/jgm/skylighting--# Custom Styles--Custom styles can be used in the docx and ICML formats.--## Output--By default, pandoc's docx and ICML output applies a predefined set of styles-for blocks such as paragraphs and block quotes, and uses largely default-formatting (italics, bold) for inlines. This will work for most-purposes, especially alongside a `reference.docx` file. However, if you-need to apply your own styles to blocks, or match a preexisting set of-styles, pandoc allows you to define custom styles for blocks and text-using `div`s and `span`s, respectively.--If you define a `div` or `span` with the attribute `custom-style`,-pandoc will apply your specified style to the contained elements (with-the exception of elements whose function depends on a style, like-headings, code blocks, block quotes, or links). So, for example, using-the `bracketed_spans` syntax,--    [Get out]{custom-style="Emphatically"}, he said.--would produce a docx file with "Get out" styled with character-style `Emphatically`. Similarly, using the `fenced_divs` syntax,--    Dickinson starts the poem simply:--    ::: {custom-style="Poetry"}-    | A Bird came down the Walk----    | He did not know I saw----    :::--would style the two contained lines with the `Poetry` paragraph style.--For docx output, styles will be defined in the output file as inheriting-from normal text, if the styles are not yet in your reference.docx.-If they are already defined, pandoc will not alter the definition.--This feature allows for greatest customization in conjunction with-[pandoc filters]. If you want all paragraphs after block quotes to be-indented, you can write a filter to apply the styles necessary. If you-want all italics to be transformed to the `Emphasis` character style-(perhaps to change their color), you can write a filter which will-transform all italicized inlines to inlines within an `Emphasis`-custom-style `span`.--For docx output, you don't need to enable any extensions for-custom styles to work.--[pandoc filters]: https://pandoc.org/filters.html--## Input--The docx reader, by default, only reads those styles that it can-convert into pandoc elements, either by direct conversion or-interpreting the derivation of the input document's styles.--By enabling the [`styles` extension](#ext-styles) in the docx reader-(`-f docx+styles`), you can produce output that maintains the styles-of the input document, using the `custom-style` class. Paragraph-styles are interpreted as divs, while character styles are interpreted-as spans.--For example, using the `custom-style-reference.docx` file in the test-directory, we have the following different outputs:--Without the `+styles` extension:--    $ pandoc test/docx/custom-style-reference.docx -f docx -t markdown-    This is some text.--    This is text with an *emphasized* text style. And this is text with a-    **strengthened** text style.--    > Here is a styled paragraph that inherits from Block Text.--And with the extension:--    $ pandoc test/docx/custom-style-reference.docx -f docx+styles -t markdown--    ::: {custom-style="First Paragraph"}-    This is some text.-    :::--    ::: {custom-style="Body Text"}-    This is text with an [emphasized]{custom-style="Emphatic"} text style.-    And this is text with a [strengthened]{custom-style="Strengthened"}-    text style.-    :::--    ::: {custom-style="My Block Style"}-    > Here is a styled paragraph that inherits from Block Text.-    :::--With these custom styles, you can use your input document as a-reference-doc while creating docx output (see below), and maintain the-same styles in your input and output files.--# Custom readers and writers--Pandoc can be extended with custom readers and writers written-in [Lua].  (Pandoc includes a Lua interpreter, so Lua need not-be installed separately.)--To use a custom reader or writer, simply specify the path to the-Lua script in place of the input or output format. For example:--    pandoc -t data/sample.lua-    pandoc -f my_custom_markup_language.lua -t latex -s--If the script is not found relative to the working directory,-it will be sought in the `custom` subdirectory of the user data-directory (see `--data-dir`).--A custom reader is a Lua script that defines one function,-Reader, which takes a string as input and returns a Pandoc-AST.  See the [Lua filters documentation] for documentation-of the functions that are available for creating pandoc-AST elements.  For parsing, the [lpeg] parsing library-is available by default. To see a sample custom reader:--    pandoc --print-default-data-file creole.lua--If you want your custom reader to have access to reader options-(e.g. the tab stop setting), you give your Reader function a-second `options` parameter.--A custom writer is a Lua script that defines a function-that specifies how to render each element in a Pandoc AST.-See the [djot-writer.lua] for a full-featured example.--Note that custom writers have no default template.  If you want-to use `--standalone` with a custom writer, you will need to-specify a template manually using `--template` or add a new-default template with the name-`default.NAME_OF_CUSTOM_WRITER.lua` to the `templates`-subdirectory of your user data directory (see [Templates]).--[Lua]: https://www.lua.org-[lpeg]:  http://www.inf.puc-rio.br/~roberto/lpeg/-[djot-writer.lua]: https://github.com/jgm/djot.lua/blob/main/djot-writer.lua--# Reproducible builds--Some of the document formats pandoc targets (such as EPUB,-docx, and ODT) include build timestamps in the generated document.-That means that the files generated on successive builds will-differ, even if the source does not.  To avoid this, set the-`SOURCE_DATE_EPOCH` environment variable, and the timestamp will-be taken from it instead of the current time.-`SOURCE_DATE_EPOCH` should contain an integer unix timestamp-(specifying the number of seconds since midnight UTC January 1, 1970).--Some document formats also include a unique identifier.  For-EPUB, this can be set explicitly by setting the `identifier`-metadata field (see [EPUB Metadata], above).--# Accessible PDFs and PDF archiving standards--PDF is a flexible format, and using PDF in certain contexts-requires additional conventions. For example, PDFs are not-accessible by default; they define how characters are placed on a-page but do not contain semantic information on the content.-However, it is possible to generate accessible PDFs, which use-tagging to add semantic information to the document.--Pandoc defaults to LaTeX to generate PDF. Tagging support in LaTeX-is in development and not readily available, so PDFs generated in-this way will always be untagged and not accessible. This means-that alternative engines must be used to generate accessible PDFs.--The PDF standards PDF/A and PDF/UA define further restrictions-intended to optimize PDFs for archiving and accessibility. Tagging-is commonly used in combination with these standards to ensure-best results.--Note, however, that standard compliance depends on many things,-including the colorspace of embedded images. Pandoc cannot check-this, and external programs must be used to ensure that generated-PDFs are in compliance.--## ConTeXt--ConTeXt always produces tagged PDFs, but the quality depends on-the input. The default ConTeXt markup generated by pandoc is-optimized for readability and reuse, not tagging. Enable the-[`tagging`](#extension--tagging) format extension to force markup-that is optimized for tagging. This can be combined with the-`pdfa` variable to generate standard-compliant PDFs. E.g.:--    pandoc --to=context+tagging -V pdfa=3a--A recent `context` version should be used, as older versions-contained a bug that lead to invalid PDF metadata.--## WeasyPrint--The HTML-based engine WeasyPrint includes experimental support for-PDF/A and PDF/UA since version 57. Tagged PDFs can created with--    pandoc --pdf-engine=weasyprint \-           --pdf-engine-opt=--pdf-variant=pdf/ua-1 ...--The feature is experimental and standard compliance should not be-assumed.--## Prince XML--The non-free HTML-to-PDf converter `prince` has extensive support-for various PDF standards as well as tagging. E.g.:--    pandoc --pdf-engine=prince \-           --pdf-engine-opt=--tagged-pdf ...--See the prince documentation for more info.--## Word Processors--Word processors like LibreOffice and MS Word can also be used to-generate standardized and tagged PDF output. Pandoc does not-support direct conversions via these tools. However, pandoc can-convert a document to a `docx` or `odt` file, which can then be-opened and converted to PDF with the respective word processor.-See the documentation for [Word][word-accessible-pdfs] and-[LibreOffice][lo-pdf-export].--[word-accessible-pdfs]: https://support.microsoft.com/en-us/office/create-accessible-pdfs-064625e0-56ea-4e16-ad71-3aa33bb4b7ed-[lo-pdf-export]: https://help.libreoffice.org/7.1/en-US/text/shared/01/ref_pdf_export_general.html---# Running pandoc as a web server--If you rename (or symlink) the pandoc executable to-`pandoc-server`, or if you call pandoc with `server` as the first-argument, it will start up a web server with a JSON API. This-server exposes most of the conversion functionality of pandoc. For-full documentation, see the [pandoc-server] man page.--If you rename (or symlink) the pandoc executable to-`pandoc-server.cgi`, it will function as a CGI program-exposing the same API as `pandoc-server`.--`pandoc-server` is designed to be maximally secure; it uses-Haskell's type system to provide strong guarantees that no I/O-will be performed on the server during pandoc conversions.--[pandoc-server]: https://github.com/jgm/pandoc/blob/master/doc/pandoc-server.md--# Running pandoc as a Lua interpreter--Calling the pandoc executable under the name `pandoc-lua` or with-`lua` as the first argument will make it function as a standalone-Lua interpreter. The behavior is mostly identical to that of the-[standalone `lua` executable][lua standalone], version 5.4.-However, there is no REPL yet, and the `-i` option has no effect.-For full documentation, see the [pandoc-lua] man page.--[lua standalone]: https://www.lua.org/manual/5.4/manual.html#7-[pandoc-lua]: https://github.com/jgm/pandoc/blob/master/doc/pandoc-lua.md--# A note on security--1. Although pandoc itself will not create or modify any files other-   than those you explicitly ask it create (with the exception-   of temporary files used in producing PDFs), a filter or custom-   writer could in principle do anything on your file system. Please-   audit filters and custom writers very carefully before using them.--2. Several input formats (including HTML, Org, and RST) support `include`-   directives that allow the contents of a file to be included in the-   output. An untrusted attacker could use these to view the contents of-   files on the file system.  (Using the `--sandbox` option can-   protect against this threat.)--3. Several output formats (including RTF, FB2, HTML with-   `--self-contained`, EPUB, Docx, and ODT) will embed encoded-   or raw images into the output file.  An untrusted attacker-   could exploit this to view the contents of non-image files on the-   file system.  (Using the `--sandbox` option can protect-   against this threat, but will also prevent including images in-   these formats.)--4. If your application uses pandoc as a Haskell library (rather than-   shelling out to the executable), it is possible to use it in a mode-   that fully isolates pandoc from your file system, by running the-   pandoc operations in the `PandocPure` monad. See the document-   [Using the pandoc API](https://pandoc.org/using-the-pandoc-api.html)-   for more details. (This corresponds to the use of the `--sandbox`-   option on the command line.)--5. Pandoc's parsers can exhibit pathological performance on some-   corner cases.  It is wise to put any pandoc operations under-   a timeout, to avoid DOS attacks that exploit these issues.-   If you are using the pandoc executable, you can add the-   command line options `+RTS -M512M -RTS` (for example) to limit-   the heap size to 512MB.  Note that the `commonmark` parser-   (including `commonmark_x` and `gfm`) is much less vulnerable-   to pathological performance than the `markdown` parser, so-   it is a better choice when processing untrusted input.--6. The HTML generated by pandoc is not guaranteed to be safe.-   If `raw_html` is enabled for the Markdown input, users can-   inject arbitrary HTML.  Even if `raw_html` is disabled,-   users can include dangerous content in URLs and attributes.-   To be safe, you should run all HTML generated from untrusted-   user input through an HTML sanitizer.--# Authors--Copyright 2006--2022 John MacFarlane (jgm@berkeley.edu). Released+date: 2026-06-03+---++# Synopsis++`pandoc` [*options*] [*input-file*]...++# Description++Pandoc is a [Haskell] library for converting from one markup format to+another, and a command-line tool that uses this library.++Pandoc can convert between numerous markup and word processing formats,+including, but not limited to, various flavors of [Markdown], [HTML],+[LaTeX] and [Word docx]. For the full lists of input and output formats,+see the `--from` and `--to` [options below][General options].+Pandoc can also produce [PDF] output: see [creating a PDF], below.++Pandoc's enhanced version of Markdown includes syntax for [tables],+[definition lists], [metadata blocks], [footnotes], [citations], [math],+and much more.  See below under [Pandoc's Markdown].++Pandoc has a modular design: it consists of a set of readers, which parse+text in a given format and produce a native representation of the document+(an _abstract syntax tree_ or AST), and a set of writers, which convert+this native representation into a target format. Thus, adding an input+or output format requires only adding a reader or writer. Users can also+run custom [pandoc filters] to modify the intermediate AST.++Because pandoc's intermediate representation of a document is less+expressive than many of the formats it converts between, one should+not expect perfect conversions between every format and every other.+Pandoc attempts to preserve the structural elements of a document, but+not formatting details such as margin size.  And some document elements,+such as complex tables, may not fit into pandoc's simple document+model.  While conversions from pandoc's Markdown to all formats aspire+to be perfect, conversions from formats more expressive than pandoc's+Markdown can be expected to be lossy.++## Using pandoc++If no *input-files* are specified, input is read from *stdin*.+Output goes to *stdout* by default. For output to a file,+use the `-o`/`--output` option:++    pandoc -o output.html input.txt++By default, pandoc produces a document fragment. To produce a standalone+document (e.g. a valid HTML file including `<head>` and `<body>`),+use the `-s` or `--standalone` flag:++    pandoc -s -o output.html input.txt++For more information on how standalone documents are produced, see+[Templates] below.++If multiple input files are given, pandoc will concatenate them all (with+blank lines between them) before parsing. (Use `--file-scope` to parse files+individually.)++## Specifying formats++The format of the input and output can be specified explicitly using+command-line options.  The input format can be specified using the+`-f/--from` option, the output format using the `-t/--to` option.+Thus, to convert `hello.txt` from Markdown to LaTeX, you could type:++    pandoc -f markdown -t latex hello.txt++To convert `hello.html` from HTML to Markdown:++    pandoc -f html -t markdown hello.html++Supported input and output formats are listed below under [Options]+(see `-f` for input formats and `-t` for output formats).  You+can also use `pandoc --list-input-formats` and+`pandoc --list-output-formats` to print lists of supported+formats.++If the input or output format is not specified explicitly, pandoc+will attempt to guess it from the extensions of the filenames.+Thus, for example,++    pandoc -o hello.tex hello.txt++will convert `hello.txt` from Markdown to LaTeX.  If no output file+is specified (so that output goes to *stdout*), or if the output file's+extension is unknown, the output format will default to HTML.+If no input file is specified (so that input comes from *stdin*), or+if the input files' extensions are unknown, the input format will+be assumed to be Markdown.++## Character encoding++Pandoc uses the UTF-8 character encoding for both input and output.+If your local character encoding is not UTF-8, you+should pipe input and output through [`iconv`]:++    iconv -t utf-8 input.txt | pandoc | iconv -f utf-8++Note that in some output formats (such as HTML, LaTeX, ConTeXt,+RTF, OPML, DocBook, and Texinfo), information about+the character encoding is included in the document header, which+will only be included if you use the `-s/--standalone` option.++[`iconv`]: https://www.gnu.org/software/libiconv/++## Creating a PDF++To produce a PDF, specify an output file with a `.pdf` extension:++    pandoc test.txt -o test.pdf++By default, pandoc will use LaTeX to create the PDF, which requires+that a LaTeX engine be installed (see `--pdf-engine` below).+Alternatively, pandoc can use ConTeXt, roff ms, or HTML as an+intermediate format.  To do this, specify an output file with a+`.pdf` extension, as before, but add the `--pdf-engine` option+or `-t context`, `-t html`, or `-t ms` to the command line.+The tool used to generate the PDF from the intermediate format+may be specified using `--pdf-engine`.++You can control the PDF style using variables, depending on+the intermediate format used: see [variables for LaTeX],+[variables for ConTeXt], [variables for `wkhtmltopdf`],+[variables for ms].  When HTML is used as an intermediate+format, the output can be styled using `--css`.++To debug the PDF creation, it can be useful to look at the intermediate+representation: instead of `-o test.pdf`, use for example `-s -o test.tex`+to output the generated LaTeX. You can then test it with `pdflatex test.tex`.++When using LaTeX, the following packages need to be available+(they are included with all recent versions of [TeX Live]):+[`amsfonts`], [`amsmath`], [`lm`], [`unicode-math`],+[`iftex`], [`listings`] (if the+`--listings` option is used), [`fancyvrb`], [`longtable`],+[`booktabs`], [`multirow`] (if the document contains a table with+cells that cross multiple rows), [`graphicx`] (if the document+contains images), [`bookmark`], [`xcolor`],+[`soul`], [`geometry`] (with the `geometry` variable set),+[`setspace`] (with `linestretch`), and+[`babel`] (with `lang`).  If `CJKmainfont` is set, [`xeCJK`]+is needed if `xelatex` is used, else [`luatexja`] is needed if+`lualatex` is used. [`framed`] is required if code is highlighted in a+scheme that use a colored background. The use of `xelatex` or+`lualatex` as the PDF engine requires [`fontspec`]. `lualatex`+uses [`selnolig`] and [`lua-ul`]. `xelatex` uses [`bidi`] (with+the `dir` variable set).+If the `mathspec` variable is set, `xelatex` will use [`mathspec`]+instead of [`unicode-math`].  The [`csquotes`] package will be used+for [typography] if the `csquotes` variable or metadata field is+set to a true value.  The [`natbib`], [`biblatex`], [`bibtex`],+and [`biber`] packages can optionally be used for [citation+rendering].  If math with `\cancel`, `\bcancel`, or `\xcancel`+is used, the [`cancel`] package is needed.+The following packages will be used to improve+output quality if present, but pandoc does not require them to+be present: [`upquote`] (for straight quotes in verbatim+environments), [`microtype`] (for better spacing adjustments),+[`parskip`] (for better inter-paragraph spaces), [`xurl`] (for+better line breaks in URLs), and [`footnotehyper`] or+[`footnote`] (to allow footnotes in tables).++[TeX Live]: https://www.tug.org/texlive/+[`amsfonts`]: https://ctan.org/pkg/amsfonts+[`amsmath`]: https://ctan.org/pkg/amsmath+[`babel`]: https://ctan.org/pkg/babel+[`biber`]: https://ctan.org/pkg/biber+[`biblatex`]: https://ctan.org/pkg/biblatex+[`bibtex`]: https://ctan.org/pkg/bibtex+[`bidi`]: https://ctan.org/pkg/bidi+[`bookmark`]: https://ctan.org/pkg/bookmark+[`booktabs`]: https://ctan.org/pkg/booktabs+[`csquotes`]: https://ctan.org/pkg/csquotes+[`fancyvrb`]: https://ctan.org/pkg/fancyvrb+[`fontspec`]: https://ctan.org/pkg/fontspec+[`footnote`]: https://ctan.org/pkg/footnote+[`footnotehyper`]: https://ctan.org/pkg/footnotehyper+[`framed`]: https://ctan.org/pkg/framed+[`geometry`]: https://ctan.org/pkg/geometry+[`graphicx`]: https://ctan.org/pkg/graphicx+[`cancel`]: https://ctan.org/pkg/cancel+[`hyperref`]: https://ctan.org/pkg/hyperref+[`iftex`]: https://ctan.org/pkg/iftex+[`listings`]: https://ctan.org/pkg/listings+[`lm`]: https://ctan.org/pkg/lm+[`lua-ul`]: https://ctan.org/pkg/lua-ul+[`luatexja`]: https://ctan.org/pkg/luatexja+[`longtable`]: https://ctan.org/pkg/longtable+[`mathspec`]: https://ctan.org/pkg/mathspec+[`microtype`]: https://ctan.org/pkg/microtype+[`multirow`]: https://ctan.org/pkg/multirow+[`natbib`]: https://ctan.org/pkg/natbib+[`parskip`]: https://ctan.org/pkg/parskip+[`polyglossia`]: https://ctan.org/pkg/polyglossia+[`prince`]: https://www.princexml.com/+[`setspace`]: https://ctan.org/pkg/setspace+[`soul`]: https://ctan.org/pkg/soul+[`unicode-math`]: https://ctan.org/pkg/unicode-math+[`upquote`]: https://ctan.org/pkg/upquote+[`weasyprint`]: https://weasyprint.org+[`wkhtmltopdf`]: https://wkhtmltopdf.org+[`xcolor`]: https://ctan.org/pkg/xcolor+[`xeCJK`]: https://ctan.org/pkg/xecjk+[`xurl`]: https://ctan.org/pkg/xurl+[`selnolig`]: https://ctan.org/pkg/selnolig++++## Reading from the Web++Instead of an input file, an absolute URI may be given. In this case+pandoc will fetch the content using HTTP:++    pandoc -f html -t markdown https://www.fsf.org++It is possible to supply a custom User-Agent string or other+header when requesting a document from a URL:++    pandoc -f html -t markdown --request-header User-Agent:"Mozilla/5.0" \+      https://www.fsf.org++# Options++## General options {.options}++`-f` *FORMAT*, `-r` *FORMAT*, `--from=`*FORMAT*, `--read=`*FORMAT*++:   Specify input format.  *FORMAT* can be:++    ::: {#input-formats}+    - `asciidoc` ([AsciiDoc] markup)+    - `bibtex` ([BibTeX] bibliography)+    - `biblatex` ([BibLaTeX] bibliography)+    - `bits` ([BITS] XML, alias for `jats`)+    - `commonmark` ([CommonMark] Markdown)+    - `commonmark_x` ([CommonMark] Markdown with extensions)+    - `creole` ([Creole 1.0])+    - `csljson` ([CSL JSON] bibliography)+    - `csv` ([CSV] table)+    - `tsv` ([TSV] table)+    - `djot` ([Djot markup])+    - `docbook` ([DocBook])+    - `docx` ([Word docx])+    - `dokuwiki` ([DokuWiki markup])+    - `endnotexml` ([EndNote XML bibliography])+    - `epub` ([EPUB])+    - `fb2` ([FictionBook2] e-book)+    - `gfm` ([GitHub-Flavored Markdown]),+      or the deprecated and less accurate `markdown_github`;+      use [`markdown_github`](#markdown-variants) only+      if you need extensions not supported in [`gfm`](#markdown-variants).+    - `haddock` ([Haddock markup])+    - `html` ([HTML])+    - `ipynb` ([Jupyter notebook])+    - `jats` ([JATS] XML)+    - `jira` ([Jira]/Confluence wiki markup)+    - `json` (JSON version of native AST)+    - `latex` ([LaTeX])+    - `markdown` ([Pandoc's Markdown])+    - `markdown_mmd` ([MultiMarkdown])+    - `markdown_phpextra` ([PHP Markdown Extra])+    - `markdown_strict` (original unextended [Markdown])+    - `mediawiki` ([MediaWiki markup])+    - `man` ([roff man])+    - `mdoc` ([mdoc] manual page markup)+    - `muse` ([Muse])+    - `native` (native Haskell)+    - `odt` ([OpenDocument text document][ODT])+    - `opml` ([OPML])+    - `org` ([Emacs Org mode])+    - `pod` (Perl's [Plain Old Documentation])+    - `pptx` ([PowerPoint])+    - `ris` ([RIS] bibliography)+    - `rtf` ([Rich Text Format])+    - `rst` ([reStructuredText])+    - `t2t` ([txt2tags])+    - `textile` ([Textile])+    - `tikiwiki` ([TikiWiki markup])+    - `twiki` ([TWiki markup])+    - `typst` ([typst])+    - `vimwiki` ([Vimwiki])+    - `xlsx` ([Excel spreadsheet][XLSX])+    - `xml` (XML version of native AST)+    - the path of a custom Lua reader, see [Custom readers and writers] below+    :::++    Extensions can be individually enabled or disabled by+    appending `+EXTENSION` or `-EXTENSION` to the format name.+    See [Extensions] below, for a list of extensions and+    their names.  See `--list-input-formats` and `--list-extensions`,+    below.++`-t` *FORMAT*, `-w` *FORMAT*, `--to=`*FORMAT*, `--write=`*FORMAT*++:   Specify output format.  *FORMAT* can be:++    ::: {#output-formats}+    - `ansi` (text with [ANSI escape codes], for terminal viewing)+    - `asciidoc` (modern [AsciiDoc] as interpreted by [AsciiDoctor])+    - `asciidoc_legacy` ([AsciiDoc] as interpreted by [`asciidoc-py`]).+    - `asciidoctor` (deprecated synonym for `asciidoc`)+    - `bbcode` [BBCode]+    - `bbcode_fluxbb` [BBCode (FluxBB)]+    - `bbcode_phpbb` [BBCode (phpBB)]+    - `bbcode_steam` [BBCode (Steam)]+    - `bbcode_hubzilla` [BBCode (Hubzilla)]+    - `bbcode_xenforo` [BBCode (xenForo)]+    - `beamer` ([LaTeX beamer][`beamer`] slide show)+    - `bibtex` ([BibTeX] bibliography)+    - `biblatex` ([BibLaTeX] bibliography)+    - `chunkedhtml` (zip archive of multiple linked HTML files)+    - `commonmark` ([CommonMark] Markdown)+    - `commonmark_x` ([CommonMark] Markdown with extensions)+    - `context` ([ConTeXt])+    - `csljson` ([CSL JSON] bibliography)+    - `djot` ([Djot markup])+    - `docbook` or `docbook4` ([DocBook] 4)+    - `docbook5` (DocBook 5)+    - `docx` ([Word docx])+    - `dokuwiki` ([DokuWiki markup])+    - `epub` or `epub3` ([EPUB] v3 book)+    - `epub2` (EPUB v2)+    - `fb2` ([FictionBook2] e-book)+    - `gfm` ([GitHub-Flavored Markdown]),+      or the deprecated and less accurate `markdown_github`;+      use [`markdown_github`](#markdown-variants) only+      if you need extensions not supported in [`gfm`](#markdown-variants).+    - `haddock` ([Haddock markup])+    - `html` or `html5` ([HTML], i.e. [HTML5]/XHTML [polyglot markup])+    - `html4` ([XHTML] 1.0 Transitional)+    - `icml` ([InDesign ICML])+    - `ipynb` ([Jupyter notebook])+    - `jats_archiving` ([JATS] XML, Archiving and Interchange Tag Set)+    - `jats_articleauthoring` ([JATS] XML, Article Authoring Tag Set)+    - `jats_publishing` ([JATS] XML, Journal Publishing Tag Set)+    - `jats` (alias for `jats_archiving`)+    - `jira` ([Jira]/Confluence wiki markup)+    - `json` (JSON version of native AST)+    - `latex` ([LaTeX])+    - `man` ([roff man])+    - `markdown` ([Pandoc's Markdown])+    - `markdown_mmd` ([MultiMarkdown])+    - `markdown_phpextra` ([PHP Markdown Extra])+    - `markdown_strict` (original unextended [Markdown])+    - `markua` ([Markua])+    - `mediawiki` ([MediaWiki markup])+    - `ms` ([roff ms])+    - `muse` ([Muse])+    - `native` (native Haskell)+    - `odt` ([OpenDocument text document][ODT])+    - `opml` ([OPML])+    - `opendocument` ([OpenDocument XML])+    - `org` ([Emacs Org mode])+    - `pdf` ([PDF])+    - `plain` (plain text)+    - `pptx` ([PowerPoint] slide show)+    - `rst` ([reStructuredText])+    - `rtf` ([Rich Text Format])+    - `texinfo` ([GNU Texinfo])+    - `textile` ([Textile])+    - `slideous` ([Slideous] HTML and JavaScript slide show)+    - `slidy` ([Slidy] HTML and JavaScript slide show)+    - `dzslides` ([DZSlides] HTML5 + JavaScript slide show)+    - `revealjs` ([reveal.js] HTML5 + JavaScript slide show)+    - `s5` ([S5] HTML and JavaScript slide show)+    - `tei` ([TEI Simple])+    - `typst` ([typst])+    - `vimdoc` ([Vimdoc])+    - `xml` (XML version of native AST)+    - `xwiki` ([XWiki markup])+    - `zimwiki` ([ZimWiki markup])+    - the path of a custom Lua writer, see [Custom readers and writers] below+    :::++    Note that `odt`, `docx`, `epub`, and `pdf` output will not be directed+    to *stdout* unless forced with `-o -`.++    Extensions can be individually enabled or+    disabled by appending `+EXTENSION` or `-EXTENSION` to the format+    name.  See [Extensions] below, for a list of extensions and their+    names.  See `--list-output-formats` and `--list-extensions`, below.++`-o` *FILE*, `--output=`*FILE*++:   Write output to *FILE* instead of *stdout*.  If *FILE* is+    `-`, output will go to *stdout*, even if a non-textual format+    (`docx`, `odt`, `epub2`, `epub3`) is specified.  If the+    output format is `chunkedhtml` and *FILE* has no extension,+    then instead of producing a `.zip` file pandoc will create+    a directory *FILE* and unpack the zip archive there+    (unless *FILE* already exists, in which case an error+    will be raised).++`--data-dir=`*DIRECTORY*++:   Specify the user data directory to search for pandoc data files.+    If this option is not specified, the default user data directory+    will be used.  On \*nix and macOS systems this will be the `pandoc`+    subdirectory of the XDG data directory (by default,+    `$HOME/.local/share`, overridable by setting the `XDG_DATA_HOME`+    environment variable).  If that directory does not exist and+    `$HOME/.pandoc` exists, it will be used (for backwards compatibility).+    On Windows the default user data directory is `%APPDATA%\pandoc`.+    You can find the default user data directory on your system by+    looking at the output of `pandoc --version`.+    Data files placed in this directory (for example, `reference.odt`,+    `reference.docx`, `epub.css`, `templates`) will override+    pandoc's normal defaults.  (Note that the user data directory+    is not created by pandoc, so you will need to create it yourself+    if you want to make use of it.)++`-d` *FILE*, `--defaults=`*FILE*++:   Specify a set of default option settings.  *FILE* is a YAML or JSON+    file whose fields correspond to command-line option+    settings.  All options for document conversion, including input+    and output files, can be set using a defaults file.  The file will+    be searched for first in the working directory, and then in+    the `defaults` subdirectory of the user data directory+    (see `--data-dir`).  The `.yaml` extension will be added if+    *FILE* lacs an extension. See the section [Defaults files]+    for more information on the file format. Settings from the+    defaults file may be overridden or extended by subsequent+    options on the command line.++`--bash-completion`++:   Generate a bash completion script.  To enable bash completion+    with pandoc, add this to your `.bashrc`:++        eval "$(pandoc --bash-completion)"++`--sandbox[=true|false]`++:   Run pandoc in a sandbox, limiting IO operations in readers+    and writers to reading the files specified on the command line.+    Note that this option does not limit IO operations by+    filters or in the production of PDF documents.  But it does+    offer security against, for example, disclosure of files+    through the use of `include` directives.  Anyone using+    pandoc on untrusted user input should use this option.++    Note: some readers and writers (e.g., `docx`) need access to data+    files.  If these are stored on the file system, then pandoc+    will not be able to find them when run in `--sandbox` mode+    and will raise an error. For these applications, we+    recommend using a pandoc binary compiled with the `embed_data_files`+    option, which causes the data files to be baked into the binary+    instead of being stored on the file system.++`--verbose`++:   Give verbose debugging output.++`--quiet`++:   Suppress warning messages.++`--fail-if-warnings[=true|false]`++:   Exit with error status if there are any warnings.++`--log=`*FILE*++:   Write log messages in machine-readable JSON format to+    *FILE*.  All messages above DEBUG level will be written,+    regardless of verbosity settings (`--verbose`, `--quiet`).++`--list-input-formats`++:   List supported input formats, one per line.++`--list-output-formats`++:   List supported output formats, one per line.++`--list-extensions`[`=`*FORMAT*]++:   List supported extensions for *FORMAT*, one per line, preceded+    by a `+` or `-` indicating whether it is enabled by default+    in *FORMAT*. If *FORMAT* is not specified, defaults for+    pandoc's Markdown are given.++`--list-highlight-languages`++:   List supported languages for syntax highlighting, one per+    line.++`--list-highlight-styles`++:   List supported styles for syntax highlighting, one per line.+    See `--syntax-highlighting`.++`-v`, `--version`++:   Print version.++`-h`, `--help`++:   Show usage message.++[ANSI escape codes]: https://en.wikipedia.org/wiki/ANSI_escape_code+[Markdown]: https://daringfireball.net/projects/markdown/+[CommonMark]: https://commonmark.org+[PHP Markdown Extra]: https://michelf.ca/projects/php-markdown/extra/+[GitHub-Flavored Markdown]: https://help.github.com/articles/github-flavored-markdown/+[MultiMarkdown]: https://fletcherpenney.net/multimarkdown/+[reStructuredText]: https://docutils.sourceforge.io/docs/ref/rst/introduction.html+[S5]: https://meyerweb.com/eric/tools/s5/+[Slidy]: https://www.w3.org/Talks/Tools/Slidy2/+[Slideous]: https://goessner.net/articles/slideous/+[HTML]: https://www.w3.org/html/+[HTML5]: https://html.spec.whatwg.org/+[polyglot markup]: https://www.w3.org/TR/html-polyglot/+[XHTML]: https://www.w3.org/TR/xhtml1/+[LaTeX]: https://www.latex-project.org/+[`beamer`]: https://ctan.org/pkg/beamer+[Beamer User's Guide]: http://mirrors.ctan.org/macros/latex/contrib/beamer/doc/beameruserguide.pdf+[ConTeXt]: https://www.contextgarden.net/+[Rich Text Format]: https://en.wikipedia.org/wiki/Rich_Text_Format+[DocBook]: https://docbook.org+[Djot markup]: https://djot.net+[JATS]: https://jats.nlm.nih.gov+[BITS]: https://jats.nlm.nih.gov/extensions/bits/+[Jira]: https://jira.atlassian.com/secure/WikiRendererHelpAction.jspa?section=all+[txt2tags]: https://txt2tags.org+[EPUB]: http://idpf.org/epub+[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+[Textile]: https://textile-lang.com+[MediaWiki markup]: https://www.mediawiki.org/wiki/Help:Formatting+[DokuWiki markup]: https://www.dokuwiki.org/dokuwiki+[ZimWiki markup]: https://zim-wiki.org/manual/Help/Wiki_Syntax.html+[XWiki markup]: https://www.xwiki.org/xwiki/bin/view/Documentation/UserGuide/Features/XWikiSyntax/+[XLSX]: https://en.wikipedia.org/wiki/Microsoft_Excel#File_formats+[Vimdoc]: https://vimhelp.org/helphelp.txt.html#help-writing+[TWiki markup]: https://twiki.org/cgi-bin/view/TWiki/TextFormattingRules+[TikiWiki markup]: https://doc.tiki.org/Wiki-Syntax-Text#The_Markup_Language_Wiki-Syntax+[Haddock markup]: https://www.haskell.org/haddock/doc/html/ch03s08.html+[Creole 1.0]: http://www.wikicreole.org/wiki/Creole1.0+[CSV]: https://tools.ietf.org/html/rfc4180+[TSV]: https://www.iana.org/assignments/media-types/text/tab-separated-values+[roff man]: https://man.cx/groff_man(7)+[roff ms]: https://man.cx/groff_ms(7)+[Haskell]: https://www.haskell.org+[GNU Texinfo]: https://www.gnu.org/software/texinfo/+[RIS]: https://en.wikipedia.org/wiki/RIS_(file_format)+[Emacs Org mode]: https://orgmode.org+[AsciiDoc]: https://asciidoc.org/+[AsciiDoctor]: https://asciidoctor.org/+[`asciidoc-py`]: https://github.com/asciidoc-py/asciidoc-py+[DZSlides]: https://paulrouget.com/dzslides/+[Word docx]: https://en.wikipedia.org/wiki/Office_Open_XML+[PDF]: https://www.adobe.com/pdf/+[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://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+[Vimwiki]: https://vimwiki.github.io+[CSL JSON]: https://citeproc-js.readthedocs.io/en/latest/csl-json/markup.html+[BibTeX]: https://ctan.org/pkg/bibtex+[BibLaTeX]: https://ctan.org/pkg/biblatex+[Markua]: https://leanpub.com/markua/read+[EndNote XML bibliography]: https://support.clarivate.com/Endnote/s/article/EndNote-XML-Document-Type-Definition+[typst]: https://typst.app+[mdoc]: https://mandoc.bsd.lv/man/mdoc.7.html+[BBCode]: https://www.bbcode.org/reference.php+[BBCode (FluxBB)]: https://web.archive.org/web/20210623155046/https://fluxbb.org/forums/help.php#bbcode+[BBCode (Hubzilla)]: https://hubzilla.org/help/member/bbcode+[BBCode (Steam)]: https://steamcommunity.com/comment/ForumTopic/formattinghelp+[BBCode (phpBB)]: https://www.phpbb.com/community/help/bbcode+[BBCode (xenForo)]: https://www.xenfocus.com/community/help/bb-codes/++## Reader options {.options}++`--shift-heading-level-by=`*NUMBER*++:   Shift heading levels by a positive or negative integer.+    For example, with `--shift-heading-level-by=-1`, level 2+    headings become level 1 headings, and level 3 headings+    become level 2 headings.  Headings cannot have a level+    less than 1, so a heading that would be shifted below level 1+    becomes a regular paragraph.  Exception: with a shift of -N,+    a level-N heading at the beginning of the document+    replaces the metadata title. `--shift-heading-level-by=-1`+    is a good choice when converting HTML or Markdown documents that+    use an initial level-1 heading for the document title and+    level-2+ headings for sections. `--shift-heading-level-by=1`+    may be a good choice for converting Markdown documents that+    use level-1 headings for sections to HTML, since pandoc uses+    a level-1 heading to render the document title.++`--base-header-level=`*NUMBER*++:   *Deprecated.  Use `--shift-heading-level-by`=X instead,+    where X = NUMBER - 1.* Specify the base level for headings+    (defaults to 1).++`--indented-code-classes=`*CLASSES*++:   Specify classes to use for indented code blocks---for example,+    `perl,numberLines` or `haskell`. Multiple classes may be separated+    by spaces or commas.++`--default-image-extension=`*EXTENSION*++:   Specify a default extension to use when image paths/URLs have no+    extension.  This allows you to use the same source for formats that+    require different kinds of images.  Currently this option only affects+    the Markdown and LaTeX readers.++`--file-scope[=true|false]`++:   Parse each file individually before combining for multifile+    documents. This will allow footnotes in different files with the+    same identifiers to work as expected. If this option is set,+    footnotes and links will not work across files. Reading binary+    files (docx, odt, epub) implies `--file-scope`.++    If two or more files are processed using `--file-scope`,+    prefixes based on the filenames will be added to identifiers+    in order to disambiguate them, and internal links will+    be adjusted accordingly.  For example, a header with+    identifier `foo` in `subdir/file1.txt` will have its+    identifier changed to `subdir__file1.txt__foo`.++`-F` *PROGRAM*, `--filter=`*PROGRAM*++:   Specify an executable to be used as a filter transforming the+    pandoc AST after the input is parsed and before the output is+    written.  The executable should read JSON from stdin and write+    JSON to stdout.  The JSON must be formatted like  pandoc's own+    JSON input and output.  The name of the output format will be+    passed to the filter as the first argument.  Hence,++        pandoc --filter ./caps.py -t latex++    is equivalent to++        pandoc -t json | ./caps.py latex | pandoc -f json -t latex++    The latter form may be useful for debugging filters.++    Filters may be written in any language.  `Text.Pandoc.JSON`+    exports `toJSONFilter` to facilitate writing filters in Haskell.+    Those who would prefer to write filters in python can use the+    module [`pandocfilters`], installable from PyPI. There are also+    pandoc filter libraries in [PHP], [perl], and+    [JavaScript/node.js].++    In order of preference, pandoc will look for filters in++     1. a specified full or relative path (executable or+     non-executable),++     2. `$DATADIR/filters` (executable or non-executable)+     where `$DATADIR` is the user data directory (see+     `--data-dir`, above),++     3. `$PATH` (executable only).++    Filters, Lua-filters, and citeproc processing are applied in+    the order specified on the command line.++`-L` *SCRIPT*, `--lua-filter=`*SCRIPT*++:   Transform the document in a similar fashion as JSON filters (see+    `--filter`), but use pandoc's built-in Lua filtering system.  The given+    Lua script is expected to return a list of Lua filters which will be+    applied in order.  Each Lua filter must contain element-transforming+    functions indexed by the name of the AST element on which the filter+    function should be applied.++    The `pandoc` Lua module provides helper functions for element+    creation.  It is always loaded into the script's Lua environment.++    See the [Lua filters documentation] for further details.++    In order of preference, pandoc will look for Lua filters in++     1. a specified full or relative path,++     2. `$DATADIR/filters` where `$DATADIR` is the user data+     directory (see `--data-dir`, above).++    Filters, Lua filters, and citeproc processing are applied in+    the order specified on the command line.++`-M` *KEY*[`=`*VAL*], `--metadata=`*KEY*[`:`*VAL*]++:   Set the metadata field *KEY* to the value *VAL*.  A value specified+    on the command line overrides a value specified in the document+    using [YAML metadata blocks][Extension: `yaml_metadata_block`].+    Values will be parsed as YAML boolean or string values. If no value is+    specified, the value will be treated as Boolean true.  Like+    `--variable`, `--metadata` causes template variables to be set.+    But unlike `--variable`, `--metadata` affects the metadata of the+    underlying document (which is accessible from filters and may be+    printed in some output formats) and metadata values will be escaped+    when inserted into the template.++`--metadata-file=`*FILE*++:   Read metadata from the supplied YAML (or JSON) file. This+    option can be used with every input format, but string scalars+    in the metadata file will always be parsed as Markdown. (If the+    input format is Markdown or a Markdown variant, then the+    same variant will be used to parse the metadata file;+    if it is a non-Markdown format, pandoc's default Markdown+    extensions will be used.) This option can be used+    repeatedly to include multiple metadata files; values in+    files specified later on the command line will be preferred+    over those specified in earlier files. Metadata values+    specified inside the document, or by using `-M`, overwrite+    values specified with this option. The file will be searched+    for first in the working directory, and then in the `metadata`+    subdirectory of the user data directory (see `--data-dir`).++`-p`, `--preserve-tabs[=true|false]`++:   Preserve tabs instead of converting them to spaces. (By default, pandoc+    converts tabs to spaces before parsing its input.)  Note that this will+    only affect tabs in literal code spans and code blocks. Tabs in regular+    text are always treated as spaces.++`--tab-stop=`*NUMBER*++:   Specify the number of spaces per tab (default is 4).++`--track-changes=accept`|`reject`|`all`++:   Specifies what to do with insertions, deletions, and comments+    produced by the MS Word "Track Changes" feature.  `accept` (the+    default) processes all the insertions and deletions.+    `reject` ignores them.  Both `accept` and `reject` ignore comments.+    `all` includes all insertions, deletions, and comments, wrapped+    in spans with `insertion`, `deletion`, `comment-start`, and+    `comment-end` classes, respectively. The author and time of+    change is included. `all` is useful for scripting: only+    accepting changes from a certain reviewer, say, or before a+    certain date. If a paragraph is inserted or deleted,+    `track-changes=all` produces a span with the class+    `paragraph-insertion`/`paragraph-deletion` before the+    affected paragraph break. This option only affects the docx+    reader.++`--extract-media=`*DIR*|*FILE*`.zip`++:   Extract images and other media contained in or linked from+    the source document to the path *DIR*, creating it if+    necessary, and adjust the images references in the document+    so they point to the extracted files.  Media are downloaded,+    read from the file system, or extracted from a binary+    container (e.g. docx), as needed.  The original file paths+    are used if they are relative paths not containing `..`.+    Otherwise filenames are constructed from the SHA1 hash of+    the contents.++    If the path given ends in `.zip`, then instead of creating+    a directory, pandoc will create a zip archive containing the+    media files.++`--abbreviations=`*FILE*++:   Specifies a custom abbreviations file, with abbreviations+    one to a line.  If this option is not specified, pandoc will+    read the data file `abbreviations` from the user data+    directory or fall back on a system default.  To see the+    system default, use+    `pandoc --print-default-data-file=abbreviations`.  The only+    use pandoc makes of this list is in the Markdown reader.+    Strings found in this list will be followed by a nonbreaking+    space, and the period will not produce sentence-ending space+    in formats like LaTeX.  The strings may not contain spaces.++`--typst-input=`*KEY*[`=`*VAL*]++:   Set a parameter value that will be made available to the typst+    parser in `sys.inputs`, like `--input` in the `typst` CLI.+    Either `:` or `=` may be used to separate *KEY* from *VAL*.+    Values containing spaces must be quoted.++`--trace[=true|false]`++:   Print diagnostic output tracing parser progress to stderr.+    This option is intended for use by developers in diagnosing+    performance issues.++[`pandocfilters`]: https://github.com/jgm/pandocfilters+[PHP]: https://github.com/vinai/pandocfilters-php+[perl]: https://metacpan.org/pod/Pandoc::Filter+[JavaScript/node.js]: https://github.com/mvhenderson/pandoc-filter-node+[Lua filters documentation]: https://pandoc.org/lua-filters.html++## General writer options {.options}++`-s`, `--standalone`++:   Produce output with an appropriate header and footer (e.g. a+    standalone HTML, LaTeX, TEI, or RTF file, not a fragment).  This option+    is set automatically for `pdf`, `epub`, `epub3`, `fb2`, `docx`, and `odt`+    output.  For `native` output, this option causes metadata to+    be included; otherwise, metadata is suppressed.++`--template=`*FILE*|*URL*++:   Use the specified file as a custom template for the generated document.+    Implies `--standalone`. See [Templates], below, for a+    description of template syntax. If the template is not found,+    pandoc will search for it in the `templates` subdirectory of+    the user data directory (see `--data-dir`). If no extension+    is specified and an extensionless template is not found,+    pandoc will look for a template with an extension+    corresponding to the writer, so that `--template=special`+    looks for `special.html` for HTML output. If this option is+    not used, a default template appropriate for the output+    format will be used (see `-D/--print-default-template`).++`-V` *KEY*[`=`*VAL*], `--variable=`*KEY*[`=`*VAL*]++:   Set the template variable *KEY* to the string value *VAL* when rendering+    the document in standalone mode. Either `:` or `=` may be used+    to separate *KEY* from *VAL*. If no *VAL* is specified, the+    key will be given the value `true`.  Structured values (lists, maps)+    cannot be assigned using this option, but they can be assigned in+    the `variables` section of a [defaults file][Defaults files] or+    using the `--variable-json` option. If the variable already has+    a *list* value, the value will be added to the list. If it already+    has another kind of value, it will be made into a list containing+    the previous and the new value. For example,+    `-V author=Joe -V author=Sue` makes `author` contain a list+    of strings: `Joe` and `Sue`.++`--variable-json=`*KEY*[`=`*JSON*]++:   Set the template variable *KEY* to the value specified by a JSON+    string (this may be a boolean, a string, a list, or a mapping;+    a number will be treated as a string). For example,+    `--variable-json foo=false` will give `foo` the boolean false+    value, while `--variable-json foo='"false"'` will give it the+    string value `"false"`. Either `:` or `=` may be used to+    separate *KEY* from *VAL*. If the variable already has a+    value, this value will be replaced.++`-D` *FORMAT*, `--print-default-template=`*FORMAT*++:   Print the system default template for an output *FORMAT*. (See `-t`+    for a list of possible *FORMAT*s.)  Templates in the user data+    directory are ignored.  This option may be used with+    `-o`/`--output` to redirect output to a file, but+    `-o`/`--output` must come before `--print-default-template`+    on the command line.++    Note that some of the default templates use partials, for+    example `styles.html`.  To print the partials, use+    `--print-default-data-file`: for example,+    `--print-default-data-file=templates/styles.html`.++`--print-default-data-file=`*FILE*++:   Print a system default data file.  Files in the user data directory+    are ignored.  This option may be used with `-o`/`--output` to+    redirect output to a file, but `-o`/`--output` must come before+    `--print-default-data-file` on the command line.++`--eol=crlf`|`lf`|`native`++:   Manually specify line endings: `crlf` (Windows), `lf`+    (macOS/Linux/UNIX), or `native` (line endings appropriate+    to the OS on which pandoc is being run).  The default is+    `native`.++`--dpi`=*NUMBER*++:   Specify the default dpi (dots per inch) value for conversion+    from pixels to inch/centimeters and vice versa. (Technically,+    the correct term would be ppi: pixels per inch.) The default+    is 96dpi.   When images contain information about dpi+    internally, the encoded value is used instead of the default+    specified by this option.++`--wrap=auto`|`none`|`preserve`++:   Determine how text is wrapped in the output (the source+    code, not the rendered version).  With `auto` (the default),+    pandoc will attempt to wrap lines to the column width specified by+    `--columns` (default 72).  With `none`, pandoc will not wrap+    lines at all.  With `preserve`, pandoc will attempt to+    preserve the wrapping from the source document (that is,+    where there are nonsemantic newlines in the source, there+    will be nonsemantic newlines in the output as well).+    In `ipynb` output, this option affects wrapping of the+    contents of Markdown cells.++`--columns=`*NUMBER*++:   Specify length of lines in characters.  This affects text wrapping+    in the generated source code (see `--wrap`).  It also affects+    calculation of column widths for plain text tables (see [Tables] below).++`--toc[=true|false]`, `--table-of-contents[=true|false]`++:   Include an automatically generated table of contents (or, in+    the case of `latex`, `context`, `docx`, `odt`,+    `opendocument`, `rst`, or `ms`, an instruction to create+    one) in the output document. This option has no effect+    unless `-s/--standalone` is used, and it has no effect+    on `man`, `docbook4`, `docbook5`, or `jats` output.++    Note that if you are producing a PDF via `ms` and using+    (the default) `groff` as a `--pdf-engine`, the table of+    contents will appear at the end of the document. If you would+    prefer it to be at the beginning of the document, before the+    title, you can use `--pdf-engine=pdfroff`.++`--toc-depth=`*NUMBER*++:   Specify the number of section levels to include in the table+    of contents.  The default is 3 (which means that level-1, 2, and 3+    headings will be listed in the contents).++`--lof[=true|false]`, `--list-of-figures[=true|false]`++:   Include an automatically generated list of figures (or, in+    some formats, an instruction to create one) in the output+    document. This option has no effect unless `-s/--standalone`+    is used, and it only has an effect on `latex`, `context`, and+    `docx` output.++`--lot[=true|false]`, `--list-of-tables[=true|false]`++:   Include an automatically generated list of tables (or, in+    some formats, an instruction to create one) in the output+    document. This option has no effect unless `-s/--standalone`+    is used, and it only has an effect on `latex`, `context`, and+    `docx` output.++`--strip-comments[=true|false]`++:   Strip out HTML comments in the Markdown or Textile source,+    rather than passing them on to Markdown, Textile or HTML+    output as raw HTML.  This does not apply to HTML comments+    inside raw HTML blocks when the `markdown_in_html_blocks`+    extension is not set.++`--syntax-highlighting=default|none|idiomatic|`*STYLE*`|`*FILE*++:   The method to use for code syntax highlighting. Setting a+    specific *STYLE* causes highlighting to be performed with the+    internal highlighting engine, using KDE syntax definitions and+    styles. The `idiomatic` method uses a format-specific+    highlighter if one is available, or the default style if the+    target format has no idiomatic highlighting method. Setting this+    option to `none` disables all syntax highlighting. The+    `default` method uses a format-specific default.++    The default for HTML, EPUB, Docx, Ms, Man, and LaTeX output is+    to use the internal highlighter with the default style; for Typst+    it is to use Typst's own syntax highlighting system.++    Style options are `pygments` (the default), `kate`,+    `monochrome`, `breezeDark`, `espresso`, `zenburn`, `haddock`,+    and `tango`. For more information on syntax highlighting in+    pandoc, see [Syntax highlighting], below. See also+    `--list-highlight-styles`.++    Instead of a *STYLE* name, a JSON file with extension+    `.theme` may be supplied.  This will be parsed as a KDE+    syntax highlighting theme and (if valid) used as the+    highlighting style.++    To generate the JSON version of an existing style,+    use `--print-highlight-style`.++`--no-highlight`++:   *Deprecated, use `--syntax-highlighting=none` instead.*++    Disables syntax highlighting for code blocks and inlines, even when+    a language attribute is given.++`--highlight-style=`*STYLE*|*FILE*++:   _Deprecated, use `--syntax-highlighting=`*STYLE*|*FILE* instead._++    Specifies the coloring style to be used in highlighted source code.++`--print-highlight-style=`*STYLE*|*FILE*++:   Prints a JSON version of a highlighting style, which can+    be modified, saved with a `.theme` extension, and used+    with `--syntax-highlighting`.  This option may be used with+    `-o`/`--output` to redirect output to a file, but+    `-o`/`--output` must come before `--print-highlight-style`+    on the command line.++`--syntax-definition=`*FILE*++:   Instructs pandoc to load a KDE XML syntax definition file,+    which will be used for syntax highlighting of appropriately+    marked code blocks.  This can be used to add support for+    new languages or to use altered syntax definitions for+    existing languages.  This option may be repeated to add+    multiple syntax definitions.++`-H` *FILE*, `--include-in-header=`*FILE*|*URL*++:   Include contents of *FILE*, verbatim, at the end of the header.+    This can be used, for example, to include special+    CSS or JavaScript in HTML documents.  This option can be used+    repeatedly to include multiple files in the header.  They will be+    included in the order specified.  Implies `--standalone`.++`-B` *FILE*, `--include-before-body=`*FILE*|*URL*++:   Include contents of *FILE*, verbatim, at the beginning of the+    document body (e.g. after the `<body>` tag in HTML, or the+    `\begin{document}` command in LaTeX). This can be used to include+    navigation bars or banners in HTML documents. This option can be+    used repeatedly to include multiple files. They will be included in+    the order specified.  Implies `--standalone`. Note that if the+    output format is `odt`, this file must be in OpenDocument XML format+    suitable for insertion into the body of the document, and if+    the output is `docx`, this file must be in appropriate+    OpenXML format.++`-A` *FILE*, `--include-after-body=`*FILE*|*URL*++:   Include contents of *FILE*, verbatim, at the end of the document+    body (before the `</body>` tag in HTML, or the+    `\end{document}` command in LaTeX). This option can be used+    repeatedly to include multiple files. They will be included in the+    order specified.  Implies `--standalone`. Note that if the+    output format is `odt`, this file must be in OpenDocument XML format+    suitable for insertion into the body of the document, and if+    the output is `docx`, this file must be in appropriate+    OpenXML format.++`--resource-path=`*SEARCHPATH*++:   List of paths to search for images and other resources.+    The paths should be separated by `:` on Linux, UNIX, and+    macOS systems, and by `;` on Windows.  If `--resource-path`+    is not specified, the default resource path is the working+    directory. Note that, if `--resource-path` is specified,+    the working directory must be explicitly listed or it+    will not be searched.  For example:+    `--resource-path=.:test` will search the working directory+    and the `test` subdirectory, in that order.+    This option can be used repeatedly. Search path components+    that come later on the command line will be searched before+    those that come earlier, so+    `--resource-path foo:bar --resource-path baz:bim` is+    equivalent to `--resource-path baz:bim:foo:bar`.+    Note that this option only has an effect when pandoc+    itself needs to find an image (e.g., in producing a+    PDF or docx, or when `--embed-resources` is used.)+    It will not cause image paths to be rewritten in other+    cases (e.g., when pandoc is generating LaTeX or HTML).++`--request-header=`*NAME*`:`*VAL*++:   Set the request header *NAME* to the value *VAL* when making+    HTTP requests (for example, when a URL is given on the+    command line, or when resources used in a document must be+    downloaded). If you're behind a proxy, you also need to set+    the environment variable `http_proxy` to `http://...`.++`--no-check-certificate[=true|false]`++:   Disable the certificate verification to allow access to+    unsecure HTTP resources (for example when the certificate+    is no longer valid or self signed).++## Options affecting specific writers {.options}++`--self-contained[=true|false]`++:   *Deprecated synonym for `--embed-resources --standalone`.*++`--embed-resources[=true|false]`++:   Produce a standalone HTML file with no external dependencies, using+    `data:` URIs to incorporate the contents of linked scripts, stylesheets,+    images, and videos. The resulting file should be "self-contained," in the+    sense that it needs no external files and no net access to be displayed+    properly by a browser. This option works only with HTML output formats,+    including `html4`, `html5`, `html+lhs`, `html5+lhs`, `s5`, `slidy`,+    `slideous`, `dzslides`, and `revealjs`. Scripts, images, and stylesheets at+    absolute URLs will be downloaded; those at relative URLs will be sought+    relative to the working directory (if the first source+    file is local) or relative to the base URL (if the first source+    file is remote).  Elements with the attribute+    `data-external="1"` will be left alone; the documents they+    link to will not be incorporated in the document.+    Limitation: resources that are loaded dynamically through+    JavaScript cannot be incorporated; as a result, fonts may+    be missing when `--mathjax` is used, and some+    advanced features (e.g.  zoom or speaker notes) may not work+    in an offline "self-contained" `reveal.js` slide show.++    For SVG images, `img` tags with `data:` URIs are used,+    unless the image has the class `inline-svg`, in which case+    an inline SVG element is inserted. This approach is+    recommended when there are many occurrences of the same+    SVG in a document, as `<use>` elements will be used to+    reduce duplication.++`--link-images[=true|false]`++:   Include links to images instead of embedding the images in ODT.+    (This option currently only affects ODT output.)++`--html-q-tags[=true|false]`++:   Use `<q>` tags for quotes in HTML.  (This option only has an+    effect if the `smart` extension is enabled for the input+    format used.)++`--ascii[=true|false]`++:   Use only ASCII characters in output. Currently supported for XML+    and HTML formats (which use entities instead of UTF-8 when this+    option is selected), CommonMark, gfm, and Markdown (which use+    entities), roff man and ms (which use hexadecimal escapes), and to a+    limited degree LaTeX (which uses standard commands for accented+    characters when possible).++`--reference-links[=true|false]`++:   Use reference-style links, rather than inline links, in writing Markdown+    or reStructuredText.  By default inline links are used.  The+    placement of link references is affected by the+    `--reference-location` option.++`--reference-location=block`|`section`|`document`++:   Specify whether footnotes (and references, if `reference-links` is+    set) are placed at the end of the current (top-level) block, the+    current section, or the document. The default is+    `document`. Currently this option only affects the+    `markdown`, `muse`, `html`, `epub`, `slidy`, `s5`, `slideous`,+    `dzslides`, and `revealjs` writers.  In slide formats,+    specifying `--reference-location=section` will cause notes+    to be rendered at the bottom of a slide.++`--figure-caption-position=above`|`below`++:   Specify whether figure captions go above or below figures+    (default is `below`).  This option only affects HTML,+    LaTeX, Docx, ODT, and Typst output.++`--table-caption-position=above`|`below`++:   Specify whether table captions go above or below tables+    (default is `above`).  This option only affects HTML,+    LaTeX, Docx, ODT, and Typst output.++`--markdown-headings=setext`|`atx`++:   Specify whether to use ATX-style (`#`-prefixed) or+    Setext-style (underlined) headings for level 1 and 2+    headings in Markdown output.  (The default is `atx`.)+    ATX-style headings are always used for levels 3+.+    This option also affects Markdown cells in `ipynb` output.++`--list-tables[=true|false]`++:   Render tables as list tables in RST output.++`--top-level-division=default`|`section`|`chapter`|`part`++:   Treat top-level headings as the given division type in+    LaTeX, ConTeXt, DocBook, and TEI output. The hierarchy+    order is part, chapter, then section; all headings are+    shifted such that the top-level heading becomes the+    specified type. The default behavior is to determine the+    best division type via heuristics: unless other conditions+    apply, `section` is chosen. When the `documentclass`+    variable is set to `report`, `book`, or `memoir` (unless the+    `article` option is specified), `chapter` is implied as the+    setting for this option. If `beamer` is the output format,+    specifying either `chapter` or `part` will cause top-level+    headings to become `\part{..}`, while second-level headings+    remain as their default type.++    In Docx output, this option adds section breaks before first-level+    headings if `chapter` is selected, and before first- and second-level+    headings if `part` is selected. Footnote numbers will restart+    with each section break unless the reference doc modifies this.++`-N`, `--number-sections=[true|false]`++:   Number section headings in LaTeX, ConTeXt, HTML, Docx, ms, or EPUB+    output.  By default, sections are not numbered.  Sections with class+    `unnumbered` will never be numbered, even if `--number-sections`+    is specified.++`--number-offset=`*NUMBER*[`,`*NUMBER*`,`*...*]++:   Offsets for section heading numbers. The first number is added+    to the section number for level-1 headings, the second for+    level-2 headings, and so on. So, for example, if you+    want the first level-1 heading in your document to be+    numbered "6" instead of "1", specify `--number-offset=5`.+    If your document starts with a level-2 heading which you want+    to be numbered "1.5", specify `--number-offset=1,4`.+    `--number-offset` only directly affects the number of the+    first section heading in a document; subsequent numbers+    increment in the normal way. Implies `--number-sections`.+    Currently this feature only affects HTML and Docx output.++`--listings[=true|false]`++:   *Deprecated, use `--syntax-highlighting=idiomatic` or+    `--syntax-highlighting=default` instead.++    Use the [`listings`] package for LaTeX code blocks. The package+    does not support multi-byte encoding for source code. To handle UTF-8+    you would need to use a custom template. This issue is fully+    documented here: [Encoding issue with the listings package].++`-i`, `--incremental[=true|false]`++:   Make list items in slide shows display incrementally (one by one).+    The default is for lists to be displayed all at once.++`--slide-level=`*NUMBER*++:   Specifies that headings with the specified level create+    slides (for `beamer`, `revealjs`, `pptx`, `s5`, `slidy`,+    `slideous`, `dzslides`). Headings above this level in the+    hierarchy are used to divide the slide show into sections;+    headings below this level create subheads within a slide.+    Valid values are 0-6. If a slide level of 0 is specified,+    slides will not be split automatically on headings, and+    horizontal rules must be used to indicate slide boundaries.+    If a slide level is not specified explicitly, the slide level+    will be set automatically based on the contents of the+    document; see [Structuring the slide show].++`--section-divs[=true|false]`++:   Wrap sections in `<section>` tags (or `<div>` tags for `html4`),+    and attach identifiers to the enclosing `<section>` (or `<div>`)+    rather than the heading itself (see+    [Heading identifiers], below). This option only affects+    HTML output (and does not affect HTML slide formats).++`--email-obfuscation=none`|`javascript`|`references`++:   Specify a method for obfuscating `mailto:` links in HTML documents.+    `none` leaves `mailto:` links as they are.  `javascript` obfuscates+    them using JavaScript. `references` obfuscates them by printing their+    letters as decimal or hexadecimal character references.  The default+    is `none`.++`--id-prefix=`*STRING*++:   Specify a prefix to be added to all identifiers and internal links+    in HTML and DocBook output, and to footnote numbers in Markdown+    and Haddock output. This is useful for preventing duplicate+    identifiers when generating fragments to be included in other pages.++`-T` *STRING*, `--title-prefix=`*STRING*++:   Specify *STRING* as a prefix at the beginning of the title+    that appears in the HTML header (but not in the title as it+    appears at the beginning of the HTML body).  Implies `--standalone`.++`-c` *URL*, `--css=`*URL*++:   Link to a CSS style sheet. This option can be used repeatedly to+    include multiple files. They will be included in the order specified.+    This option only affects HTML (including HTML slide shows)+    and EPUB output.  It should be used together with+    `-s/--standalone`, because the link to the stylesheet goes+    in the document header.++    A stylesheet is required for generating EPUB.  If none is+    provided using this option (or the `css` or `stylesheet`+    metadata fields), pandoc will look for a file `epub.css` in the+    user data directory (see `--data-dir`).  If it is not+    found there, sensible defaults will be used.++[`--reference-doc=`*FILE*|*URL*]{#option--reference-doc}++:   Use the specified file as a style reference in producing a+    docx or ODT file.++    Docx++    :   For best results, the reference docx should be a modified+        version of a docx file produced using pandoc.  The contents+        of the reference docx are ignored, but its stylesheets and+        document properties (including margins, page size, header,+        and footer) are used in the new docx. If no reference docx+        is specified on the command line, pandoc will look for a+        file `reference.docx` in the user data directory (see+        `--data-dir`). If this is not found either, sensible+        defaults will be used.++        To produce a custom `reference.docx`, first get a copy of+        the default `reference.docx`: `pandoc+        -o custom-reference.docx --print-default-data-file reference.docx`.+        Then open `custom-reference.docx` in Word or LibreOffice, modify the+        styles as you wish, and save the file.  For best+        results, do not make changes to this file other than+        modifying the styles used by pandoc:++        Paragraph styles:++        - Normal+        - Body Text+        - First Paragraph+        - Compact+        - Title+        - Subtitle+        - Author+        - Date+        - Abstract+        - AbstractTitle+        - Bibliography+        - Heading 1+        - Heading 2+        - Heading 3+        - Heading 4+        - Heading 5+        - Heading 6+        - Heading 7+        - Heading 8+        - Heading 9+        - Block Text [for block quotes]+        - Footnote Block Text [for block quotes in footnotes]+        - Source Code+        - Footnote Text+        - Definition Term+        - Definition+        - Caption+        - Table Caption+        - Image Caption+        - Figure+        - Captioned Figure+        - TOC Heading++        Character styles:++        - Default Paragraph Font+        - Verbatim Char+        - Footnote Reference+        - Hyperlink+        - Section Number++        Table style:++        - Table++    ODT++    :   For best results, the reference ODT should be a modified+        version of an ODT produced using pandoc.  The contents of+        the reference ODT are ignored, but its stylesheets are used+        in the new ODT. If no reference ODT is specified on the+        command line, pandoc will look for a file `reference.odt` in+        the user data directory (see `--data-dir`). If this is not+        found either, sensible defaults will be used.++        To produce a custom `reference.odt`, first get a copy of+        the default `reference.odt`: `pandoc+        -o custom-reference.odt --print-default-data-file reference.odt`.+        Then open `custom-reference.odt` in LibreOffice, modify+        the styles as you wish, and save the file.++    PowerPoint++    :   Templates included with Microsoft PowerPoint 2013 (either with+        `.pptx` or `.potx` extension) are known to work, as are most+        templates derived from these.++        The specific requirement is that the template should contain layouts+        with the following names (as seen within PowerPoint):++        - Title Slide+        - Title and Content+        - Section Header+        - Two Content+        - Comparison+        - Content with Caption+        - Blank++        For each name, the first layout found with that name will be used.+        If no layout is found with one of the names, pandoc will output a+        warning and use the layout with that name from the default reference+        doc instead. (How these layouts are used is described in [PowerPoint+        layout choice](#powerpoint-layout-choice).)++        All templates included with a recent version of MS PowerPoint+        will fit these criteria. (You can click on `Layout` under the+        `Home` menu to check.)++        You can also modify the default `reference.pptx`: first run+        `pandoc -o custom-reference.pptx --print-default-data-file+        reference.pptx`, and then modify `custom-reference.pptx`+        in MS PowerPoint (pandoc will use the layouts with the names+        listed above).++`--split-level=`*NUMBER*++:   Specify the heading level at which to split an EPUB or+    chunked HTML document into separate files. The default is to split+    into chapters at level-1 headings. In the case of EPUB, this+    option only affects the internal composition of the EPUB, not the way+    chapters and sections are displayed to users. Some+    readers may be slow if the chapter files are too large, so for large+    documents with few level-1 headings, one might want to use a chapter+    level of 2 or 3. For chunked HTML, this option determines+    how much content goes in each "chunk."++`--chunk-template=`*PATHTEMPLATE*++:   Specify a template for the filenames in a `chunkedhtml` document.+    In the template, `%n` will be replaced by the chunk number (padded+    with leading 0s to 3 digits), `%s` with the section number of the chunk,+    `%h` with the heading text (with formatting removed), `%i` with+    the section identifier. For example, `section-%s-%i.html` might+    be resolved to `section-1.1-introduction.html`. The characters+    `/` and `\` are not allowed in chunk templates and will be+    ignored. The default is `%s-%i.html`.++`--epub-chapter-level=`*NUMBER*++:   *Deprecated synonym for `--split-level`.*++`--epub-cover-image=`*FILE*++:   Use the specified image as the EPUB cover.  It is recommended+    that the image be less than 1000px in width and height. Note that+    in a Markdown source document you can also specify `cover-image`+    in a YAML metadata block (see [EPUB Metadata], below).++`--epub-title-page=true`|`false`++:   Determines whether a the title page is included in the EPUB+    (default is `true`).++`--epub-metadata=`*FILE*++:   Look in the specified XML file for metadata for the EPUB.+    The file should contain a series of [Dublin Core elements].+    For example:++         <dc:rights>Creative Commons</dc:rights>+         <dc:language>es-AR</dc:language>++    By default, pandoc will include the following metadata elements:+    `<dc:title>` (from the document title), `<dc:creator>` (from the+    document authors), `<dc:date>` (from the document date, which should+    be in [ISO 8601 format]), `<dc:language>` (from the `lang`+    variable, or, if is not set, the locale), and `<dc:identifier+    id="BookId">` (a randomly generated UUID). Any of these may be+    overridden by elements in the metadata file.++    Note: if the source document is Markdown, a YAML metadata block+    in the document can be used instead.  See below under+    [EPUB Metadata].++`--epub-embed-font=`*FILE*++:   Embed the specified font in the EPUB. This option can be repeated+    to embed multiple fonts.  Wildcards can also be used: for example,+    `DejaVuSans-*.ttf`.  However, if you use wildcards on the command+    line, be sure to escape them or put the whole filename in single quotes,+    to prevent them from being interpreted by the shell. To use the+    embedded fonts, you will need to add declarations like the following+    to your CSS (see `--css`):++        @font-face {+           font-family: DejaVuSans;+           font-style: normal;+           font-weight: normal;+           src:url("../fonts/DejaVuSans-Regular.ttf");+        }+        @font-face {+           font-family: DejaVuSans;+           font-style: normal;+           font-weight: bold;+           src:url("../fonts/DejaVuSans-Bold.ttf");+        }+        @font-face {+           font-family: DejaVuSans;+           font-style: italic;+           font-weight: normal;+           src:url("../fonts/DejaVuSans-Oblique.ttf");+        }+        @font-face {+           font-family: DejaVuSans;+           font-style: italic;+           font-weight: bold;+           src:url("../fonts/DejaVuSans-BoldOblique.ttf");+        }+        body { font-family: "DejaVuSans"; }++`--epub-subdirectory=`*DIRNAME*++:   Specify the subdirectory in the OCF container that is to hold+    the EPUB-specific contents.  The default is `EPUB`.  To put+    the EPUB contents in the top level, use an empty string.++`--ipynb-output=all|none|best`++:   Determines how ipynb output cells are treated. `all` means+    that all of the data formats included in the original are+    preserved.  `none` means that the contents of data cells+    are omitted.  `best` causes pandoc to try to pick the+    richest data block in each output cell that is compatible+    with the output format.  The default is `best`.++`--pdf-engine=`*PROGRAM*++:   Use the specified engine when producing PDF output.+    Valid values are `pdflatex`, `lualatex`, `xelatex`, `latexmk`,+    `tectonic`, `wkhtmltopdf`, `weasyprint`, `pagedjs-cli`,+    `prince`, `context`, `groff`, `pdfroff`, and `typst`.+    If the engine is not in your PATH, the full path of the engine+    may be specified here. If this option is not specified,+    pandoc uses the following defaults depending on the output+    format specified using `-t/--to`:++    - `-t latex` or none: `pdflatex` (other options: `xelatex`, `lualatex`,+        `tectonic`, `latexmk`)+    - `-t context`: `context`+    - `-t html`:  `weasyprint` (other options: `prince`, `wkhtmltopdf`,+        `pagedjs-cli`;+        see [print-css.rocks](https://print-css.rocks) for a good+        introduction to PDF generation from HTML/CSS)+    - `-t ms`:  `groff`+    - `-t typst`: `typst`++    This option is normally intended to be used when a PDF+    file is specified as `-o/--output`.  However, it may still+    have an effect when other output formats are requested.+    For example, `ms` output will include `.pdfhref` macros+    only if a `--pdf-engine` is selected, and the macros will+    be differently encoded depending on whether `groff` or+    `pdfroff` is specified.++`--pdf-engine-opt=`*STRING*++:   Use the given string as a command-line argument to the `pdf-engine`.+    For example, to use a persistent directory `foo` for `latexmk`'s+    auxiliary files, use `--pdf-engine-opt=-outdir=foo`.+    Note that no check for duplicate options is done.++[Dublin Core elements]: https://www.dublincore.org/specifications/dublin-core/dces/+[ISO 8601 format]: https://www.w3.org/TR/NOTE-datetime+[Encoding issue with the listings package]:+  https://en.wikibooks.org/wiki/LaTeX/Source_Code_Listings#Encoding_issue++## Citation rendering {.options}++`-C`, `--citeproc`++:   Process the citations in the file, replacing them with+    rendered citations and adding a bibliography.+    Citation processing will not take place unless bibliographic+    data is supplied, either through an external file specified+    using the `--bibliography` option or the `bibliography`+    field in metadata, or via a `references` section in metadata+    containing a list of citations in CSL YAML format with+    Markdown formatting.  The style is controlled by a [CSL]+    stylesheet specified using the `--csl` option or the `csl`+    field in metadata. (If no stylesheet is specified,+    the `chicago-author-date` style will be used by default.)+    The citation processing transformation may be applied before+    or after filters or Lua filters (see `--filter`,+    `--lua-filter`): these transformations are applied in the+    order they appear on the command line.  For more+    information, see the section on [Citations].++    Note: if this option is specified, the `citations` extension+    will be disabled automatically in the writer, to ensure that+    the citeproc-generated citations will be rendered instead of+    the format's own citation syntax.++`--bibliography=`*FILE*++:   Set the `bibliography` field in the document's metadata to *FILE*,+    overriding any value set in the metadata.  If you supply+    this argument multiple times, each *FILE* will be added to+    bibliography.  If *FILE* is a URL, it will be fetched+    via HTTP. If *FILE* is not found relative to the+    working directory, it will be sought in the resource path+    (see `--resource-path`).++`--csl=`*FILE*++:   Set the `csl` field in the document's metadata to *FILE*,+    overriding any value set in the metadata.  (This is equivalent to+    `--metadata csl=FILE`.)  If *FILE* is a URL, it will be+    fetched via HTTP.  If *FILE* is not found relative to the+    working directory, it will be sought in the resource path+    (see `--resource-path`) and finally in the `csl`+    subdirectory of the pandoc user data directory.++`--citation-abbreviations=`*FILE*++:   Set the `citation-abbreviations` field in the document's metadata to+    *FILE*, overriding any value set in the metadata.  (This is equivalent to+    `--metadata citation-abbreviations=FILE`.)+    If *FILE* is a URL, it will be fetched via HTTP.  If *FILE* is not+    found relative to the working directory, it will be sought+    in the resource path (see `--resource-path`) and finally in+    the `csl` subdirectory of the pandoc user data directory.++`--natbib`++:   Use [`natbib`] for citations in LaTeX output.  This option+    is not for use with the `--citeproc` option or with PDF+    output.  It is intended for use in producing a LaTeX file+    that can be processed with [`bibtex`].++`--biblatex`++:   Use [`biblatex`] for citations in LaTeX output.  This option+    is not for use with the `--citeproc` option or with PDF+    output. It is intended for use in producing a LaTeX file+    that can be processed with [`bibtex`] or [`biber`].++## Math rendering in HTML {.options}++The default is to render TeX math as far as possible using+Unicode characters.  Formulas are put inside a `span` with+`class="math"`, so that they may be styled differently from the+surrounding text if needed. However, this gives acceptable+results only for basic math, usually you will want to use+`--mathjax` or another of the following options.++`--mathjax`[`=`*URL*]++:   Use [MathJax] to display embedded TeX math in HTML output.+    TeX math will be put between `\(...\)` (for inline math)+    or `\[...\]` (for display math) and wrapped in `<span>` tags+    with class `math`. Then the MathJax JavaScript will render it.+    The *URL* should point to the `MathJax.js` load script.+    If a *URL* is not provided, a link to the Cloudflare CDN will+    be inserted.++`--mathml`++:   Convert TeX math to [MathML] (in `epub3`, `docbook4`,+    `docbook5`, `jats`, `html4` and `html5`).  This is the+    default in `odt` output. MathML is supported natively by+    the main web browsers and select e-book readers.++`--webtex`[`=`*URL*]++:   Convert TeX formulas to `<img>` tags that link to an external script+    that converts formulas to images. The formula will be URL-encoded+    and concatenated with the URL provided. For SVG images you can for+    example use `--webtex https://latex.codecogs.com/svg.latex?`.+    If no URL is specified, the CodeCogs URL generating PNGs+    will be used (`https://latex.codecogs.com/png.latex?`).+    Note:  the `--webtex` option will affect Markdown output+    as well as HTML, which is useful if you're targeting a+    version of Markdown without native math support.++`--katex`[`=`*URL*]++:   Use [KaTeX] to display embedded TeX math in HTML output.+    The *URL* is the base URL for the KaTeX library. That directory+    should contain a `katex.min.js` and a `katex.min.css` file.+    If a *URL* is not provided, a link to the KaTeX CDN will be inserted.++`--gladtex`++:   Enclose TeX math in `<eq>` tags in HTML output.  The resulting HTML+    can then be processed by [GladTeX] to produce SVG images of the typeset+    formulas and an HTML file with these images embedded.++        pandoc -s --gladtex input.md -o myfile.htex+        gladtex -d image_dir myfile.htex+        # produces myfile.html and images in image_dir++[MathML]: https://www.w3.org/Math/+[MathJax]: https://www.mathjax.org+[KaTeX]: https://github.com/Khan/KaTeX+[GladTeX]: https://humenda.github.io/GladTeX/++## Options for wrapper scripts {.options}++`--dump-args[=true|false]`++:   Print information about command-line arguments to *stdout*, then exit.+    This option is intended primarily for use in wrapper scripts.+    The first line of output contains the name of the output file specified+    with the `-o` option, or `-` (for *stdout*) if no output file was+    specified.  The remaining lines contain the command-line arguments,+    one per line, in the order they appear.  These do not include regular+    pandoc options and their arguments, but do include any options appearing+    after a `--` separator at the end of the line.++`--ignore-args[=true|false]`++:   Ignore command-line arguments (for use in wrapper scripts).+    Regular pandoc options are not ignored.  Thus, for example,++        pandoc --ignore-args -o foo.html -s foo.txt -- -e latin1++    is equivalent to++        pandoc -o foo.html -s++# Exit codes++If pandoc completes successfully, it will return exit code 0.+Nonzero exit codes have the following meanings:++ Code Error+----- ------------------------------------+    1 PandocIOError+    3 PandocFailOnWarningError+    4 PandocAppError+    5 PandocTemplateError+    6 PandocOptionError+   21 PandocUnknownReaderError+   22 PandocUnknownWriterError+   23 PandocUnsupportedExtensionError+   24 PandocCiteprocError+   25 PandocBibliographyError+   31 PandocEpubSubdirectoryError+   43 PandocPDFError+   44 PandocXMLError+   47 PandocPDFProgramNotFoundError+   61 PandocHttpError+   62 PandocShouldNeverHappenError+   63 PandocSomeError+   64 PandocParseError+   66 PandocMakePDFError+   67 PandocSyntaxMapError+   83 PandocFilterError+   84 PandocLuaError+   89 PandocNoScriptingEngine+   91 PandocMacroLoop+   92 PandocUTF8DecodingError+   93 PandocIpynbDecodingError+   94 PandocUnsupportedCharsetError+   95 PandocInputNotTextError+   97 PandocCouldNotFindDataFileError+   98 PandocCouldNotFindMetadataFileError+   99 PandocResourceNotFound+----- ------------------------------------++# Defaults files++The `--defaults` option may be used to specify a package+of options, in the form of a YAML or JSON file. Examples in+this section will be given in YAML, but the equivalent forms in+JSON will also work.++Fields that are omitted will just have their regular+default values.  So a defaults file can be as simple as+one line:++``` yaml+verbosity: INFO+```++or in JSON:++``` json+{ "verbosity": "INFO" }+```++In fields that expect a file path (or list of file paths), the+following syntax may be used to interpolate environment variables:++``` yaml+csl:  ${HOME}/mycsldir/special.csl+```++`${USERDATA}` may also be used; this will always resolve to the+user data directory that is current when the defaults file is+parsed, regardless of the setting of the environment+variable `USERDATA`.++`${.}` will resolve to the directory containing the defaults+file itself.  This allows you to refer to resources contained+in that directory:++``` yaml+epub-cover-image: ${.}/cover.jpg+epub-metadata: ${.}/meta.xml+resource-path:+- .             # the working directory from which pandoc is run+- ${.}/images   # the images subdirectory of the directory+                # containing this defaults file+```++This environment variable interpolation syntax *only* works in+fields that expect file paths.++Defaults files can be placed in the `defaults` subdirectory of+the user data directory and used from any directory.  For+example, one could create a file specifying defaults for writing+letters, save it as `letter.yaml` in the `defaults` subdirectory+of the user data directory, and then invoke these defaults+from any directory using `pandoc --defaults letter`+or `pandoc -dletter`.++When multiple defaults are used, their contents will be combined.++Note that, where command-line arguments may be repeated+(`--metadata-file`, `--css`, `--include-in-header`,+`--include-before-body`, `--include-after-body`, `--variable`,+`--metadata`, `--syntax-definition`), the values specified on+the command line will combine with values specified in the+defaults file, rather than replacing them.++The following tables show the mapping between the command line and+defaults file entries.+++----------------------------------+-----------------------------------++| command line                     | defaults file                     |++:=================================+:==================================++| ```                              | ``` yaml                          |+| foo.md                           | input-file: foo.md                |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| foo.md bar.md                    | input-files:                      |+|                                  |   - foo.md                        |+|                                  |   - bar.md                        |+| ```                              | ```                               |++----------------------------------+-----------------------------------+++The value of `input-files` may be left empty to indicate input from+stdin, and it can be an empty sequence `[]` for no input.++## General options+++----------------------------------+-----------------------------------++| command line                     | defaults file                     |++:=================================+:==================================++| ```                              | ``` yaml                          |+| --from markdown+emoji            | from: markdown+emoji              |+| ```                              | ```                               |+|                                  | ``` yaml                          |+|                                  | reader: markdown+emoji            |+|                                  | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --to markdown+hard_line_breaks   | to: markdown+hard_line_breaks     |+| ```                              | ```                               |+|                                  | ``` yaml                          |+|                                  | writer: markdown+hard_line_breaks |+|                                  | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --output foo.pdf                 | output-file: foo.pdf              |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --output -                       | output-file:                      |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --data-dir dir                   | data-dir: dir                     |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --defaults file                  | defaults:                         |+| ```                              | - file                            |+|                                  | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --verbose                        | verbosity: INFO                   |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --quiet                          | verbosity: ERROR                  |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --fail-if-warnings               | fail-if-warnings: true            |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --sandbox                        | sandbox: true                     |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --log=FILE                       | log-file: FILE                    |+| ```                              | ```                               |++----------------------------------+-----------------------------------+++Options specified in a defaults file itself always have priority over+those in another file included with a `defaults:` entry.++`verbosity` can have the values `ERROR`, `WARNING`, or `INFO`.++## Reader options+++----------------------------------+-----------------------------------++| command line                     | defaults file                     |++:=================================+:==================================++| ```                              | ``` yaml                          |+| --shift-heading-level-by -1      | shift-heading-level-by: -1        |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --indented-code-classes python   | indented-code-classes:            |+|                                  |   - python                        |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --default-image-extension ".jpg" | default-image-extension: '.jpg'   |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --file-scope                     | file-scope: true                  |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --citeproc \                     | filters:                          |+|  --lua-filter count-words.lua \  |   - citeproc                      |+|  --filter special.lua            |   - count-words.lua               |+|                                  |   - type: json                    |+|                                  |     path: special.lua             |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --metadata key=value \           | metadata:                         |+|  --metadata key2                 |   key: value                      |+|                                  |   key2: true                      |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --metadata-file meta.yaml        | metadata-files:                   |+|                                  |   - meta.yaml                     |+| ```                              | ```                               |+|                                  | ``` yaml                          |+|                                  | metadata-file: meta.yaml          |+|                                  | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --preserve-tabs                  | preserve-tabs: true               |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --tab-stop 8                     | tab-stop: 8                       |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --track-changes accept           | track-changes: accept             |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --extract-media dir              | extract-media: dir                |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --abbreviations abbrevs.txt      | abbreviations: abbrevs.txt        |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --typst-input foo=bar            | typst-inputs:                     |+|                                  |   foo: bar                        |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --trace                          | trace: true                       |+| ```                              | ```                               |++----------------------------------+-----------------------------------+++Metadata values specified in a defaults file are parsed as literal+string text, not Markdown.++Filters will be assumed to be Lua filters if they have the `.lua`+extension, and JSON filters otherwise.  But the filter type can also be+specified explicitly, as shown.  Filters are run in the order specified.+To include the built-in citeproc filter, use either `citeproc` or+`{type: citeproc}`.++## General writer options+++----------------------------------+-----------------------------------++| command line                     | defaults file                     |++:=================================+:==================================++| ```                              | ``` yaml                          |+| --standalone                     | standalone: true                  |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --template letter                | template: letter                  |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --variable key=val \             | variables:                        |+|   --variable key2                |   key: val                        |+|                                  |   key2: true                      |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --eol nl                         | eol: nl                           |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --dpi 300                        | dpi: 300                          |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --wrap preserve                  | wrap: "preserve"                  |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --columns 72                     | columns: 72                       |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --table-of-contents              | table-of-contents: true           |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --toc                            | toc: true                         |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --toc-depth 3                    | toc-depth: 3                      |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --strip-comments                 | strip-comments: true              |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --no-highlight                   | syntax-highlighting: 'none'       |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --syntax-highlighting kate       | syntax-highlighting: kate         |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --syntax-definition mylang.xml   | syntax-definitions:               |+|                                  |   - mylang.xml                    |+| ```                              | ```                               |+|                                  | ``` yaml                          |+|                                  | syntax-definition: mylang.xml     |+|                                  | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --include-in-header inc.tex      | include-in-header:                |+|                                  |   - inc.tex                       |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --include-before-body inc.tex    | include-before-body:              |+|                                  |   - inc.tex                       |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --include-after-body inc.tex     | include-after-body:               |+|                                  |   - inc.tex                       |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --resource-path .:foo            | resource-path: ['.','foo']        |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --request-header foo:bar         | request-headers:                  |+|                                  |   - ["User-Agent", "Mozilla/5.0"] |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --no-check-certificate           | no-check-certificate: true        |+| ```                              | ```                               |++----------------------------------+-----------------------------------++++## Options affecting specific writers+++----------------------------------+-----------------------------------++| command line                     | defaults file                     |++:=================================+:==================================++| ```                              | ``` yaml                          |+| --self-contained                 | self-contained: true              |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --link-images                    | link-images: true                 |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --html-q-tags                    | html-q-tags: true                 |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --ascii                          | ascii: true                       |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --reference-links                | reference-links: true             |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --reference-location block       | reference-location: block         |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --figure-caption-position=above  | figure-caption-position: above    |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --table-caption-position=below   | table-caption-position: below     |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --markdown-headings atx          | markdown-headings: atx            |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --list-tables                    | list-tables: true                 |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --top-level-division chapter     | top-level-division: chapter       |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --number-sections                | number-sections: true             |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --number-offset=1,4              | number-offset: \[1,4\]            |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --listings                       | listings: true                    |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --list-of-figures                | list-of-figures: true             |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --lof                            | lof: true                         |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --list-of-tables                 | list-of-tables: true              |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --lot                            | lot: true                         |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --incremental                    | incremental: true                 |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --slide-level 2                  | slide-level: 2                    |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --section-divs                   | section-divs: true                |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --email-obfuscation references   | email-obfuscation: references     |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --id-prefix ch1                  | identifier-prefix: ch1            |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --title-prefix MySite            | title-prefix: MySite              |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --css styles/screen.css  \       | css:                              |+|   --css styles/special.css       |   - styles/screen.css             |+|                                  |   - styles/special.css            |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --reference-doc my.docx          | reference-doc: my.docx            |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --epub-cover-image cover.jpg     | epub-cover-image: cover.jpg       |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --epub-title-page=false          | epub-title-page: false            |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --epub-metadata meta.xml         | epub-metadata: meta.xml           |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --epub-embed-font special.otf \  | epub-fonts:                       |+|   --epub-embed-font headline.otf |   - special.otf                   |+|                                  |   - headline.otf                  |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --split-level 2                  | split-level: 2                    |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --chunk-template="%i.html"       | chunk-template: "%i.html"         |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --epub-subdirectory=""           | epub-subdirectory: ''             |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --ipynb-output best              | ipynb-output: best                |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --pdf-engine xelatex             | pdf-engine: xelatex               |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --pdf-engine-opt=--shell-escape  | pdf-engine-opts:                  |+|                                  |   - '-shell-escape'               |+| ```                              | ```                               |+|                                  | ``` yaml                          |+|                                  | pdf-engine-opt: '-shell-escape'   |+|                                  | ```                               |++----------------------------------+-----------------------------------+++## Citation rendering+++----------------------------------+-----------------------------------++| command line                     | defaults file                     |++:=================================+:==================================++| ```                              | ``` yaml                          |+| --citeproc                       | citeproc: true                    |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --bibliography logic.bib         | bibliography: logic.bib           |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --csl ieee.csl                   | csl: ieee.csl                     |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --citation-abbreviations ab.json | citation-abbreviations: ab.json   |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --natbib                         | cite-method: natbib               |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --biblatex                       | cite-method: biblatex             |+| ```                              | ```                               |++----------------------------------+-----------------------------------+++`cite-method` can be `citeproc`, `natbib`, or `biblatex`. This only+affects LaTeX output.  If you want to use citeproc to format citations,+you should also set 'citeproc: true'.++If you need control over when the citeproc processing is done relative+to other filters, you should instead use `citeproc` in the list+of `filters` (see [Reader options](#reader-options-1)).++## Math rendering in HTML+++----------------------------------+-----------------------------------++| command line                     | defaults file                     |++:=================================+:==================================++| ```                              | ``` yaml                          |+| --mathjax                        | html-math-method:                 |+|                                  |   method: mathjax                 |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --mathml                         | html-math-method:                 |+|                                  |   method: mathml                  |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --webtex                         | html-math-method:                 |+|                                  |   method: webtex                  |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --katex                          | html-math-method:                 |+|                                  |   method: katex                   |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --gladtex                        | html-math-method:                 |+|                                  |   method: gladtex                 |+| ```                              | ```                               |++----------------------------------+-----------------------------------+++In addition to the values listed above, `method` can have the+value `plain`.++If the command line option accepts a URL argument, an `url:` field can+be added to `html-math-method:`.++## Options for wrapper scripts+++----------------------------------+-----------------------------------++| command line                     | defaults file                     |++:=================================+:==================================++| ```                              | ``` yaml                          |+| --dump-args                      | dump-args: true                   |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --ignore-args                    | ignore-args: true                 |+| ```                              | ```                               |++----------------------------------+-----------------------------------+++# Templates++When the `-s/--standalone` option is used, pandoc uses a template to+add header and footer material that is needed for a self-standing+document.  To see the default template that is used, just type++    pandoc -D *FORMAT*++where *FORMAT* is the name of the output format. A custom template+can be specified using the `--template` option.  You can also override+the system default templates for a given output format *FORMAT*+by putting a file `templates/default.*FORMAT*` in the user data+directory (see `--data-dir`, above). *Exceptions:*++- For `odt` output, customize the `default.opendocument` template.+- For `docx` output, customize the `default.openxml` template.+- For `pdf` output, customize the `default.latex` template+  (or the `default.context` template, if you use `-t context`,+  or the `default.ms` template, if you use `-t ms`, or the+  `default.html` template, if you use `-t html`).+- `pptx` has no template.++Note that `docx`, `odt`, and `pptx` output can also be customized+using `--reference-doc`.  Use a reference doc to adjust the styles+in your document; use a template to handle variable interpolation and+customize the presentation of metadata, the position of the table+of contents, boilerplate text, etc.++Templates contain *variables*, which allow for the inclusion of+arbitrary information at any point in the file. They may be set at the+command line using the `-V/--variable` option. If a variable is not set,+pandoc will look for the key in the document's metadata, which can be set+using either [YAML metadata blocks][Extension: `yaml_metadata_block`]+or with the `-M/--metadata` option.  In addition, some variables+are given default values by pandoc.  See [Variables] below for+a list of variables used in pandoc's default templates.++If you use custom templates, you may need to revise them as pandoc+changes.  We recommend tracking the changes in the default templates,+and modifying your custom templates accordingly. An easy way to do this+is to fork the [pandoc-templates] repository and merge in+changes after each pandoc release.++  [pandoc-templates]: https://github.com/jgm/pandoc-templates++## Template syntax++### Comments++Anything between the sequence `$--` and the end of the+line will be treated as a comment and omitted from the output.++### Delimiters++To mark variables and control structures in the template,+either `$`...`$` or `${`...`}` may be used as delimiters.+The styles may also be mixed in the same template, but the+opening and closing delimiter must match in each case.  The+opening delimiter may be followed by one or more spaces+or tabs, which will be ignored. The closing delimiter may+be preceded by one or more spaces or tabs, which will be+ignored.++To include a literal `$` in the document, use `$$`.++### Interpolated variables++A slot for an interpolated variable is a variable name surrounded+by matched delimiters.  Variable names must begin with a letter+and can contain letters, numbers, `_`, `-`, and `.`.  The+keywords `it`, `if`, `else`, `endif`, `for`, `sep`, and `endfor` may+not be used as variable names. Examples:++```+$foo$+$foo.bar.baz$+$foo_bar.baz-bim$+$ foo $+${foo}+${foo.bar.baz}+${foo_bar.baz-bim}+${ foo }+```++Variable names with periods are used to get at structured+variable values.  So, for example, `employee.salary` will return the+value of the `salary` field of the object that is the value of+the `employee` field.++- If the value of the variable is a simple value, it will be+  rendered verbatim.  (Note that no escaping is done;+  the assumption is that the calling program will escape+  the strings appropriately for the output format.)+- If the value is a list, the values will be concatenated.+- If the value is a map, the string `true` will be rendered.+- Every other value will be rendered as the empty string.++### Conditionals++A conditional begins with `if(variable)` (enclosed in+matched delimiters) and ends with `endif` (enclosed in matched+delimiters).  It may optionally contain an `else` (enclosed in+matched delimiters).  The `if` section is used if+`variable` has a true value, otherwise the `else`+section is used (if present).  The following values count+as true:++- any map+- any array containing at least one true value+- any nonempty string+- boolean True++Note that in YAML metadata (and metadata specified on the+command line using `-M/--metadata`), unquoted `true` and `false` will be+interpreted as Boolean values. But a variable specified on the+command line using `-V/--variable` will always be given a string+value. Hence a conditional `if(foo)` will be triggered if you+use `-V foo=false`, but not if you use `-M foo=false`.++Examples:++```+$if(foo)$bar$endif$++$if(foo)$+  $foo$+$endif$++$if(foo)$+part one+$else$+part two+$endif$++${if(foo)}bar${endif}++${if(foo)}+  ${foo}+${endif}++${if(foo)}+${ foo.bar }+${else}+no foo!+${endif}+```++The keyword `elseif` may be used to simplify complex nested+conditionals:++```+$if(foo)$+XXX+$elseif(bar)$+YYY+$else$+ZZZ+$endif$+```++### For loops++A for loop begins with `for(variable)` (enclosed in+matched delimiters) and ends with `endfor` (enclosed in matched+delimiters).++- If `variable` is an array, the material inside the loop will+  be evaluated repeatedly, with `variable` being set to each+  value of the array in turn, and concatenated.+- If `variable` is a map, the material inside will be set to+  the map.+- If the value of the associated variable is not an array or+  a map, a single iteration will be performed on its value.++Examples:++```+$for(foo)$$foo$$sep$, $endfor$++$for(foo)$+  - $foo.last$, $foo.first$+$endfor$++${ for(foo.bar) }+  - ${ foo.bar.last }, ${ foo.bar.first }+${ endfor }++$for(mymap)$+$it.name$: $it.office$+$endfor$+```++You may optionally specify a separator between consecutive+values using `sep` (enclosed in matched delimiters).  The+material between `sep` and the `endfor` is the separator.++```+${ for(foo) }${ foo }${ sep }, ${ endfor }+```++Instead of using `variable` inside the loop, the special+anaphoric keyword `it` may be used.++```+${ for(foo.bar) }+  - ${ it.last }, ${ it.first }+${ endfor }+```++### Partials++Partials (subtemplates stored in different files) may be+included by using the name of the partial, followed+by `()`, for example:++```+${ styles() }+```++Partials will be sought in the directory containing+the main template. The file name will be assumed to+have the same extension as the main template if it+lacks an extension. When calling the partial, the+full name including file extension can also be used:++```+${ styles.html() }+```++(If a partial is not found in the directory of the+template and the template path is given as a relative+path, it will also be sought in the `templates`+subdirectory of the user data directory.)++Partials may optionally be applied to variables using+a colon:++```+${ date:fancy() }++${ articles:bibentry() }+```++If `articles` is an array, this will iterate over its+values, applying the partial `bibentry()` to each one.  So the+second example above is equivalent to++```+${ for(articles) }+${ it:bibentry() }+${ endfor }+```++Note that the anaphoric keyword `it` must be used when+iterating over partials.  In the above examples,+the `bibentry` partial should contain `it.title`+(and so on) instead of `articles.title`.++Final newlines are omitted from included partials.++Partials may include other partials.++A separator between values of an array may be specified+in square brackets, immediately after the variable name+or partial:++```+${months[, ]}++${articles:bibentry()[; ]}+```++The separator in this case is literal and (unlike with `sep`+in an explicit `for` loop) cannot contain interpolated+variables or other template directives.++### Nesting++To ensure that content is "nested," that is, subsequent lines+indented, use the `^` directive:++```+$item.number$  $^$$item.description$ ($item.price$)+```++In this example, if `item.description` has multiple lines,+they will all be indented to line up with the first line:++```+00123  A fine bottle of 18-year old+       Oban whiskey. ($148)+```++To nest multiple lines to the same level, align them+with the `^` directive in the template. For example:++```+$item.number$  $^$$item.description$ ($item.price$)+               (Available til $item.sellby$.)+```++will produce++```+00123  A fine bottle of 18-year old+       Oban whiskey. ($148)+       (Available til March 30, 2020.)+```++If a variable occurs by itself on a line, preceded by whitespace+and not followed by further text or directives on the same line,+and the variable's value contains multiple lines, it will be+nested automatically.++### Breakable spaces++Normally, spaces in the template itself (as opposed to values of+the interpolated variables) are not breakable, but they can be+made breakable in part of the template by using the `~` keyword+(ended with another `~`).++```+$~$This long line may break if the document is rendered+with a short line length.$~$+```++### Pipes++A pipe transforms the value of a variable or partial. Pipes are+specified using a slash (`/`) between the variable name (or partial)+and the pipe name. Example:++```+$for(name)$+$name/uppercase$+$endfor$++$for(metadata/pairs)$+- $it.key$: $it.value$+$endfor$++$employee:name()/uppercase$+```++Pipes may be chained:++```+$for(employees/pairs)$+$it.key/alpha/uppercase$. $it.name$+$endfor$+```++Some pipes take parameters:++```+|----------------------|------------|+$for(employee)$+$it.name.first/uppercase/left 20 "| "$$it.name.salary/right 10 " | " " |"$+$endfor$+|----------------------|------------|+```++Currently the following pipes are predefined:++- `pairs`:  Converts a map or array to an array of maps,+  each with `key` and `value` fields.  If the original+  value was an array, the `key` will be the array index,+  starting with 1.++- `uppercase`:  Converts text to uppercase.++- `lowercase`:  Converts text to lowercase.++- `length`:  Returns the length of the value:  number+  of characters for a textual value, number of elements+  for a map or array.++- `reverse`:  Reverses a textual value or array,+  and has no effect on other values.++- `first`: Returns the first value of an array, if+  applied to a non-empty array; otherwise returns+  the original value.++- `last`: Returns the last value of an array, if+  applied to a non-empty array; otherwise returns+  the original value.++- `rest`: Returns all but the first value of an array, if+  applied to a non-empty array; otherwise returns+  the original value.++- `allbutlast`: Returns all but the last value of an array, if+  applied to a non-empty array; otherwise returns+  the original value.++- `chomp`:  Removes trailing newlines (and breakable space).++- `nowrap`:  Disables line wrapping on breakable spaces.++- `alpha`:  Converts textual values that can be+  read as an integer into lowercase alphabetic+  characters `a..z` (mod 26). This can be used to get lettered+  enumeration from array indices.  To get uppercase+  letters, chain with `uppercase`.++- `roman`:  Converts textual values that can be+  read as an integer into lowercase roman numerals.+  This can be used to get lettered enumeration from array indices.+  To get uppercase roman, chain with `uppercase`.++- `left n "leftborder" "rightborder"`:  Renders a textual value+  in a block of width `n`, aligned to the left, with an optional+  left and right border.  Has no effect on other values. This+  can be used to align material in tables.  Widths are positive+  integers indicating the number of characters.  Borders+  are strings inside double quotes; literal `"` and `\` characters+  must be backslash-escaped.++- `right n "leftborder" "rightborder"`:  Renders a textual value+  in a block of width `n`, aligned to the right, and has no+  effect on other values.++- `center n "leftborder" "rightborder"`:  Renders a textual+  value in a block of width `n`, aligned to the center, and has+  no effect on other values.+++## Variables++### Metadata variables++`title`, `author`, `date`+:   allow identification of basic aspects of the document.  Included+    in PDF metadata through LaTeX and ConTeXt.  These can be set+    through a [pandoc title block][Extension: `pandoc_title_block`],+    which allows for multiple authors, or through a+    [YAML metadata block][Extension: `yaml_metadata_block`]:++        ---+        author:+        - Aristotle+        - Peter Abelard+        ...++    Note that if you just want to set PDF or HTML metadata, without+    including a title block in the document itself, you can+    set the `title-meta`, `author-meta`, and `date-meta`+    variables.  (By default these are set automatically, based+    on `title`, `author`, and `date`.) The page title in HTML+    is set by `pagetitle`, which is equal to `title` by default.++`subtitle`+:   document subtitle, included in HTML, EPUB, LaTeX, ConTeXt, and docx+    documents++`abstract`+:   document summary, included in HTML, LaTeX, ConTeXt, AsciiDoc, and docx+    documents++`abstract-title`+:   title of abstract, currently used only in HTML, EPUB, docx, and Typst.+    This will be set automatically to a localized value,+    depending on `lang`, but can be manually overridden.++`keywords`+:   list of keywords to be included in HTML, PDF, ODT, pptx, docx+    and AsciiDoc metadata; repeat as for `author`, above++`subject`+:   document subject, included in ODT, PDF, docx, EPUB, and pptx metadata++`description`+:   document description, included in ODT, docx and pptx metadata. Some+    applications show this as `Comments` metadata.++`category`+:   document category, included in docx and pptx metadata++Additionally,+any root-level string metadata, not included in ODT, docx+or pptx metadata is added as a *custom property*.+The following [YAML] metadata block for instance:++    ---+    title:  'This is the title'+    subtitle: "This is the subtitle"+    author:+    - Author One+    - Author Two+    description: |+        This is a long+        description.++        It consists of two paragraphs+    ...++will include `title`, `author` and `description` as standard document+properties and `subtitle` as a custom property when converting to docx,+ODT or pptx.++### Language variables++`lang`+:   identifies the main language of the document using IETF language+    tags (following the [BCP 47] standard), such as `en` or `en-GB`.+    The [Language subtag lookup] tool can look up or verify these tags.+    This affects most formats, and controls hyphenation in PDF output+    when using LaTeX (through [`babel`] and [`polyglossia`]) or ConTeXt.++    Use native pandoc [Divs and Spans] with the `lang` attribute to+    switch the language:++        ---+        lang: en-GB+        ...++        Text in the main document language (British English).++        ::: {lang=fr-CA}+        > Cette citation est écrite en français canadien.+        :::++        More text in English. ['Zitat auf Deutsch.']{lang=de}++`dir`+:   the base script direction, either `rtl` (right-to-left)+    or `ltr` (left-to-right).++    For bidirectional documents, native pandoc `span`s and+    `div`s with the `dir` attribute (value `rtl` or `ltr`) can+    be used to override the base direction in some output+    formats.  This may not always be necessary if the final+    renderer (e.g. the browser, when generating HTML) supports+    the [Unicode Bidirectional Algorithm].++    When using LaTeX for bidirectional documents, only the+    `xelatex` engine is fully supported (use+    `--pdf-engine=xelatex`).++[BCP 47]: https://tools.ietf.org/html/bcp47+[Unicode Bidirectional Algorithm]: https://www.w3.org/International/articles/inline-bidi-markup/uba-basics+[Language subtag lookup]: https://r12a.github.io/app-subtags/++### Variables for HTML++`document-css`+:   Enables inclusion of most of the [CSS] in the `styles.html`+    [partial](#partials) (have a look with+    `pandoc --print-default-data-file=templates/styles.html`).+    Unless you use `--css`, this variable+    is set to `true` by default. You can disable it with+    e.g. `pandoc -M document-css=false`.++`mainfont`+:   sets the CSS `font-family` property on the `html` element.++`fontsize`+:   sets the base CSS `font-size`, which you'd usually set+    to e.g. `20px`, but it also accepts `pt`+    (12pt = 16px in most browsers).++`fontcolor`+:   sets the CSS `color` property on the `html` element.++`linkcolor`+:   sets the CSS `color` property on all links.++`monofont`+:   sets the CSS `font-family` property on `code` elements.++`monobackgroundcolor`+:   sets the CSS `background-color` property on `code` elements+    and adds extra padding.++`linestretch`+:   sets the CSS `line-height` property on the `html` element,+    which is preferred to be unitless.++`maxwidth`+:   sets the CSS `max-width` property (default is 36em).++`backgroundcolor`+:   sets the CSS `background-color` property on the `html` element.++`margin-left`, `margin-right`, `margin-top`, `margin-bottom`+:   sets the corresponding CSS `padding` properties on the `body` element.++To override or extend some [CSS] for just one document, include for example:++    ---+    header-includes: |+      <style>+      blockquote {+        font-style: italic;+      }+      tr.even {+        background-color: #f0f0f0;+      }+      td, th {+        padding: 0.5em 2em 0.5em 0.5em;+      }+      tbody {+        border-bottom: none;+      }+      </style>+    ---++[CSS]: https://developer.mozilla.org/en-US/docs/Learn/CSS++### Variables for HTML math++`classoption`+:   when using `--katex`, you can render display math equations+    flush left using [YAML metadata](#layout) or with `-M+    classoption=fleqn`.++### Variables for HTML slides++These affect HTML output when [producing slide shows with+pandoc](#slide-shows).++`institute`+:   author affiliations: can be a list when there are multiple authors++`revealjs-url`+:   base URL for reveal.js documents (defaults to+    `https://unpkg.com/reveal.js@^5`)++`s5-url`+:   base URL for S5 documents (defaults to `s5/default`)++`slidy-url`+:   base URL for Slidy documents (defaults to+    `https://www.w3.org/Talks/Tools/Slidy2`)++`slideous-url`+:   base URL for Slideous documents (defaults to `slideous`)++`title-slide-attributes`+:   additional attributes for the title slide of reveal.js slide shows.+    See [background in reveal.js, beamer, and pptx] for an example.++`highlightjs-theme`+:   highlight.js theme for code highlighting when using+    `--syntax-highlighting=idiomatic` with reveal.js (defaults to+    `monokai`). See the [highlight.js demo page] for available themes.++[highlight.js demo page]: https://highlightjs.org/demo++All [reveal.js configuration options] are available as variables.+To turn off boolean flags that default to true in reveal.js, use `0`.++[reveal.js configuration options]: https://revealjs.com/config/++### Variables for Beamer slides++These variables change the appearance of PDF slides using [`beamer`].++`aspectratio`+:   slide aspect ratio (`43` for 4:3 [default], `169` for 16:9,+    `1610` for 16:10, `149` for 14:9, `141` for 1.41:1, `54` for 5:4,+    `32` for 3:2)++`beameroption`+:   add extra beamer option with `\setbeameroption{}`++`institute`+:   author affiliations: can be a list when there are multiple authors++`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`)++`section-titles`+:   enables "title pages" for new sections (default is true)++`theme`, `colortheme`, `fonttheme`, `innertheme`, `outertheme`+:   beamer themes++`themeoptions`, `colorthemeoptions`, `fontthemeoptions`, `innerthemeoptions`, `outerthemeoptions`+:   options for LaTeX beamer themes (lists)++`titlegraphic`+:   image for title slide: can be a list++`titlegraphicoptions`+:   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,+    institute, date++### Variables for PowerPoint++These variables control the visual aspects of a slide show that+are not easily controlled via templates.++`monofont`+:   font to use for code.++### Variables for LaTeX++Pandoc uses these variables when [creating a PDF] with a LaTeX engine.++#### Layout++`block-headings`+:   make `\paragraph` and `\subparagraph` (fourth- and+    fifth-level headings, or fifth- and sixth-level with book+    classes) free-standing rather than run-in; requires further+    formatting to distinguish from `\subsubsection` (third- or+    fourth-level headings). Instead of using this option,+    [KOMA-Script] can adjust headings more extensively:++        ---+        documentclass: scrartcl+        header-includes: |+          \RedeclareSectionCommand[+            beforeskip=-10pt plus -2pt minus -1pt,+            afterskip=1sp plus -1sp minus 1sp,+            font=\normalfont\itshape]{paragraph}+          \RedeclareSectionCommand[+            beforeskip=-10pt plus -2pt minus -1pt,+            afterskip=1sp plus -1sp minus 1sp,+            font=\normalfont\scshape,+            indent=0pt]{subparagraph}+        ...++`classoption`+:   option for document class, e.g. `oneside`; repeat for multiple options:++        ---+        classoption:+        - twocolumn+        - landscape+        ...++`documentclass`+:   document class: usually one of the standard classes,+    [`article`], [`book`], and [`report`]; the [KOMA-Script]+    equivalents, `scrartcl`, `scrbook`, and `scrreprt`, which+    default to smaller margins; or [`memoir`]++`geometry`+:   option for [`geometry`] package, e.g. `margin=1in`;+    repeat for multiple options:++        ---+        geometry:+        - top=30mm+        - left=20mm+        - heightrounded+        ...++`shorthands`+:   Enable language-specific shorthands when loading `babel`.+    (By default, pandoc includes `shorthands=off` when loading+    `babel`, disabling language-specific shorthands.)++`hyperrefoptions`+:   option for [`hyperref`] package, e.g. `linktoc=all`;+    repeat for multiple options:++        ---+        hyperrefoptions:+        - linktoc=all+        - pdfwindowui+        - pdfpagemode=FullScreen+        ...++`indent`+:   if true, pandoc will use document class settings for+    indentation (the default LaTeX template otherwise removes+    indentation and adds space between paragraphs)++`linestretch`+:   adjusts line spacing using the [`setspace`]+    package, e.g. `1.25`, `1.5`++`margin-left`, `margin-right`, `margin-top`, `margin-bottom`+:   sets margins if `geometry` is not used (otherwise `geometry`+    overrides these)++`pagestyle`+:   control `\pagestyle{}`: the default article class+    supports `plain` (default), `empty` (no running heads or page numbers),+    and `headings` (section titles in running heads)++`papersize`+:   paper size, e.g. `letter`, `a4`++`secnumdepth`+:   numbering depth for sections (with `--number-sections` option+    or `numbersections` variable)++`beamerarticle`+:   produce an article from Beamer slides.  Note: if you set+    this variable, you must specify the beamer writer but use the+    default *LaTeX* template: for example,+    `pandoc -Vbeamerarticle -t beamer --template default.latex`.++`handout`+:   produce a handout version of Beamer slides (with overlays condensed+    into single slides)++`csquotes`+:   load `csquotes` package and use `\enquote` or `\enquote*` for quoted text.++`csquotesoptions`+:   options to use for `csquotes` package (repeat for multiple options).++`babeloptions`+:   options to pass to the babel package (may be repeated for+    multiple options). This defaults to `provide=*` if the main+    language isn't a European language written with Latin or+    Cyrillic script or Vietnamese. Most users will not need to+    adjust the default setting.++#### Fonts++`fontenc`+:   allows font encoding to be specified through `fontenc` package (with+    `pdflatex`); default is `T1` (see [LaTeX font encodings guide])++`fontfamily`+:   font package for use with `pdflatex`:+    [TeX Live] includes many options, documented in the [LaTeX Font Catalogue].+    The default is [Latin Modern][`lm`].++`fontfamilyoptions`+:   options for package used as `fontfamily`; repeat for multiple options.+    For example, to use the Libertine font with proportional lowercase+    (old-style) figures through the [`libertinus`] package:++        ---+        fontfamily: libertinus+        fontfamilyoptions:+        - osf+        - p+        ...++`fontsize`+:   font size for body text. The standard classes allow 10pt, 11pt, and+    12pt.  To use another size, set `documentclass` to one of+    the [KOMA-Script] classes, such as `scrartcl` or `scrbook`.++`mainfont`, `sansfont`, `monofont`, `mathfont`, `CJKmainfont`, `CJKsansfont`, `CJKmonofont`+:   font families for use with `xelatex` or+    `lualatex`: take the name of any system font, using the+    [`fontspec`] package.  `CJKmainfont` uses the [`xecjk`] package if `xelatex` is used,+    or the [`luatexja`] package if `lualatex` is used.++`mainfontoptions`, `sansfontoptions`, `monofontoptions`, `mathfontoptions`, `CJKoptions`, `luatexjapresetoptions`+:   options to use with `mainfont`, `sansfont`, `monofont`, `mathfont`,+    `CJKmainfont` in `xelatex` and `lualatex`.  Allow for any+    choices available through [`fontspec`]; repeat for multiple+    options. For example, to use the [TeX Gyre] version of+    Palatino with lowercase figures:++        ---+        mainfont: TeX Gyre Pagella+        mainfontoptions:+        - Numbers=Lowercase+        - Numbers=Proportional+        ...++`mainfontfallback`, `sansfontfallback`, `monofontfallback`+:   fonts to try if a glyph isn't found in `mainfont`, `sansfont`, or `monofont`+    respectively. These are lists. The font name must be followed by a colon+    and optionally a set of options, for example:++        ---+        mainfontfallback:+          - "FreeSans:"+          - "NotoColorEmoji:mode=harf"+        ...++    Font fallbacks currently only work with `lualatex`.++`babelfonts`+:   a map of Babel language names (e.g. `chinese`) to the font+    to be used with the language:++        ---+        babelfonts:+          chinese-hant: "Noto Serif CJK TC"+          russian: "Noto Serif"+        ...++`microtypeoptions`+:    options to pass to the microtype package++#### Links++`colorlinks`+:   add color to link text; automatically enabled if any of+    `linkcolor`, `filecolor`, `citecolor`, `urlcolor`, or `toccolor` are set++`boxlinks`+:   add visible box around links (has no effect if `colorlinks` is set)++`linkcolor`, `filecolor`, `citecolor`, `urlcolor`, `toccolor`+:   color for internal links, external links, citation links, linked+    URLs, and links in table of contents, respectively: uses options+    allowed by [`xcolor`], including the `dvipsnames`, `svgnames`, and+    `x11names` lists++`links-as-notes`+:   causes links to be printed as footnotes++`urlstyle`+:   style for URLs (e.g., `tt`, `rm`, `sf`, and, the default, `same`)++#### Front matter++`lof`, `lot`+:   include list of figures, list of tables (can also be set using+    `--lof/--list-of-figures`, `--lot/--list-of-tables`)++`thanks`+:   contents of acknowledgments footnote after document title++`toc`+:   include table of contents (can also be set using+    `--toc/--table-of-contents`)++`toc-depth`+:   level of section to include in table of contents++#### BibLaTeX Bibliographies++These variables function when using BibLaTeX for [citation rendering].++`biblatexoptions`+:   list of options for biblatex++`biblio-style`+:   bibliography style, when used with `--natbib` and `--biblatex`++`biblio-title`+:   bibliography title, when used with `--natbib` and `--biblatex`++`bibliography`+:   bibliography to use for resolving references++`natbiboptions`+:   list of options for natbib++#### Other++`pdf-trailer-id`+:   the PDF trailer ID; must be two PDF byte strings if set,+    conventionally with 16 bytes each. E.g.,+    `<00112233445566778899aabbccddeeff>+    <00112233445566778899aabbccddeeff>`.++    See the section on [reproducible builds].++`pdfstandard`+:   PDF standard(s) for the document, e.g. `ua-2`, `a-4f`.+    Supports PDF/A, PDF/X, and PDF/UA variants.+    Requires LuaLaTeX and LaTeX 2023+. Repeat for multiple standards:++        ---+        pdfstandard:+        - ua-2+        - a-4f+        ...++[KOMA-Script]: https://ctan.org/pkg/koma-script+[LaTeX Font Catalogue]: https://tug.org/FontCatalogue/+[LaTeX font encodings guide]: https://ctan.org/pkg/encguide+[TeX Gyre]: http://www.gust.org.pl/projects/e-foundry/tex-gyre+[`article`]: https://ctan.org/pkg/article+[`book`]: https://ctan.org/pkg/book+[`libertinus`]: https://ctan.org/pkg/libertinus+[`memoir`]: https://ctan.org/pkg/memoir+[`report`]: https://ctan.org/pkg/report++### Variables for ConTeXt++Pandoc uses these variables when [creating a PDF] with ConTeXt.++`fontsize`+:   font size for body text (e.g. `10pt`, `12pt`)++`headertext`, `footertext`+:   text to be placed in running header or footer (see [ConTeXt Headers and+    Footers]); repeat up to four times for different placement++`indenting`+:   controls indentation of paragraphs, e.g. `yes,small,next` (see+    [ConTeXt Indentation]); repeat for multiple options++`interlinespace`+:   adjusts line spacing, e.g. `4ex` (using [`setupinterlinespace`]);+    repeat for multiple options++`layout`+:   options for page margins and text arrangement (see [ConTeXt Layout]);+    repeat for multiple options++`linkcolor`, `contrastcolor`+:   color for links outside and inside a page, e.g. `red`, `blue` (see+    [ConTeXt Color])++`linkstyle`+:   typeface style for links, e.g. `normal`, `bold`, `slanted`, `boldslanted`,+    `type`, `cap`, `small`++`lof`, `lot`+:   include list of figures, list of tables++`mainfont`, `sansfont`, `monofont`, `mathfont`+:   font families: take the name of any system font (see+    [ConTeXt Font Switching])++`mainfontfallback`, `sansfontfallback`, `monofontfallback`+:   list of fonts to try, in order, if a glyph is not found in the+    main font. Use `\definefallbackfamily`-compatible font name syntax.+    Emoji fonts are unsupported.++`margin-left`, `margin-right`, `margin-top`, `margin-bottom`+:   sets margins, if `layout` is not used (otherwise `layout`+    overrides these)++`pagenumbering`+:   page number style and location (using [`setuppagenumbering`]);+    repeat for multiple options++`papersize`+:   paper size, e.g. `letter`, `A4`, `landscape` (see [ConTeXt Paper Setup]);+    repeat for multiple options++`pdfa`+:   adds to the preamble the setup necessary to generate PDF/A+    of the type specified, e.g. `1a:2005`, `2a`. If no type is+    specified (i.e. the value is set to True, by e.g.+    `--metadata=pdfa` or `pdfa: true` in a YAML metadata block),+    `1b:2005` will be used as default, for reasons of backwards+    compatibility. Using `--variable=pdfa` without specified value+    is not supported.  To successfully generate PDF/A the required+    ICC color profiles have to be available and the content and all+    included files (such as images) have to be standard-conforming.+    The ICC profiles and output intent may be specified using the+    variables `pdfaiccprofile` and `pdfaintent`.  See also [ConTeXt+    PDFA] for more details.++`pdfaiccprofile`+:   when used in conjunction with `pdfa`, specifies the ICC profile to use+    in the PDF, e.g. `default.cmyk`. If left unspecified, `sRGB.icc` is+    used as default. May be repeated to include multiple profiles. Note that+    the profiles have to be available on the system. They can be obtained+    from [ConTeXt ICC Profiles].++`pdfaintent`+:   when used in conjunction with `pdfa`, specifies the output intent for+    the colors, e.g. `ISO coated v2 300\letterpercent\space (ECI)`+    If left unspecified, `sRGB IEC61966-2.1` is used as default.++`toc`+:   include table of contents (can also be set using+    `--toc/--table-of-contents`)++`urlstyle`+:   typeface style for links without link text, e.g. `normal`, `bold`, `slanted`, `boldslanted`,+    `type`, `cap`, `small`++`whitespace`+:   spacing between paragraphs, e.g. `none`, `small` (using+    [`setupwhitespace`])++`includesource`+:   include all source documents as file attachments in the PDF file++[ConTeXt Paper Setup]: https://wiki.contextgarden.net/Document_layout_and_layers/Paper_setup+[ConTeXt Layout]: https://wiki.contextgarden.net/Document_layout_and_layers/Tutorials+[ConTeXt Font Switching]: https://wiki.contextgarden.net/Characters_words_and_fonts/Tutorials+[ConTeXt Color]: https://wiki.contextgarden.net/Color+[ConTeXt Headers and Footers]: https://wiki.contextgarden.net/Document_layout_and_layers/Headers_and_footers+[ConTeXt Indentation]: https://wiki.contextgarden.net/Text_blocks/Typography/Indentation+[ConTeXt PDFA]: https://wiki.contextgarden.net/Input_and_compilation/PDF/PDFA+[ConTeXt ICC Profiles]: https://wiki.contextgarden.net/Input_and_compilation/PDF/PDFX#ICC_profiles+[`setupwhitespace`]: https://wiki.contextgarden.net/Command/setupwhitespace+[`setupinterlinespace`]: https://wiki.contextgarden.net/Command/setupinterlinespace+[`setuppagenumbering`]: https://wiki.contextgarden.net/Command/setuppagenumbering++### Variables for `wkhtmltopdf`++Pandoc uses these variables when [creating a PDF] with [`wkhtmltopdf`].+The `--css` option also affects the output.++`footer-html`, `header-html`+:   add information to the header and footer++`margin-left`, `margin-right`, `margin-top`, `margin-bottom`+:   set the page margins++`papersize`+:   sets the PDF paper size++### Variables for man pages++`adjusting`+:   adjusts text to left (`l`), right (`r`), center (`c`),+    or both (`b`) margins++`footer`+:   footer in man pages++`header`+:   header in man pages++`section`+:   section number in man pages++### Variables for Texinfo++`version`+:   version of software (used in title and title page)++`filename`+:   name of info file to be generated (defaults to a name based on the+    texi filename)++### Variables for Typst++`template`+:   Typst template to use (relative path only).++`margin`+:   A dictionary with the fields defined in the Typst documentation:+    `x`, `y`, `top`, `bottom`, `left`, `right`.++`papersize`+:    Paper size: `a4`, `us-letter`, etc.++`mainfont`+:    Name of system font to use for the main font.++`fontsize`+:    Font size (e.g., `12pt`).++`section-numbering`+:    Schema to use for numbering sections, e.g. `1.A.1`.++`page-numbering`+:    Schema to use for numbering pages, e.g. `1` or `i`, or+     an empty string to omit page numbering.++`columns`+:    Number of columns for body text.++`thanks`+:   contents of acknowledgments footnote after document title++`mathfont`, `codefont`+:    Name of system font to use for math and code, respectively.++`linestretch`+:   adjusts line spacing, e.g. `1.25`, `1.5`++`linkcolor`, `filecolor`, `citecolor`+:   color for external links, internal links, and citation links,+    respectively: expects a hexadecimal color code++### Variables for ms++`fontfamily`+:   `A` (Avant Garde), `B` (Bookman), `C` (Helvetica), `HN`+    (Helvetica Narrow), `P` (Palatino), or `T` (Times New Roman).+    This setting does not affect source code, which is always+    displayed using monospace Courier. These built-in fonts are+    limited in their coverage of characters. Additional fonts may+    be installed using the script [`install-font.sh`] provided+    by Peter Schaffter and documented in detail on [his web+    site][ms-font-steps].++`indent`+:   paragraph indent (e.g. `2m`)++`lineheight`+:   line height (e.g. `12p`)++`pointsize`+:   point size (e.g. `10p`)++[`install-font.sh`]: https://www.schaffter.ca/mom/bin/install-font.sh+[ms-font-steps]: https://www.schaffter.ca/mom/momdoc/appendices.html#steps++### Variables set automatically++Pandoc sets these variables automatically in response to [options] or+document contents; users can also modify them. These vary depending+on the output format, and include the following:++`body`+:   body of document++`date-meta`+:   the `date` variable converted to ISO 8601 YYYY-MM-DD,+    included in all HTML based formats (dzslides, epub,+    html, html4, html5, revealjs, s5, slideous, slidy).+    The recognized formats for `date` are: `mm/dd/yyyy`,+    `mm/dd/yy`, `yyyy-mm-dd` (ISO 8601), `dd MM yyyy`+    (e.g. either `02 Apr 2018` or `02 April 2018`),+    `MM dd, yyyy` (e.g. `Apr. 02, 2018` or `April 02, 2018),+    `yyyy[mm[dd]]` (e.g. `20180402, `201804` or `2018`).++`header-includes`+:   contents specified by `-H/--include-in-header` (may have multiple+    values)++`include-before`+:   contents specified by `-B/--include-before-body` (may have+    multiple values)++`include-after`+:   contents specified by `-A/--include-after-body` (may have+    multiple values)++`meta-json`+:   JSON representation of all of the document's metadata. Field+    values are transformed to the selected output format.++`numbersections`+:   non-null value if `-N/--number-sections` was specified++`sourcefile`, `outputfile`+:   source and destination filenames, as given on the command line.+    `sourcefile` can also be a list if input comes from multiple files,+    or empty if input is from stdin. You can use the following snippet in+    your template to distinguish them:++        $if(sourcefile)$+        $for(sourcefile)$+        $sourcefile$+        $endfor$+        $else$+        (stdin)+        $endif$++    Similarly, `outputfile` can be `-` if output goes to the terminal.++    If you need absolute paths, use e.g. `$curdir$/$sourcefile$`.++`pdf-engine`+:   name of PDF engine if provided using `--pdf-engine`, or the+    default engine for the format if PDF output is requested.++`curdir`+:   working directory from which pandoc is run.++`pandoc-version`+:   pandoc version.++`toc`+:   non-null value if `--toc/--table-of-contents` was specified++`toc-title`+:   title of table of contents (works only with EPUB,+    HTML, revealjs, opendocument, odt, docx, pptx, beamer, LaTeX).+    Note that in docx and pptx a custom `toc-title` will be+    picked up from metadata, but cannot be set as a variable.++[pandoc-templates]: https://github.com/jgm/pandoc-templates++# Extensions++The behavior of some of the readers and writers can be adjusted by+enabling or disabling various extensions.++An extension can be enabled by adding `+EXTENSION`+to the format name and disabled by adding `-EXTENSION`. For example,+`--from markdown_strict+footnotes` is strict Markdown with footnotes+enabled, while `--from markdown-footnotes-pipe_tables` is pandoc's+Markdown without footnotes or pipe tables.++The Markdown reader and writer make by far the most use of extensions.+Extensions only used by them are therefore covered in the+section [Pandoc's Markdown] below (see [Markdown variants] for+`commonmark` and `gfm`). In the following, extensions that also work+for other formats are covered.++Note that Markdown extensions added to the `ipynb` format+affect Markdown cells in Jupyter notebooks (as do command-line+options like `--markdown-headings`).++## Typography++### Extension: `smart` ###++Interpret straight quotes as curly quotes, `---` as em-dashes,+`--` as en-dashes, and `...` as ellipses. Nonbreaking spaces are+inserted after certain abbreviations, such as "Mr."++This extension can be enabled/disabled for the following formats:++input formats+:  `markdown`, `commonmark`, `latex`, `mediawiki`, `org`, `rst`, `twiki`,+   `html`++output formats+:  `markdown`, `latex`, `context`, `org`, `rst`++enabled by default in+:  `markdown`, `latex`, `context` (both input and output)++Note: If you are *writing* Markdown, then the `smart` extension+has the reverse effect: what would have been curly quotes comes+out straight.++In LaTeX, `smart` means to use the standard TeX ligatures+for quotation marks (` `` ` and ` '' ` for double quotes,+`` ` `` and `` ' `` for single quotes) and dashes (`--` for+en-dash and `---` for em-dash).  If `smart` is disabled,+then in reading LaTeX pandoc will parse these characters+literally.  In writing LaTeX, enabling `smart` tells pandoc+to use the ligatures when possible; if `smart` is disabled+pandoc will use unicode quotation mark and dash characters.++## Headings and sections++### Extension: `auto_identifiers` ###++A heading without an explicitly specified identifier will be+automatically assigned a unique identifier based on the heading text.++This extension can be enabled/disabled for the following formats:++input formats+:  `markdown`, `latex`, `rst`, `mediawiki`, `textile`, `man`++output formats+:  `markdown`, `muse`++enabled by default in+:  `markdown`, `muse`, `man`++The default algorithm used to derive the identifier from the+heading text is:++  - Remove all formatting, links, etc.+  - Remove all footnotes.+  - Remove all non-alphanumeric characters,+    except underscores, hyphens, and periods.+  - Replace all spaces and newlines with hyphens.+  - Convert all alphabetic characters to lowercase.+  - Remove everything up to the first letter (identifiers may+    not begin with a number or punctuation mark).+  - If nothing is left after this, use the identifier `section`.++Thus, for example,++  Heading                           Identifier+  -------------------------------   ----------------------------+  `Heading identifiers in HTML`     `heading-identifiers-in-html`+  `Maître d'hôtel`                  `maître-dhôtel`+  `*Dogs*?--in *my* house?`         `dogs--in-my-house`+  `[HTML], [S5], or [RTF]?`         `html-s5-or-rtf`+  `3. Applications`                 `applications`+  `33`                              `section`++These rules should, in most cases, allow one to determine the identifier+from the heading text. The exception is when several headings have the+same text; in this case, the first will get an identifier as described+above; the second will get the same identifier with `-1` appended; the+third with `-2`; and so on.++(However, a different algorithm is used if+`gfm_auto_identifiers` is enabled; see below.)++These identifiers are used to provide link targets in the table of+contents generated by the `--toc|--table-of-contents` option. They+also make it easy to provide links from one section of a document to+another. A link to this section, for example, might look like this:++    See the section on+    [heading identifiers](#heading-identifiers-in-html-latex-and-context).++Note, however, that this method of providing links to sections works+only in HTML, LaTeX, and ConTeXt formats.++If the `--section-divs` option is specified, then each section will+be wrapped in a `section` (or a `div`, if `html4` was specified),+and the identifier will be attached to the enclosing `<section>`+(or `<div>`) tag rather than the heading itself. This allows entire+sections to be manipulated using JavaScript or treated differently in+CSS.++### Extension: `ascii_identifiers` ###++Causes the identifiers produced by `auto_identifiers` to be pure ASCII.+Accents are stripped off of accented Latin letters, and non-Latin+letters are omitted.++### Extension: `gfm_auto_identifiers` ###++Changes the algorithm used by `auto_identifiers` to conform to+GitHub's method.  Spaces are converted to dashes (`-`),+uppercase characters to lowercase characters, and punctuation+characters other than `-` and `_` are removed.+Emojis are replaced by their names.++## Math Input++The extensions [`tex_math_dollars`](#extension-tex_math_dollars),+[`tex_math_gfm`](#extension-tex_math_gfm),+[`tex_math_single_backslash`](#extension-tex_math_single_backslash), and+[`tex_math_double_backslash`](#extension-tex_math_double_backslash)+are described in the section about Pandoc's Markdown.++However, they can also be used with HTML input. This is handy for+reading web pages formatted using MathJax, for example.++## Raw HTML/TeX++The following extensions are described in more detail in+their respective sections of [Pandoc's Markdown]:++- [`raw_html`](#extension-raw_html) allows HTML elements which+  are not representable in pandoc's AST to be parsed as raw HTML.+  By default, this is disabled for HTML input.++- [`raw_tex`](#extension-raw_tex) allows raw LaTeX, TeX, and ConTeXt+  to be included in a document.  This extension can be enabled/disabled+  for the following formats (in addition to `markdown`):++  input formats+  :  `latex`, `textile`, `html` (environments, `\ref`, and+     `\eqref` only), `ipynb`++  output formats+  :  `textile`, `commonmark`++  Note: as applied to `ipynb`, `raw_html` and `raw_tex` affect not+  only raw TeX in Markdown cells, but data with mime type+  `text/html` in output cells.  Since the `ipynb` reader attempts+  to preserve the richest possible outputs when several options+  are given, you will get best results if you disable `raw_html`+  and `raw_tex` when converting to formats like `docx` which don't+  allow raw `html` or `tex`.++- [`native_divs`](#extension-native_divs) causes HTML `div`+  elements to be parsed as native pandoc Div blocks.+  If you want them to be parsed as raw HTML, use+  `-f html-native_divs+raw_html`.++- [`native_spans`](#extension-native_spans) causes HTML `span`+  elements to be parsed as native pandoc Span inlines.+  If you want them to be parsed as raw HTML, use+  `-f html-native_spans+raw_html`.  If you want to drop all+  `div`s and `span`s when converting HTML to Markdown, you+  can use `pandoc -f html-native_divs-native_spans -t markdown`.++## Literate Haskell support++### Extension: `literate_haskell` ###++Treat the document as literate Haskell source.++This extension can be enabled/disabled for the following formats:++input formats+:  `markdown`, `rst`, `latex`++output formats+:  `markdown`, `rst`, `latex`, `html`++If you append `+lhs` (or `+literate_haskell`) to one of the formats+above, pandoc will treat the document as literate Haskell source.+This means that++  - In Markdown input, "bird track" sections will be parsed as Haskell+    code rather than block quotations.  Text between `\begin{code}`+    and `\end{code}` will also be treated as Haskell code.  For+    ATX-style headings the character '=' will be used instead of '#'.++  - In Markdown output, code blocks with classes `haskell` and `literate`+    will be rendered using bird tracks, and block quotations will be+    indented one space, so they will not be treated as Haskell code.+    In addition, headings will be rendered setext-style (with underlines)+    rather than ATX-style (with '#' characters). (This is because ghc+    treats '#' characters in column 1 as introducing line numbers.)++  - In restructured text input, "bird track" sections will be parsed+    as Haskell code.++  - In restructured text output, code blocks with class `haskell` will+    be rendered using bird tracks.++  - In LaTeX input, text in `code` environments will be parsed as+    Haskell code.++  - In LaTeX output, code blocks with class `haskell` will be rendered+    inside `code` environments.++  - In HTML output, code blocks with class `haskell` will be rendered+    with class `literatehaskell` and bird tracks.++Examples:++    pandoc -f markdown+lhs -t html++reads literate Haskell source formatted with Markdown conventions and writes+ordinary HTML (without bird tracks).++    pandoc -f markdown+lhs -t html+lhs++writes HTML with the Haskell code in bird tracks, so it can be copied+and pasted as literate Haskell source.++Note that GHC expects the bird tracks in the first column, so indented+literate code blocks (e.g. inside an itemized environment) will not be+picked up by the Haskell compiler.++## Other extensions++### Extension: `empty_paragraphs` ###++Allows empty paragraphs.  By default empty paragraphs are+omitted.++This extension can be enabled/disabled for the following formats:++input formats+:  `docx`, `html`++output formats+:  `docx`, `odt`, `opendocument`, `html`, `latex`++### Extension: `native_numbering` ###++Enables native numbering of figures and tables. Enumeration+starts at 1.++This extension can be enabled/disabled for the following formats:++output formats+:  `odt`, `opendocument`, `docx`++### Extension: `xrefs_name` ###++Links to headings, figures and tables inside the document are+substituted with cross-references that will use the name or caption+of the referenced item. The original link text is replaced once+the generated document is refreshed. This extension can be combined+with `xrefs_number` in which case numbers will appear before the+name.++Text in cross-references is only made consistent with the referenced+item once the document has been refreshed.++This extension can be enabled/disabled for the following formats:++output formats+:  `odt`, `opendocument`++### Extension: `xrefs_number` ###++Links to headings, figures and tables inside the document are+substituted with cross-references that will use the number+of the referenced item. The original link text is discarded.+This extension can be combined with `xrefs_name` in which case+the name or caption numbers will appear after the number.++For the `xrefs_number` to be useful heading numbers must be enabled+in the generated document, also table and figure captions must be enabled+using for example the `native_numbering` extension.++Numbers in cross-references are only visible in the final document once+it has been refreshed.++This extension can be enabled/disabled for the following formats:++output formats+:  `odt`, `opendocument`++### Extension: `styles` ### {#ext-styles}++When converting from docx, add `custom-styles` attributes+for all docx styles, regardless of whether pandoc understands+the meanings of these styles. Because attributes cannot be+added directly to paragraphs or text in the pandoc AST,+paragraph styles will cause Divs to be created and character+styles will cause Spans to be created to hold the attributes.+(Table styles will be added to the Table elements directly.)+This extension can be used with [docx custom styles](#custom-styles).++input formats+:  `docx`++### Extension: `amuse` ###++In the `muse` input format, this enables Text::Amuse+extensions to Emacs Muse markup.++### Extension: `raw_markdown` ###++In the `ipynb` input format, this causes Markdown cells+to be included as raw Markdown blocks (allowing lossless+round-tripping) rather than being parsed.  Use this only+when you are targeting `ipynb` or a Markdown-based+output format.++### Extension: `citations` (typst) {#typst-citations}++When the `citations` extension is enabled in `typst`+(as it is by default), `typst` citations will+be parsed as native pandoc citations, and native+pandoc citations will be rendered as `typst` citations.++### Extension: `citations` (org) {#org-citations}++When the `citations` extension is enabled in `org`,+org-cite and org-ref style citations will be parsed as+native pandoc citations, and org-cite citations will+be used to render native pandoc citations.++  [org-cite]: https://orgmode.org/manual/Citations.html+  [org-ref]:  https://github.com/jkitchin/org-ref++### Extension: `citations` (docx) {#docx-citations}++When `citations` is enabled in `docx`, citations inserted+by Zotero or Mendeley or EndNote plugins will be parsed as native+pandoc citations.  (Otherwise, the formatted citations generated+by the bibliographic software will be parsed as regular text.)++### Extension: `fancy_lists` (org) {#org-fancy-lists}++Some aspects of [Pandoc's Markdown fancy lists](#extension-fancy_lists) are also+accepted in `org` input, mimicking the option `org-list-allow-alphabetical` in+Emacs. As in Org Mode, enabling this extension allows lowercase and uppercase+alphabetical markers for ordered lists to be parsed in addition to arabic ones.+Note that for Org, this does not include roman numerals or the `#` placeholder+that are enabled by the extension in Pandoc's Markdown.++### Extension: `element_citations` ###++In the `jats` output formats, this causes reference items to+be replaced with `<element-citation>` elements. These+elements are not influenced by CSL styles, but all information+on the item is included in tags.++### Extension: `ntb` ###++In the `context` output format this enables the use of [Natural Tables+(TABLE)](https://wiki.contextgarden.net/TABLE) instead of the default+[Extreme Tables (xtables)](https://wiki.contextgarden.net/xtables).+Natural tables allow more fine-grained global customization but come+at a performance penalty compared to extreme tables.++### Extension: `smart_quotes` (org) ###++Interpret straight quotes as curly quotes during parsing. When+*writing* Org, then the `smart_quotes` extension has the reverse+effect: what would have been curly quotes comes out straight.++This extension is implied if `smart` is enabled.++### Extension: `special_strings` (org) ###++Interpret `---` as em-dashes, `--` as en-dashes, `\-` as shy+hyphen, and `...` as ellipses.++This extension is implied if `smart` is enabled.++### Extension: `tagging` ### {#extension--tagging}++Enabling this extension with `context` output will produce markup+suitable for the production of tagged PDFs. This includes+additional markers for paragraphs and alternative markup for+emphasized text. The `emphasis-command` template variable is set+if the extension is enabled.++# Pandoc's Markdown++Pandoc understands an extended and slightly revised version of+John Gruber's [Markdown] syntax.  This document explains the syntax,+noting differences from original Markdown. Except where noted, these+differences can be suppressed by using the `markdown_strict` format instead+of `markdown`. Extensions can be enabled or disabled to specify the+behavior more granularly. They are described in the following. See also+[Extensions] above, for extensions that work also on other formats.++## Philosophy++Markdown is designed to be easy to write, and, even more importantly,+easy to read:++> A Markdown-formatted document should be publishable as-is, as plain+> text, without looking like it's been marked up with tags or formatting+> instructions.\+> -- [John Gruber](https://daringfireball.net/projects/markdown/syntax#philosophy)++This principle has guided pandoc's decisions in finding syntax for+tables, footnotes, and other extensions.++There is, however, one respect in which pandoc's aims are different+from the original aims of Markdown.  Whereas Markdown was originally+designed with HTML generation in mind, pandoc is designed for multiple+output formats.  Thus, while pandoc allows the embedding of raw HTML,+it discourages it, and provides other, non-HTMLish ways of representing+important document elements like definition lists, tables, mathematics, and+footnotes.++## Paragraphs++A paragraph is one or more lines of text followed by one or more blank lines.+Newlines are treated as spaces, so you can reflow your paragraphs as you like.+If you need a hard line break, put two or more spaces at the end of a line.++### Extension: `escaped_line_breaks` ###++A backslash followed by a newline is also a hard line break.+Note:  in multiline and grid table cells, this is the only way+to create a hard line break, since trailing spaces in the cells+are ignored.++## Headings++There are two kinds of headings: Setext and ATX.++### Setext-style headings ###++A setext-style heading is a line of text "underlined" with a row of `=` signs+(for a level-one heading) or `-` signs (for a level-two heading):++    A level-one heading+    ===================++    A level-two heading+    -------------------++The heading text can contain inline formatting, such as emphasis (see+[Inline formatting], below).+++### ATX-style headings ###++An ATX-style heading consists of one to six `#` signs and a line of+text, optionally followed by any number of `#` signs.  The number of+`#` signs at the beginning of the line is the heading level:++    ## A level-two heading++    ### A level-three heading ###++As with setext-style headings, the heading text can contain formatting:++    # A level-one heading with a [link](/url) and *emphasis*++### Extension: `blank_before_header` ###++Original Markdown syntax does not require a blank line before a heading.+Pandoc does require this (except, of course, at the beginning of the+document). The reason for the requirement is that it is all too easy for a+`#` to end up at the beginning of a line by accident (perhaps through line+wrapping). Consider, for example:++    I like several of their flavors of ice cream:+    #22, for example, and #5.++### Extension: `space_in_atx_header` ###++Many Markdown implementations do not require a space between the+opening `#`s of an ATX heading and the heading text, so that+`#5 bolt` and `#hashtag` count as headings.  With this extension,+pandoc does require the space.++### Heading identifiers ###++See also the [`auto_identifiers`+extension](#extension-auto_identifiers) above.++### Extension: `header_attributes` ###++Headings can be assigned attributes using this syntax at the end+of the line containing the heading text:++    {#identifier .class .class key=value key=value}++Thus, for example, the following headings will all be assigned the identifier+`foo`:++    # My heading {#foo}++    ## My heading ##    {#foo}++    My other heading   {#foo}+    ---------------++(This syntax is compatible with [PHP Markdown Extra].)++Note that although this syntax allows assignment of classes and key/value+attributes, writers generally don't use all of this information.  Identifiers,+classes, and key/value attributes are used in HTML and HTML-based formats such+as EPUB and slidy.  Identifiers are used for labels and link anchors in the+LaTeX, ConTeXt, Textile, Jira markup, and AsciiDoc writers.++Headings with the class `unnumbered` will not be numbered, even if+`--number-sections` is specified.  A single hyphen (`-`) in an attribute+context is equivalent to `.unnumbered`, and preferable in non-English+documents.  So,++    # My heading {-}++is just the same as++    # My heading {.unnumbered}++If the `unlisted` class is present in addition to `unnumbered`,+the heading will not be included in a table of contents.+(Currently this feature is only implemented for certain+formats: those based on LaTeX and HTML, PowerPoint, and RTF.)++### Extension: `implicit_header_references` ###++Pandoc behaves as if reference links have been defined for each heading.+So, to link to a heading++    # Heading identifiers in HTML++you can simply write++    [Heading identifiers in HTML]++or++    [Heading identifiers in HTML][]++or++    [the section on heading identifiers][heading identifiers in+    HTML]++instead of giving the identifier explicitly:++    [Heading identifiers in HTML](#heading-identifiers-in-html)++If there are multiple headings with identical text, the corresponding+reference will link to the first one only, and you will need to use explicit+links to link to the others, as described above.++Like regular reference links, these references are case-insensitive.++Explicit link reference definitions always take priority over+implicit heading references.  So, in the following example, the+link will point to `bar`, not to `#foo`:++    # Foo++    [foo]: bar++    See [foo]++## Block quotations++Markdown uses email conventions for quoting blocks of text.+A block quotation is one or more paragraphs or other block elements+(such as lists or headings), with each line preceded by a `>` character+and an optional space. (The `>` need not start at the left margin, but+it should not be indented more than three spaces.)++    > This is a block quote. This+    > paragraph has two lines.+    >+    > 1. This is a list inside a block quote.+    > 2. Second item.++A "lazy" form, which requires the `>` character only on the first+line of each block, is also allowed:++    > This is a block quote. This+    paragraph has two lines.++    > 1. This is a list inside a block quote.+    2. Second item.++Among the block elements that can be contained in a block quote are+other block quotes. That is, block quotes can be nested:++    > This is a block quote.+    >+    > > A block quote within a block quote.++If the `>` character is followed by an optional space, that space+will be considered part of the block quote marker and not part of+the indentation of the contents.  Thus, to put an indented code+block in a block quote, you need five spaces after the `>`:++    >     code++### Extension: `blank_before_blockquote` ###++Original Markdown syntax does not require a blank line before a+block quote.  Pandoc does require this (except, of course, at+the beginning of the document). The reason for the requirement+is that it is all too easy for a `>` to end up at the beginning+of a line by accident (perhaps through line wrapping). So,+unless the `markdown_strict` format is used, the following does+not produce a nested block quote in pandoc:++    > This is a block quote.+    >> Not nested, since `blank_before_blockquote` is enabled by default+++## Verbatim (code) blocks++### Indented code blocks ###++A block of text indented four spaces (or one tab) is treated as verbatim+text: that is, special characters do not trigger special formatting,+and all spaces and line breaks are preserved.  For example,++        if (a > 3) {+          moveShip(5 * gravity, DOWN);+        }++The initial (four space or one tab) indentation is not considered part+of the verbatim text, and is removed in the output.++Note: blank lines in the verbatim text need not begin with four spaces.+++### Fenced code blocks ###++### Extension: `fenced_code_blocks` ###++In addition to standard indented code blocks, pandoc supports+*fenced* code blocks.  These begin with a row of three or more+tildes (`~`) and end with a row of tildes that must be at least as long as+the starting row. Everything between these lines is treated as code. No+indentation is necessary:++    ~~~~~~~+    if (a > 3) {+      moveShip(5 * gravity, DOWN);+    }+    ~~~~~~~++Like regular code blocks, fenced code blocks must be separated+from surrounding text by blank lines.++If the code itself contains a row of tildes or backticks, just use a longer+row of tildes or backticks at the start and end:++    ~~~~~~~~~~~~~~~~+    ~~~~~~~~~~+    code including tildes+    ~~~~~~~~~~+    ~~~~~~~~~~~~~~~~++### Extension: `backtick_code_blocks` ###++Same as `fenced_code_blocks`, but uses backticks (`` ` ``) instead of tildes+(`~`).++### Extension: `fenced_code_attributes` ###++Optionally, you may attach attributes to fenced or backtick code block using+this syntax:++    ~~~~ {#mycode .haskell .numberLines startFrom="100"}+    qsort []     = []+    qsort (x:xs) = qsort (filter (< x) xs) ++ [x] +++                   qsort (filter (>= x) xs)+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~++Here `mycode` is an identifier, `haskell` and `numberLines` are+classes, and `startFrom` is an attribute with value `100`. Some+output formats can use this information to do syntax+highlighting. Currently, the only output formats that use this+information are HTML, LaTeX, Docx, Ms, and PowerPoint. If+highlighting is supported for your output format and language,+then the code block above will appear highlighted, with numbered+lines. (To see which languages are supported, type `pandoc+--list-highlight-languages`.) Otherwise, the code block above+will appear as follows:++    <pre id="mycode" class="haskell numberLines" startFrom="100">+      <code>+      ...+      </code>+    </pre>++The `numberLines` (or `number-lines`) class will cause the lines+of the code block to be numbered, starting with `1` or the value+of the `startFrom` attribute.  The `lineAnchors` (or+`line-anchors`) class will cause the lines to be clickable+anchors in HTML output.++A shortcut form can also be used for specifying the language of+the code block:++    ```haskell+    qsort [] = []+    ```++This is equivalent to:++    ``` {.haskell}+    qsort [] = []+    ```++This shortcut form may be combined with attributes:++    ```haskell {.numberLines}+    qsort [] = []+    ```++Which is equivalent to:++    ``` {.haskell .numberLines}+    qsort [] = []+    ```++If the `fenced_code_attributes` extension is disabled, but+input contains class attribute(s) for the code block, the first+class attribute will be printed after the opening fence as a bare+word.++To prevent all highlighting, use the `--syntax-highlighting=none`+option. To set the highlighting style or method, use+`--syntax-highlighting`. For more information on highlighting, see+[Syntax highlighting], below.++## Line blocks++### Extension: `line_blocks` ###++A line block is a sequence of lines beginning with a vertical bar (`|`)+followed by a space.  The division into lines will be preserved in+the output, as will any leading spaces; otherwise, the lines will+be formatted as Markdown.  This is useful for verse and addresses:++    | The limerick packs laughs anatomical+    | In space that is quite economical.+    |    But the good ones I've seen+    |    So seldom are clean+    | And the clean ones so seldom are comical++    | 200 Main St.+    | Berkeley, CA 94718++The lines can be hard-wrapped if needed, but the continuation+line must begin with a space.++    | The Right Honorable Most Venerable and Righteous Samuel L.+      Constable, Jr.+    | 200 Main St.+    | Berkeley, CA 94718++Inline formatting (such as emphasis) is allowed in the content+(though it can't cross line boundaries). Block-level formatting+(such as block quotes or lists) is not recognized.++This syntax is borrowed from [reStructuredText].++## Lists++### Bullet lists ###++A bullet list is a list of bulleted list items.  A bulleted list+item begins with a bullet (`*`, `+`, or `-`).  Here is a simple+example:++    * one+    * two+    * three++This will produce a "compact" list. If you want a "loose" list, in which+each item is formatted as a paragraph, put spaces between the items:++    * one++    * two++    * three++The bullets need not be flush with the left margin; they may be+indented one, two, or three spaces. The bullet must be followed+by whitespace.++List items look best if subsequent lines are flush with the first+line (after the bullet):++    * here is my first+      list item.+    * and my second.++But Markdown also allows a "lazy" format:++    * here is my first+    list item.+    * and my second.++### Block content in list items ###++A list item may contain multiple paragraphs and other block-level+content. However, subsequent paragraphs must be preceded by a blank line+and indented to line up with the first non-space content after+the list marker.++      * First paragraph.++        Continued.++      * Second paragraph. With a code block, which must be indented+        eight spaces:++            { code }++Exception: if the list marker is followed by an indented code+block, which must begin 5 spaces after the list marker, then+subsequent paragraphs must begin two columns after the last+character of the list marker:++    *     code++      continuation paragraph++List items may include other lists.  In this case the preceding blank+line is optional.  The nested list must be indented to line up with+the first non-space character after the list marker of the+containing list item.++    * fruits+      + apples+        - macintosh+        - red delicious+      + pears+      + peaches+    * vegetables+      + broccoli+      + chard++As noted above, Markdown allows you to write list items "lazily," instead of+indenting continuation lines. However, if there are multiple paragraphs or+other blocks in a list item, the first line of each must be indented.++    + A lazy, lazy, list+    item.++    + Another one; this looks+    bad but is legal.++        Second paragraph of second+    list item.++### Ordered lists ###++Ordered lists work just like bulleted lists, except that the items+begin with enumerators rather than bullets.++In original Markdown, enumerators are decimal numbers followed+by a period and a space.  The numbers themselves are ignored, so+there is no difference between this list:++    1.  one+    2.  two+    3.  three++and this one:++    5.  one+    7.  two+    1.  three++### Extension: `fancy_lists` ###++Unlike original Markdown, pandoc allows ordered list items to be marked+with uppercase and lowercase letters and roman numerals, in addition to+Arabic numerals. List markers may be enclosed in parentheses or followed by a+single right-parenthesis or period. They must be separated from the+text that follows by at least one space, and, if the list marker is a+capital letter with a period, by at least two spaces.[^2]++[^2]:  The point of this rule is to ensure that normal paragraphs+    starting with people's initials, like++        B. Russell won a Nobel Prize (but not for "On Denoting").++    do not get treated as list items.++    This rule will not prevent++        (C) 2007 Joe Smith++    from being interpreted as a list item.  In this case, a backslash+    escape can be used:++        (C\) 2007 Joe Smith++The `fancy_lists` extension also allows '`#`' to be used as an+ordered list marker in place of a numeral:++    #. one+    #. two++Note:  the '`#`' ordered list marker doesn't work with `commonmark`.++### Extension: `startnum` ###++Pandoc also pays attention to the type of list marker used, and to the+starting number, and both of these are preserved where possible in the+output format. Thus, the following yields a list with numbers followed+by a single parenthesis, starting with 9, and a sublist with lowercase+roman numerals:++     9)  Ninth+    10)  Tenth+    11)  Eleventh+           i. subone+          ii. subtwo+         iii. subthree++Pandoc will start a new list each time a different type of list+marker is used.  So, the following will create three lists:++    (2) Two+    (5) Three+    1.  Four+    *   Five++If default list markers are desired, use `#.`:++    #.  one+    #.  two+    #.  three++### Extension: `task_lists` ###++Pandoc supports task lists, using the syntax of GitHub-Flavored Markdown.++    - [ ] an unchecked task list item+    - [x] checked item++### Definition lists ###++### Extension: `definition_lists` ###++Pandoc supports definition lists, using the syntax of+[PHP Markdown Extra] with some extensions.[^3]++    Term 1++    :   Definition 1++    Term 2 with *inline markup*++    :   Definition 2++            { some code, part of Definition 2 }++        Third paragraph of definition 2.++Each term must fit on one line, which may optionally be followed by+a blank line, and must be followed by one or more definitions.+A definition begins with a colon or tilde, which may be indented one+or two spaces.++A term may have multiple definitions, and each definition may+consist of one or more indented block elements (paragraph, code block,+list, etc.). The blocks in the definition shoud be indented to the column+of the first non-space content after the `:` or `~` marker, or+(if the `four_space_rule` extension is enabled) four spaces or+one tab stop. As with other Markdown lists, you can "lazily" omit+indentation in paragraph continuation lines:++    Term 1++    : Definition+    with lazy continuation.++      Second paragraph of the definition.++If you leave space before the definition (as in the example above),+the text of the definition will be treated as a paragraph.  In some+output formats, this will mean greater spacing between term/definition+pairs. For a more compact definition list, omit the space before the+definition:++    Term 1+      ~ Definition 1++    Term 2+      ~ Definition 2a+      ~ Definition 2b++Note that space between items in a definition list is required.++[^3]:  I have been influenced by the suggestions of [David+  Wheeler](https://justatheory.com/2009/02/modest-markdown-proposal/).++### Numbered example lists ###++### Extension: `example_lists` ###++The special list marker `@` can be used for sequentially numbered+examples. The first list item with a `@` marker will be numbered '1',+the next '2', and so on, throughout the document. The numbered examples+need not occur in a single list; each new list using `@` will take up+where the last stopped. So, for example:++    (@)  My first example will be numbered (1).+    (@)  My second example will be numbered (2).++    Explanation of examples.++    (@)  My third example will be numbered (3).++Numbered examples can be labeled and referred to elsewhere in the+document:++    (@good)  This is a good example.++    As (@good) illustrates, ...++The label can be any string of alphanumeric characters, underscores,+or hyphens.++Continuation paragraphs in example lists must always+be indented four spaces, regardless of the length of the+list marker.  That is, example lists always behave as if the+`four_space_rule` extension is set.  This is because example+labels tend to be long, and indenting content to the+first non-space character after the label would be awkward.++You can repeat an earlier numbered example by re-using its label:++    (@foo) Sample sentence.++    Intervening text...++    This theory can explain the case we saw earlier (repeated):++    (@foo) Sample sentence.++This only works reliably, though, if the repeated item is in a list+by itself, because each numbered example list will be numbered+continuously from its starting number.++### Ending a list ###++What if you want to put an indented code block after a list?++    -   item one+    -   item two++        { my code block }++Trouble! Here pandoc (like other Markdown implementations) will treat+`{ my code block }` as the second paragraph of item two, and not as+a code block.++To "cut off" the list after item two, you can insert some non-indented+content, like an HTML comment, which won't produce visible output in+any format:++    -   item one+    -   item two++    <!-- end of list -->++        { my code block }++You can use the same trick if you want two consecutive lists instead+of one big list:++    1.  one+    2.  two+    3.  three++    <!-- -->++    1.  uno+    2.  dos+    3.  tres++## Horizontal rules++A line containing a row of three or more `*`, `-`, or `_` characters+(optionally separated by spaces) produces a horizontal rule:++    *  *  *  *++    ---------------++We strongly recommend that horizontal rules be separated from+surrounding text by blank lines.  If a horizontal rule is not+followed by a blank line, pandoc may try to interpret the+lines that follow as a YAML metadata block or a table.++## Tables++Four kinds of tables may be used. The first three kinds presuppose the use of+a fixed-width font, such as Courier. The fourth kind can be used with+proportionally spaced fonts, as it does not require lining up columns.++### Extension: `table_captions` ###++A caption may optionally be provided with all 4 kinds of tables (as+illustrated in the examples below). A caption is a paragraph beginning+with the string `Table:` (or `table:` or just `:`), which will be stripped+off. It may appear either before or after the table.++### Extension: `simple_tables` ###++Simple tables look like this:++      Right     Left     Center     Default+    -------     ------ ----------   -------+         12     12        12            12+        123     123       123          123+          1     1          1             1++    Table:  Demonstration of simple table syntax.++The header and table rows must each fit on one line.  Column+alignments are determined by the position of the header text relative+to the dashed line below it:[^4]++  - If the dashed line is flush with the header text on the right side+    but extends beyond it on the left, the column is right-aligned.+  - If the dashed line is flush with the header text on the left side+    but extends beyond it on the right, the column is left-aligned.+  - If the dashed line extends beyond the header text on both sides,+    the column is centered.+  - If the dashed line is flush with the header text on both sides,+    the default alignment is used (in most cases, this will be left).++[^4]:  This scheme is due to Michel Fortin, who proposed it on the+       [Markdown discussion list](http://six.pairlist.net/pipermail/markdown-discuss/2005-March/001097.html).++The table must end with a blank line, or a line of dashes followed by+a blank line.++The column header row may be omitted, provided a dashed line is used+to end the table. For example:++    -------     ------ ----------   -------+         12     12        12             12+        123     123       123           123+          1     1          1              1+    -------     ------ ----------   -------++When the header row is omitted, column alignments are determined on the basis+of the first line of the table body. So, in the tables above, the columns+would be right, left, center, and right aligned, respectively.++### Extension: `multiline_tables` ###++Multiline tables allow header and table rows to span multiple lines+of text (but cells that span multiple columns or rows of the table are+not supported).  Here is an example:++    -------------------------------------------------------------+     Centered   Default           Right Left+      Header    Aligned         Aligned Aligned+    ----------- ------- --------------- -------------------------+       First    row                12.0 Example of a row that+                                        spans multiple lines.++      Second    row                 5.0 Here's another one. Note+                                        the blank line between+                                        rows.+    -------------------------------------------------------------++    Table: Here's the caption. It, too, may span+    multiple lines.++These work like simple tables, but with the following differences:++  - They must begin with a row of dashes, before the header text+    (unless the header row is omitted).+  - They must end with a row of dashes, then a blank line.+  - The rows must be separated by blank lines.++In multiline tables, the table parser pays attention to the widths of+the columns, and the writers try to reproduce these relative widths in+the output. So, if you find that one of the columns is too narrow in the+output, try widening it in the Markdown source.++The header may be omitted in multiline tables as well as simple tables:++    ----------- ------- --------------- -------------------------+       First    row                12.0 Example of a row that+                                        spans multiple lines.++      Second    row                 5.0 Here's another one. Note+                                        the blank line between+                                        rows.+    ----------- ------- --------------- -------------------------++    : Here's a multiline table without a header.++It is possible for a multiline table to have just one row, but the row+should be followed by a blank line (and then the row of dashes that ends+the table), or the table may be interpreted as a simple table.++### Extension: `grid_tables` ###++Grid tables look like this:++    : Sample grid table.++    +---------------+---------------+--------------------++    | Fruit         | Price         | Advantages         |+    +===============+===============+====================++    | Bananas       | $1.34         | - built-in wrapper |+    |               |               | - bright color     |+    +---------------+---------------+--------------------++    | Oranges       | $2.10         | - cures scurvy     |+    |               |               | - tasty            |+    +---------------+---------------+--------------------+++The row of `=`s separates the header from the table body,+and can be omitted for a headerless table. The cells of grid+tables may contain arbitrary block elements (multiple+paragraphs, code blocks, lists, etc.).++Cells can span multiple columns or rows:++    +---------------------+----------++    | Property            | Earth    |+    +=============+=======+==========++    |             | min   | -89.2 °C |+    | Temperature +-------+----------++    | 1961-1990   | mean  | 14 °C    |+    |             +-------+----------++    |             | max   | 56.7 °C  |+    +-------------+-------+----------+++A table header may contain more than one row:++    +---------------------+-----------------------++    | Location            | Temperature 1961-1990 |+    |                     | in degree Celsius     |+    |                     +-------+-------+-------++    |                     | min   | mean  | max   |+    +=====================+=======+=======+=======++    | Antarctica          | -89.2 | N/A   | 19.8  |+    +---------------------+-------+-------+-------++    | Earth               | -89.2 | 14    | 56.7  |+    +---------------------+-------+-------+-------+++Alignments can be specified as with pipe tables, by putting+colons at the boundaries of the separator line after the+header:++    +---------------+---------------+--------------------++    | Right         | Left          | Centered           |+    +==============:+:==============+:==================:++    | Bananas       | $1.34         | built-in wrapper   |+    +---------------+---------------+--------------------+++For headerless tables, the colons go on the top line instead:++    +--------------:+:--------------+:------------------:++    | Right         | Left          | Centered           |+    +---------------+---------------+--------------------+++A table foot can be defined by enclosing it with separator lines+that use `=` instead of `-`:++     +---------------+---------------++     | Fruit         | Price         |+     +===============+===============++     | Bananas       | $1.34         |+     +---------------+---------------++     | Oranges       | $2.10         |+     +===============+===============++     | Sum           | $3.44         |+     +===============+===============+++The foot must always be placed at the very bottom of the table.++Grid tables can be created easily using Emacs' table-mode+(`M-x table-insert`).++### Extension: `pipe_tables` ###++Pipe tables look like this:++    | Right | Left | Default | Center |+    |------:|:-----|---------|:------:|+    |   12  |  12  |    12   |    12  |+    |  123  |  123 |   123   |   123  |+    |    1  |    1 |     1   |     1  |++      : Demonstration of pipe table syntax.++The syntax is identical to [PHP Markdown Extra tables].  The beginning and+ending pipe characters are optional, but pipes are required between all+columns.  The colons indicate column alignment as shown.  The header+cannot be omitted.  To simulate a headerless table, include a header+with blank cells.++Since the pipes indicate column boundaries, columns need not be vertically+aligned, as they are in the above example.  So, this is a perfectly+legal (though ugly) pipe table:++    fruit| price+    -----|-----:+    apple|2.05+    pear|1.37+    orange|3.09++The cells of pipe tables cannot contain block elements like paragraphs+and lists, and cannot span multiple lines.  If any line of the+Markdown source is longer than the column width (see `--columns`),+then the table will take up the full text width and the cell+contents will wrap, with the relative cell widths determined by+the number of dashes in the line separating the table header+from the table body. (For example `---|-` would make the first column 3/4+and the second column 1/4 of the full text width.)+On the other hand, if no lines are wider than column width, then+cell contents will not be wrapped, and the cells will be sized+to their contents.++Note:  pandoc also recognizes pipe tables of the following+form, as can be produced by Emacs' orgtbl-mode:++    | One | Two   |+    |-----+-------|+    | my  | table |+    | is  | nice  |++The difference is that `+` is used instead of `|`. Other orgtbl features+are not supported. In particular, to get non-default column alignment,+you'll need to add colons as above.++[PHP Markdown Extra tables]: https://michelf.ca/projects/php-markdown/extra/#table++### Extension: `table_attributes` ###++Attributes may be attached to tables by including them at the end+of the caption. (For the syntax, see+[`header_attributes`][Extension: `header_attributes`].)++      : Here's the caption. {#ident .class key="value"}++## Metadata blocks++### Extension: `pandoc_title_block` ###++If the file begins with a title block++    % title+    % author(s) (separated by semicolons)+    % date++it will be parsed as bibliographic information, not regular text.  (It+will be used, for example, in the title of standalone LaTeX or HTML+output.)  The block may contain just a title, a date and an author,+or all three elements. If you want to include an author but no+title, or a title and a date but no author, you need a blank line:++```+%+% Author+```++```+% My title+%+% June 15, 2006+```++The title may occupy multiple lines, but continuation lines must+begin with leading space, thus:++```+% My title+  on multiple lines+```++If a document has multiple authors, the authors may be put on+separate lines with leading space, or separated by semicolons, or+both.  So, all of the following are equivalent:++```+% Author One+  Author Two+```++```+% Author One; Author Two+```++```+% Author One;+  Author Two+```++The date must fit on one line.++All three metadata fields may contain standard inline formatting+(italics, links, footnotes, etc.).++Title blocks will always be parsed, but they will affect the output only+when the `--standalone` (`-s`) option is chosen. In HTML output, titles+will appear twice: once in the document head---this is the title that+will appear at the top of the window in a browser---and once at the+beginning of the document body. The title in the document head can have+an optional prefix attached (`--title-prefix` or `-T` option). The title+in the body appears as an H1 element with class "title", so it can be+suppressed or reformatted with CSS. If a title prefix is specified with+`-T` and no title block appears in the document, the title prefix will+be used by itself as the HTML title.++The man page writer extracts a title, man page section number, and+other header and footer information from the title line. The title+is assumed to be the first word on the title line, which may optionally+end with a (single-digit) section number in parentheses. (There should+be no space between the title and the parentheses.)  Anything after+this is assumed to be additional footer and header text. A single pipe+character (`|`) should be used to separate the footer text from the header+text.  Thus,++    % PANDOC(1)++will yield a man page with the title `PANDOC` and section 1.++    % PANDOC(1) Pandoc User Manuals++will also have "Pandoc User Manuals" in the footer.++    % PANDOC(1) Pandoc User Manuals | Version 4.0++will also have "Version 4.0" in the header.++### Extension: `yaml_metadata_block` ###++A [YAML] metadata block is a valid YAML object, delimited by a line of three+hyphens (`---`) at the top and a line of three hyphens (`---`) or three dots+(`...`) 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+separate YAML file and pass it to pandoc as an argument, along+with your Markdown files:++    pandoc chap1.md chap2.md chap3.md metadata.yaml -s -o book.html++Just be sure that the YAML file begins with `---` and ends with `---` or+`...`. Alternatively, you can use the `--metadata-file` option. Using+that approach however, you cannot reference content (like footnotes)+from the main Markdown input document.++Metadata will be taken from the fields of the YAML object and added to any+existing document metadata.  Metadata can contain lists and objects (nested+arbitrarily), but all string scalars will be interpreted as Markdown.  Fields+with names ending in an underscore will be ignored by pandoc.  (They may be+given a role by external processors.)  Field names must not be+interpretable as YAML numbers or boolean values (so, for+example, `yes`, `True`, and `15` cannot be used as field names).++A document may contain multiple metadata blocks.  If two+metadata blocks attempt to set the same field, the value from+the second block will be taken.++Each metadata block is handled internally as an independent YAML document.+This means, for example, that any YAML anchors defined in a block cannot be+referenced in another block.++When pandoc is used with `-t markdown` to create a Markdown document,+a YAML metadata block will be produced only if the `-s/--standalone`+option is used.  All of the metadata will appear in a single block+at the beginning of the document.++Note that [YAML] escaping rules must be followed. Thus, for example,+if a title contains a colon, it must be quoted, and if it contains a+backslash escape, then it must be ensured that it is not treated as a+[YAML escape sequence]. The pipe character (`|`) can be used to begin+an indented block that will be interpreted literally, without need for+escaping. This form is necessary when the field contains blank lines+or block-level formatting:++    ---+    title:  'This is the title: it contains a colon'+    author:+    - Author One+    - Author Two+    keywords: [nothing, nothingness]+    abstract: |+      This is the abstract.++      It consists of two paragraphs.+    ...++The literal block after the `|` must be indented relative to the+line containing the `|`.  If it is not, the YAML will be invalid+and pandoc will not interpret it as metadata.  For an overview+of the complex rules governing YAML, see the [Wikipedia entry on+YAML syntax].++Template variables will be set automatically from the metadata.  Thus, for+example, in writing HTML, the variable `abstract` will be set to the HTML+equivalent of the Markdown in the `abstract` field:++    <p>This is the abstract.</p>+    <p>It consists of two paragraphs.</p>++Variables can contain arbitrary YAML structures, but the template must match+this structure.  The `author` variable in the default templates expects a+simple list or string, but can be changed to support more complicated+structures.  The following combination, for example, would add an affiliation+to the author if one is given:++    ---+    title: The document title+    author:+    - name: Author One+      affiliation: University of Somewhere+    - name: Author Two+      affiliation: University of Nowhere+    ...++To use the structured authors in the example above, you would need a custom+template:++    $for(author)$+    $if(author.name)$+    $author.name$$if(author.affiliation)$ ($author.affiliation$)$endif$+    $else$+    $author$+    $endif$+    $endfor$++Raw content to include in the document's header may be specified+using `header-includes`; however, it is important to mark up+this content as raw code for a particular output format, using+the [`raw_attribute` extension](#extension-raw_attribute), or it+will be interpreted as Markdown. For example:++    header-includes:+    - |+      ```{=latex}+      \let\oldsection\section+      \renewcommand{\section}[1]{\clearpage\oldsection{#1}}+      ```++Note:  the `yaml_metadata_block` extension works not just with+`markdown` but with `commonmark` (and it is enabled by default in+`gfm` and `commonmark_x`). However, in `commonmark`, `gfm`,+and `commonmark_x`, the following restrictions apply:++- The YAML metadata block must occur at the beginning of the+  document (and there can be only one).  If multiple files are+  given as arguments to pandoc, only the first can be a YAML+  metadata block.++- The leaf nodes of the YAML structure are parsed in isolation from+  each other and from the rest of the document.  So, for+  example,  you can't use a reference link in these contexts+  if the link definition is somewhere else in the document.++[YAML escape sequence]: https://yaml.org/spec/1.2/spec.html#id2776092+[Wikipedia entry on YAML syntax]:  https://en.wikipedia.org/wiki/YAML#Syntax++## Backslash escapes++### Extension: `all_symbols_escapable` ###++Except inside a code block or inline code, any punctuation or space+character preceded by a backslash will be treated literally, even if it+would normally indicate formatting.  Thus, for example, if one writes++    *\*hello\**++one will get++    <em>*hello*</em>++instead of++    <strong>hello</strong>++This rule is easier to remember than original Markdown's rule,+which allows only the following characters to be backslash-escaped:++    \`*_{}[]()>#+-.!++(However, if the `markdown_strict` format is used, the original Markdown rule+will be used.)++A backslash-escaped space is parsed as a nonbreaking space. In TeX output,+it will appear as `~`. In HTML and XML output, it will appear as a+literal unicode nonbreaking space character (note that it will thus+actually look "invisible" in the generated HTML source; you can still+use the `--ascii` command-line option to make it appear as an explicit+entity).++A backslash-escaped newline (i.e. a backslash occurring at the end of+a line) is parsed as a hard line break.  It will appear in TeX output as+`\\` and in HTML as `<br />`.  This is a nice alternative to+Markdown's "invisible" way of indicating hard line breaks using+two trailing spaces on a line.++Backslash escapes do not work in verbatim contexts.++## Inline formatting++### Emphasis ###++To *emphasize* some text, surround it with `*`s or `_`, like this:++    This text is _emphasized with underscores_, and this+    is *emphasized with asterisks*.++Double `*` or `_` produces **strong emphasis**:++    This is **strong emphasis** and __with underscores__.++A `*` or `_` character surrounded by spaces, or backslash-escaped,+will not trigger emphasis:++    This is * not emphasized *, and \*neither is this\*.++### Extension: `intraword_underscores` ###++Because `_` is sometimes used inside words and identifiers,+pandoc does not interpret a `_` surrounded by alphanumeric+characters as an emphasis marker.  If you want to emphasize+just part of a word, use `*`:++    feas*ible*, not feas*able*.++### Strikeout ###++### Extension: `strikeout` ###++To strike out a section of text with a horizontal line, begin and end it+with `~~`. Thus, for example,++    This ~~is deleted text.~~+++### Superscripts and subscripts ###++### Extension: `superscript`, `subscript` ###++Superscripts may be written by surrounding the superscripted text by `^`+characters; subscripts may be written by surrounding the subscripted+text by `~` characters.  Thus, for example,++    H~2~O is a liquid.  2^10^ is 1024.++The text between `^...^` or `~...~` may not contain spaces or+newlines.  If the superscripted or subscripted text contains+spaces, these spaces must be escaped with backslashes.  (This is+to prevent accidental superscripting and subscripting through+the ordinary use of `~` and `^`, and also bad interactions with+footnotes.) Thus, if you want the letter P with 'a cat' in+subscripts, use `P~a\ cat~`, not `P~a cat~`.++### Verbatim ###++To make a short span of text verbatim, put it inside backticks:++    What is the difference between `>>=` and `>>`?++If the verbatim text includes a backtick, use double backticks:++    Here is a literal backtick `` ` ``.++(The spaces after the opening backticks and before the closing+backticks will be ignored.)++The general rule is that a verbatim span starts with a string+of consecutive backticks (optionally followed by a space)+and ends with a string of the same number of backticks (optionally+preceded by a space).++Note that backslash-escapes (and other Markdown constructs) do not+work in verbatim contexts:++    This is a backslash followed by an asterisk: `\*`.++### Extension: `inline_code_attributes` ###++Attributes can be attached to verbatim text, just as with+[fenced code blocks]:++    `<$>`{.haskell}++### Underline ###++To underline text, use the `underline` class:++    [Underline]{.underline}++Or, without the `bracketed_spans` extension (but with `native_spans`):++    <span class="underline">Underline</span>++This will work in all output formats that support underline.++### Small caps ###++To write small caps, use the `smallcaps` class:++    [Small caps]{.smallcaps}++Or, without the `bracketed_spans` extension:++    <span class="smallcaps">Small caps</span>++For compatibility with other Markdown flavors, CSS is also supported:++    <span style="font-variant:small-caps;">Small caps</span>++This will work in all output formats that support small caps.++### Highlighting ###++To highlight text, use the `mark` class:++    [Mark]{.mark}++Or, without the `bracketed_spans` extension (but with `native_spans`):++    <span class="mark">Mark</span>++This will work in all output formats that support highlighting.+++## Math++### Extension: `tex_math_dollars` ###++Anything between two `$` characters will be treated as TeX math.  The+opening `$` must have a non-space character immediately to its right,+while the closing `$` must have a non-space character immediately to its+left, and must not be followed immediately by a digit.  Thus,+`$20,000 and $30,000` won't parse as math.  If for some reason+you need to enclose text in literal `$` characters, backslash-escape+them and they won't be treated as math delimiters.++For display math, use `$$` delimiters.  (In this case, the delimiters+may be separated from the formula by whitespace.  However, there can be+no blank lines between the opening and closing `$$` delimiters.)++TeX math will be printed in all output formats. How it is rendered+depends on the output format:++LaTeX+  ~ It will appear verbatim surrounded by `\(...\)` (for inline+    math) or `\[...\]` (for display math).++Markdown, Emacs Org mode, ConTeXt, ZimWiki+  ~ It will appear verbatim surrounded by `$...$` (for inline+    math) or `$$...$$` (for display math).++XWiki+  ~ It will appear verbatim surrounded by `{{formula}}..{{/formula}}`.++reStructuredText+  ~ It will be rendered using an [interpreted text role `:math:`].++AsciiDoc+  ~ For AsciiDoc output math will appear verbatim surrounded by+    `latexmath:[...]`. For `asciidoc_legacy` the bracketed+    material will also include inline or display math delimiters.++Texinfo+  ~ It will be rendered inside a `@math` command.++roff man, Jira markup+  ~ It will be rendered verbatim without `$`'s.++MediaWiki, DokuWiki+  ~ It will be rendered inside `<math>` tags.++Textile+  ~ It will be rendered inside `<span class="math">` tags.++RTF, OpenDocument+  ~ It will be rendered, if possible, using Unicode characters,+    and will otherwise appear verbatim.++ODT+  ~ It will be rendered, if possible, using MathML.++DocBook+  ~ If the `--mathml` flag is used, it will be rendered using MathML+    in an `inlineequation` or `informalequation` tag.  Otherwise it+    will be rendered, if possible, using Unicode characters.++Docx and PowerPoint+  ~ It will be rendered using OMML math markup.++FictionBook2+  ~ If the `--webtex` option is used, formulas are rendered as images+    using CodeCogs or other compatible web service, downloaded+    and embedded in the e-book. Otherwise, they will appear verbatim.++HTML, Slidy, DZSlides, S5, EPUB+  ~ The way math is rendered in HTML will depend on the+    command-line options selected. Therefore see [Math rendering in HTML]+    above.++[interpreted text role `:math:`]: https://docutils.sourceforge.io/docs/ref/rst/roles.html#math++## Raw HTML++### Extension: `raw_html` ###++Markdown allows you to insert raw HTML (or DocBook) anywhere in a document+(except verbatim contexts, where `<`, `>`, and `&` are interpreted+literally).  (Technically this is not an extension, since standard+Markdown allows it, but it has been made an extension so that it can+be disabled if desired.)++The raw HTML is passed through unchanged in HTML, S5, Slidy, Slideous,+DZSlides, EPUB, Markdown, CommonMark, Emacs Org mode, and Textile+output, and suppressed in other formats.++For a more explicit way of including raw HTML in a Markdown+document, see the [`raw_attribute` extension][Extension: `raw_attribute`].++In the CommonMark format, if `raw_html` is enabled, superscripts,+subscripts, strikeouts and small capitals will be represented as HTML.+Otherwise, plain-text fallbacks will be used. Note that even if+`raw_html` is disabled, tables will be rendered with HTML syntax if+they cannot use pipe syntax.++### Extension: `markdown_in_html_blocks` ###++Original Markdown allows you to include HTML "blocks":  blocks+of HTML between balanced tags that are separated from the surrounding text+with blank lines, and start and end at the left margin.  Within+these blocks, everything is interpreted as HTML, not Markdown;+so (for example), `*` does not signify emphasis.++Pandoc behaves this way when the `markdown_strict` format is used; but+by default, pandoc interprets material between HTML block tags as Markdown.+Thus, for example, pandoc will turn++    <table>+    <tr>+    <td>*one*</td>+    <td>[a link](https://google.com)</td>+    </tr>+    </table>++into++    <table>+    <tr>+    <td><em>one</em></td>+    <td><a href="https://google.com">a link</a></td>+    </tr>+    </table>++whereas `Markdown.pl` will preserve it as is.++There is one exception to this rule:  text between `<script>`,+`<style>`, `<pre>`, and `<textarea>` tags is not interpreted as Markdown.++This departure from original Markdown should make it easier to mix+Markdown with HTML block elements.  For example, one can surround+a block of Markdown text with `<div>` tags without preventing it+from being interpreted as Markdown.++### Extension: `native_divs` ###++Use native pandoc `Div` blocks for content inside `<div>` tags.+For the most part this should give the same output as+`markdown_in_html_blocks`, but it makes it easier to write pandoc+filters to manipulate groups of blocks.++### Extension: `native_spans` ###++Use native pandoc `Span` blocks for content inside `<span>` tags.+For the most part this should give the same output as `raw_html`,+but it makes it easier to write pandoc filters to manipulate groups+of inlines.++### Extension: `raw_tex` ###++In addition to raw HTML, pandoc allows raw LaTeX, TeX, and ConTeXt to be+included in a document. Inline TeX commands will be preserved and passed+unchanged to the LaTeX and ConTeXt writers. Thus, for example, you can use+LaTeX to include BibTeX citations:++    This result was proved in \cite{jones.1967}.++Note that in LaTeX environments, like++    \begin{tabular}{|l|l|}\hline+    Age & Frequency \\ \hline+    18--25  & 15 \\+    26--35  & 33 \\+    36--45  & 22 \\ \hline+    \end{tabular}++the material between the begin and end tags will be interpreted as raw+LaTeX, not as Markdown.++For a more explicit and flexible way of including raw TeX in a+Markdown document, see the [`raw_attribute`+extension][Extension: `raw_attribute`].++Inline LaTeX is ignored in output formats other than Markdown, LaTeX,+Emacs Org mode, and ConTeXt.++### Generic raw attribute ###++### Extension: `raw_attribute` ###++Inline spans and fenced code blocks with a special+kind of attribute will be parsed as raw content with the+designated format.  For example, the following produces a raw+roff `ms` block:++    ```{=ms}+    .MYMACRO+    blah blah+    ```+And the following produces a raw `html` inline element:++    This is `<a>html</a>`{=html}++This can be useful to insert raw xml into `docx` documents, e.g.+a pagebreak:++    ```{=openxml}+    <w:p>+      <w:r>+        <w:br w:type="page"/>+      </w:r>+    </w:p>+    ```++The format name should match the target format name (see+`-t/--to`, above, for a list, or use `pandoc+--list-output-formats`). Use `openxml` for `docx` output,+`opendocument` for `odt` output, `html5` for `epub3` output,+`html4` for `epub2` output, and `latex`, `beamer`,+`ms`, or `html5` for `pdf` output (depending on what you+use for `--pdf-engine`).++This extension presupposes that the relevant kind of+inline code or fenced code block is enabled.  Thus, for+example, to use a raw attribute with a backtick code block,+`backtick_code_blocks` must be enabled.++The raw attribute cannot be combined with regular attributes.++## LaTeX macros++### Extension: `latex_macros` ###++When this extension is enabled, pandoc will parse LaTeX+macro definitions and apply the resulting macros to all LaTeX+math and raw LaTeX.  So, for example, the following will work in+all output formats, not just LaTeX:++    \newcommand{\tuple}[1]{\langle #1 \rangle}++    $\tuple{a, b, c}$++Note that LaTeX macros will not be applied if they occur+inside a raw span or block marked with the+[`raw_attribute` extension](#extension-raw_attribute).++When `latex_macros` is disabled, the raw LaTeX and math will+not have macros applied. This is usually a better approach when+you are targeting LaTeX or PDF.++Macro definitions in LaTeX will be passed through as raw LaTeX+only if `latex_macros` is not enabled.  Macro definitions in+Markdown source (or other formats allowing `raw_tex`) will+be passed through regardless of whether `latex_macros` is+enabled.++## Links++Markdown allows links to be specified in several ways.++### Automatic links ###++If you enclose a URL or email address in pointy brackets, it+will become a link:++    <https://google.com>+    <sam@green.eggs.ham>++### Inline links ###++An inline link consists of the link text in square brackets,+followed by the URL in parentheses. (Optionally, the URL can+be followed by a link title, in quotes.)++    This is an [inline link](/url), and here's [one with+    a title](https://fsf.org "click here for a good time!").++There can be no space between the bracketed part and the parenthesized part.+The link text can contain formatting (such as emphasis), but the title cannot.++Email addresses in inline links are not autodetected, so they have to be+prefixed with `mailto`:++    [Write me!](mailto:sam@green.eggs.ham)++### Reference links ###++An *explicit* reference link has two parts, the link itself and the link+definition, which may occur elsewhere in the document (either+before or after the link).++The link consists of link text in square brackets, followed by a label in+square brackets. (There cannot be space between the two unless the+`spaced_reference_links` extension is enabled.) If the label is empty+(`[]`), then it will be implicitly be taken to be the same as the link text;+thus `[foo][]` is equivalent to `[foo][foo]`. (If the+`shortcut_reference_links` extension is enabled, the empty `[]`+may be omitted.)++The link definition consists of the bracketed label, followed by+a colon and a space, followed by the URL, and optionally (after a+space) a link title either in quotes or in parentheses. The label+must not be parseable as a citation (assuming the `citations`+extension is enabled): citations take precedence over link+labels.++Here are some examples of reference links and link definitions;++    See [the website *I* built][my website].++    See [my website][] and [the bar page][1] and+    the [home page of the FSF][fsf].++    [my website]: http://foo.bar.baz+    [1]: /foo/bar.html  "My title, optional"+    [fsf]: https://fsf.org (The Free Software Foundation)+    [special page]: /bar#special  'A title in single quotes'++The URL in a link definition may optionally be surrounded by+angle brackets:++    [my label 5]: <http://foo.bar.baz>++The title may go on the next line:++    [my label 3]: https://fsf.org+      "The Free Software Foundation"++Note that link labels are not case sensitive.  So, this will work:++    Here is [my link][FOO]++    [Foo]: /bar/baz++The link definition may come either before or after a+reference link that uses the label.++Note: In some Markdown implementations, reference link+definitions cannot occur in nested constructions such as list+items or block quotes. Pandoc lifts this arbitrary-seeming+restriction. So the following is fine in pandoc, though not in+all implementations:++    > My block [quote].+    >+    > [quote]: /foo++### Extension: `shortcut_reference_links` ###++In a *shortcut* reference link, the second pair of brackets may+be omitted entirely:++    See [my website].++    [my website]: http://foo.bar.baz++### Internal links ###++To link to another section of the same document, use the automatically+generated identifier (see [Heading identifiers]). For example:++    See the [Introduction](#introduction).++or++    See the [Introduction].++    [Introduction]: #introduction++Internal links are currently supported for HTML formats (including+HTML slide shows and EPUB), LaTeX, and ConTeXt.++## Images++A link immediately preceded by a `!` will be treated as an image.+The link text will be used as the image's alt text:++    ![la lune](lalune.jpg "Voyage to the moon")++    ![movie reel]++    [movie reel]: movie.gif++### Extension: `implicit_figures` ###++An image with nonempty alt text, occurring by itself in a+paragraph, will be rendered as a figure with a caption.  The+image's description will be used as the caption.++    ![This is the caption.](image.png)++How this is rendered depends on the output format. Some output+formats (e.g. RTF) do not yet support figures. In those+formats, you'll just get an image in a paragraph by itself, with+no caption.++If you just want a regular inline image, just make sure it is not+the only thing in the paragraph. One way to do this is to insert a+nonbreaking space after the image:++    ![This image won't be a figure](image.png)\++Note that in reveal.js slide shows, an image in a paragraph+by itself that has the `r-stretch` class will fill the screen,+and the caption and figure tags will be omitted.++To specify an alt text for the image that is different+from the caption, you can use an explicit attribute (assuming the+`link_attributes` extension is set):++    ![The caption.](image.png){alt="description of image"}++For LaTeX output, you can specify a [figure's+positioning](https://www.overleaf.com/learn/latex/Positioning_images_and_tables#The_figure_environment)+by adding the `latex-placement` attribute.++    ![The caption.](image.png){latex-placement="ht"}++### Extension: `link_attributes` ###++Attributes can be set on links and images:++    An inline ![image](foo.jpg){#id .class width=30 height=20px}+    and a reference ![image][ref] with attributes.++    [ref]: foo.jpg "optional title" {#id .class key=val key2="val 2"}++(This syntax is compatible with [PHP Markdown Extra] when only `#id`+and `.class` are used.)++For HTML and EPUB, all known HTML5 attributes except `width` and+`height` (but including `srcset` and `sizes`) are passed through+as is. Unknown attributes are passed through as custom+attributes, with `data-` prepended. The other writers ignore+attributes that are not specifically supported by their output format.++The `width` and `height` attributes on images are treated specially. When+used without a unit, the unit is assumed to be pixels. However, any of+the following unit identifiers can be used: `px`, `cm`, `mm`, `in`, `inch`+and `%`. There must not be any spaces between the number and the unit.+For example:++```+![](file.jpg){ width=50% }+```++- Dimensions may be converted to a form that is compatible with+  the output format (for example, dimensions given in pixels will+  be converted to inches when converting HTML to LaTeX). Conversion+  between pixels and physical measurements is affected by the+  `--dpi` option (by default, 96 dpi is assumed, unless the image+  itself contains dpi information).+- The `%` unit is generally relative to some available space.+  For example the above example will render to the following.+  - HTML: `<img href="file.jpg" style="width: 50%;" />`+  - LaTeX: `\includegraphics[width=0.5\textwidth,height=\textheight]{file.jpg}`+    (If you're using a custom template, you need to configure `graphicx`+    as in the default template.)+  - ConTeXt: `\externalfigure[file.jpg][width=0.5\textwidth]`+- Some output formats have a notion of a class+  ([ConTeXt](https://wiki.contextgarden.net/Using_Graphics#Multiple_Image_Settings))+  or a unique identifier (LaTeX `\caption`), or both (HTML).+- When no `width` or `height` attributes are specified, the fallback+  is to look at the image resolution and the dpi metadata embedded in+  the image file.++## Divs and Spans++Using the `native_divs` and `native_spans` extensions+(see [above][Extension: `native_divs`]), HTML syntax can+be used as part of Markdown to create native `Div` and `Span`+elements in the pandoc AST (as opposed to raw HTML).+However, there is also nicer syntax available:++### Extension: `fenced_divs` ###++Allow special fenced syntax for native `Div` blocks.  A Div+starts with a fence containing at least three consecutive+colons plus some attributes. The attributes may optionally+be followed by another string of consecutive colons.++Note:  the `commonmark` parser doesn't permit colons after+the attributes.++The attribute syntax is exactly as in fenced code blocks (see+[Extension: `fenced_code_attributes`]).  As with fenced+code blocks, one can use either attributes in curly braces+or a single unbraced word, which will be treated as a class+name.  The Div ends with another line containing a string of at+least three consecutive colons.  The fenced Div should be+separated by blank lines from preceding and following blocks.++Example:++    ::::: {#special .sidebar}+    Here is a paragraph.++    And another.+    :::::++Fenced divs can be nested.  Opening fences are distinguished+because they *must* have attributes:++    ::: Warning ::::::+    This is a warning.++    ::: Danger+    This is a warning within a warning.+    :::+    ::::::::::::::::::++Fences without attributes are always closing fences.  Unlike+with fenced code blocks, the number of colons in the closing+fence need not match the number in the opening fence.  However,+it can be helpful for visual clarity to use fences of different+lengths to distinguish nested divs from their parents.+++### Extension: `bracketed_spans` ###++A bracketed sequence of inlines, as one would use to begin+a link, will be treated as a `Span` with attributes if it is+followed immediately by attributes:++    [This is *some text*]{.class key="val"}++## Footnotes++### Extension: `footnotes` ###++Pandoc's Markdown allows footnotes, using the following syntax:++    Here is a footnote reference,[^1] and another.[^longnote]++    [^1]: Here is the footnote.++    [^longnote]: Here's one with multiple blocks.++        Subsequent paragraphs are indented to show that they+    belong to the previous footnote.++            { some.code }++        The whole paragraph can be indented, or just the first+        line.  In this way, multi-paragraph footnotes work like+        multi-paragraph list items.++    This paragraph won't be part of the note, because it+    isn't indented.++The identifiers in footnote references may not contain spaces, tabs,+newlines, or the characters `^`, `[`, or `]`. These identifiers+are used only to correlate the footnote reference with the note+itself; in the output, footnotes will be numbered sequentially.++The footnotes themselves need not be placed at the end of the+document.  They may appear anywhere except inside other block elements+(lists, block quotes, tables, etc.).  Each footnote should be+separated from surrounding content (including other footnotes)+by blank lines.++### Extension: `inline_notes` ###++Inline footnotes are also allowed (though, unlike regular notes,+they cannot contain multiple paragraphs).  The syntax is as follows:++    Here is an inline note.^[Inline notes are easier to write, since+    you don't have to pick an identifier and move down to type the+    note.]++Inline and regular footnotes may be mixed freely.++## Citation syntax++### Extension: `citations` ###++To cite a bibliographic item with an identifier foo, use the+syntax `@foo`.  Normal citations should be included in square+brackets, with semicolons separating distinct items:++    Blah blah [@doe99; @smith2000; @smith2004].++How this is rendered depends on the citation style.  In an+author-date style, it might render as++    Blah blah (Doe 1999, Smith 2000, 2004).++In a footnote style, it might render as++    Blah blah.[^1]++    [^1]:  John Doe, "Frogs," *Journal of Amphibians* 44 (1999);+    Susan Smith, "Flies," *Journal of Insects* (2000);+    Susan Smith, "Bees," *Journal of Insects* (2004).++See the [CSL user documentation] for more information about CSL+styles and how they affect rendering.++Unless a citation key starts with a letter, digit, or `_`,+and contains only alphanumerics and single internal punctuation+characters (`:.#$%&-+?<>~/`), it must be surrounded+by curly braces, which are not considered part of the key.+In `@Foo_bar.baz.`, the key is `Foo_bar.baz` because the final+period is not *internal* punctuation, so it is not included in+the key.  In `@{Foo_bar.baz.}`, the key is `Foo_bar.baz.`, including+the final period.+In `@Foo_bar--baz`, the key is `Foo_bar` because the repeated internal+punctuation characters terminate the key.+The curly braces are recommended if you use URLs as+keys: `[@{https://example.com/bib?name=foobar&date=2000}, p.  33]`.++Citation items may optionally include a prefix, a locator, and+a suffix.  In++    Blah blah [see @doe99, pp. 33-35 and *passim*; @smith04, chap. 1].++the first item (`doe99`) has prefix `see `, locator `pp.  33-35`,+and suffix `and *passim*`.  The second item (`smith04`) has+locator `chap. 1` and no prefix or suffix.++Pandoc uses some heuristics to separate the locator from the+rest of the subject.  It is sensitive to the locator terms+defined in the [CSL locale files].  Either abbreviated or+unabbreviated forms are accepted. In the `en-US` locale, locator+terms can be written in either singular or plural forms, as+`book`, `bk.`/`bks.`; `chapter`, `chap.`/`chaps.`; `column`,+`col.`/`cols.`; `figure`, `fig.`/`figs.`; `folio`,+`fol.`/`fols.`; `number`, `no.`/`nos.`; `line`, `l.`/`ll.`;+`note`, `n.`/`nn.`; `opus`, `op.`/`opp.`; `page`, `p.`/`pp.`;+`paragraph`, `para.`/`paras.`; `part`, `pt.`/`pts.`; `section`,+`sec.`/`secs.`; `sub verbo`, `s.v.`/`s.vv.`; `verse`,+`v.`/`vv.`; `volume`, `vol.`/`vols.`; `¶`/`¶¶`; `§`/`§§`. If no+locator term is used, "page" is assumed.++In complex cases, you can force something to be treated as+a locator by enclosing it in curly braces or prevent parsing+the suffix as locator by prepending curly braces:++    [@smith{ii, A, D-Z}, with a suffix]+    [@smith, {pp. iv, vi-xi, (xv)-(xvii)} with suffix here]+    [@smith{}, 99 years later]++A minus sign (`-`) before the `@` will suppress mention of+the author in the citation.  This can be useful when the+author is already mentioned in the text:++    Smith says blah [-@smith04].++You can also write an author-in-text citation, by omitting the+square brackets:++    @smith04 says blah.++    @smith04 [p. 33] says blah.++This will cause the author's name to be rendered, followed by+the bibliographical details.  Use this form when you want to+make the citation the subject of a sentence.++When you are using a note style, it is usually better to let+citeproc create the footnotes from citations rather than writing+an explicit note.  If you do write an explicit note that+contains a citation, note that normal citations will be put in+parentheses, while author-in-text citations will not.  For+this reason, it is sometimes preferable to use the+author-in-text style inside notes when using a note style.++Many CSL styles will format citations differently when the+same source has been cited earlier.  In documents with chapters,+it is usually desirable to reset this position information+at the beginning of every chapter. To do this, add the class+`reset-citation-positions` to the heading for each chapter:++    # The Beginning {.reset-citation-positions}++Note that this class only has an effect when placed on+top-level headings; it is ignored in nested blocks.++[CSL user documentation]: https://citationstyles.org/authors/+[CSL]: https://docs.citationstyles.org/en/stable/specification.html+[CSL markup specs]: https://citeproc-js.readthedocs.io/en/latest/csl-json/markup.html#html-like-formatting-tags+[Chicago Manual of Style]: https://chicagomanualofstyle.org+[Citation Style Language]: https://citationstyles.org+[Zotero Style Repository]: https://www.zotero.org/styles+[finding and editing styles]: https://citationstyles.org/authors/+[CSL locale files]: https://github.com/citation-style-language/locales++## Non-default extensions++The following Markdown syntax extensions are not enabled by default+in pandoc, but may be enabled by adding `+EXTENSION` to the format+name, where `EXTENSION` is the name of the extension.  Thus, for+example, `markdown+hard_line_breaks` is Markdown with hard line breaks.++### Extension: `rebase_relative_paths` ###++Rewrite relative paths for Markdown links and images, depending+on the path of the file containing the link or image link.  For+each link or image, pandoc will compute the directory of the+containing file, relative to the working directory, and prepend+the resulting path to the link or image path.++The use of this extension is best understood by example.+Suppose you have a subdirectory for each chapter of a book,+`chap1`, `chap2`, `chap3`. Each contains a file `text.md` and a+number of images used in the chapter.  You would like to have+`![image](spider.jpg)` in `chap1/text.md` refer to+`chap1/spider.jpg` and `![image](spider.jpg)` in `chap2/text.md`+refer to `chap2/spider.jpg`.  To do this, use++    pandoc chap*/*.md -f markdown+rebase_relative_paths++Without this extension, you would have to use+`![image](chap1/spider.jpg)` in `chap1/text.md` and+`![image](chap2/spider.jpg)` in `chap2/text.md`.  Links with+relative paths will be rewritten in the same way as images.++Absolute paths and URLs are not changed.  Neither are empty+paths or paths consisting entirely of a fragment, e.g., `#foo`.++Note that relative paths in reference links and images will+be rewritten relative to the file containing the link+reference definition, not the file containing the reference link+or image itself, if these differ.++### Extension: `mark` ###++To highlight out a section of text, begin and end it with+with `==`. Thus, for example,++    This ==is deleted text.==++### Extension: `attributes` ###++Allows attributes to be attached to any inline or block-level+element when parsing `commonmark`.+The syntax for the attributes is the same as that+used in [`header_attributes`][Extension: `header_attributes`].++- Attributes that occur immediately after an inline+  element affect that element.  If they follow a space, then they+  belong to the space.  (Hence, this option subsumes+  `inline_code_attributes` and `link_attributes`.)+- Attributes that occur immediately before a block+  element, on a line by themselves, affect that+  element.+- Consecutive attribute specifiers may be used,+  either for blocks or for inlines.  Their attributes+  will be combined.+- Attributes that occur at the end of the text of+  a Setext or ATX heading (separated by whitespace+  from the text) affect the heading element. (Hence, this+  option subsumes `header_attributes`.)+- Attributes that occur after the opening fence+  in a fenced code block affect the code block element. (Hence,+  this option subsumes `fenced_code_attributes`.)+- Attributes that occur at the end of a reference+  link definition affect links that refer to that+  definition.++Note that pandoc's AST does not currently allow attributes+to be attached to arbitrary elements.  Hence a Span or Div+container will be added if needed.++### Extension: `old_dashes` ###++Selects the pandoc <= 1.8.2.1 behavior for parsing smart dashes:+`-` before a numeral is an en-dash, and `--` is an em-dash.+This option only has an effect if `smart` is enabled. It is+selected automatically for `textile` input.++### Extension: `angle_brackets_escapable` ###++Allow `<` and `>` to be backslash-escaped, as they can be in+GitHub flavored Markdown but not original Markdown.  This is+implied by pandoc's default `all_symbols_escapable`.++### Extension: `lists_without_preceding_blankline` ###++Allow a list to occur right after a paragraph, with no intervening+blank space.++### Extension: `four_space_rule` ###++Selects the pandoc <= 2.0 behavior for parsing lists, so that+four spaces indent are needed for list item continuation+paragraphs.++### Extension: `spaced_reference_links` ###++Allow whitespace between the two components of a reference link,+for example,++    [foo] [bar].++### Extension: `hard_line_breaks` ###++Causes all newlines within a paragraph to be interpreted as hard line+breaks instead of spaces.++### Extension: `ignore_line_breaks` ###++Causes newlines within a paragraph to be ignored, rather than being+treated as spaces or as hard line breaks.  This option is intended for+use with East Asian languages where spaces are not used between words,+but text is divided into lines for readability.++### Extension: `east_asian_line_breaks` ###++Causes newlines within a paragraph to be ignored, rather than+being treated as spaces or as hard line breaks, when they occur+between two East Asian wide characters.  This is a better choice+than `ignore_line_breaks` for texts that include a mix of East+Asian wide characters and other characters.++### Extension: `emoji` ###++Parses textual emojis like `:smile:` as Unicode emoticons.++### Extension: `tex_math_gfm` ###++Supports two GitHub-specific formats for math.+Inline math: ``$`e=mc^2`$``.++Display math:++````+``` math+e=mc^2+```+````++### Extension: `tex_math_single_backslash` ###++Causes anything between `\(` and `\)` to be interpreted as inline+TeX math, and anything between `\[` and `\]` to be interpreted+as display TeX math.  Note: a drawback of this extension is that+it precludes escaping `(` and `[`.++### Extension: `tex_math_double_backslash` ###++Causes anything between `\\(` and `\\)` to be interpreted as inline+TeX math, and anything between `\\[` and `\\]` to be interpreted+as display TeX math.++### Extension: `markdown_attribute` ###++By default, pandoc interprets material inside block-level tags as Markdown.+This extension changes the behavior so that Markdown is only parsed+inside block-level tags if the tags have the attribute `markdown=1`.++### Extension: `mmd_title_block` ###++Enables a [MultiMarkdown] style title block at the top of+the document, for example:++    Title:   My title+    Author:  John Doe+    Date:    September 1, 2008+    Comment: This is a sample mmd title block, with+             a field spanning multiple lines.++See the MultiMarkdown documentation for details.  If `pandoc_title_block` or+`yaml_metadata_block` is enabled, it will take precedence over+`mmd_title_block`.++### Extension: `abbreviations` ###++Parses PHP Markdown Extra abbreviation keys, like++    *[HTML]: Hypertext Markup Language++Note that the pandoc document model does not support+abbreviations, so if this extension is enabled, abbreviation keys are+simply skipped (as opposed to being parsed as paragraphs).++### Extension: `alerts` ###++Supports [GitHub-style Markdown alerts], like++    > [!TIP]+    > Helpful advice for doing things better or more easily.++  [GitHub-style Markdown alerts]: https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts++### Extension: `autolink_bare_uris` ###++Makes all absolute URIs into links, even when not surrounded by+pointy braces `<...>`.++### Extension: `mmd_link_attributes` ###++Parses MultiMarkdown-style key-value attributes on link+and image references. This extension should not be confused with the+[`link_attributes`](#extension-link_attributes) extension.++    This is a reference ![image][ref] with MultiMarkdown attributes.++    [ref]: https://path.to/image "Image title" width=20px height=30px+           id=myId class="myClass1 myClass2"++### Extension: `mmd_header_identifiers` ###++Parses MultiMarkdown-style heading identifiers (in square brackets,+after the heading but before any trailing `#`s in an ATX heading).++### Extension: `gutenberg` ###++Use [Project Gutenberg] conventions for `plain` output:+all-caps for strong emphasis, surround by underscores+for regular emphasis, add extra blank space around headings.++  [Project Gutenberg]: https://www.gutenberg.org++### Extension: `sourcepos` ###++Include source position attributes when parsing `commonmark`.+For elements that accept attributes, a `data-pos` attribute+is added; other elements are placed in a surrounding+Div or Span element with a `data-pos` attribute.++### Extension: `short_subsuperscripts` ###++Parse MultiMarkdown-style subscripts and superscripts, which start with+a '~' or '^' character, respectively, and include the alphanumeric sequence+that follows. For example:++    x^2 = 4++or++    Oxygen is O~2.++### Extension: `wikilinks_title_after_pipe` ###++Pandoc supports multiple Markdown wikilink syntaxes, regardless of+whether the title is before or after the pipe.++Using `--from=markdown+wikilinks_title_after_pipe` results in+```[[Wiki]]+[[URL|title]]+```++while using `--from=markdown+wikilinks_title_before_pipe` results+in+```[[Wiki]]+[[title|URL]]+```++## Markdown variants++In addition to pandoc's extended Markdown, the following Markdown+variants are supported:++- `markdown_phpextra` (PHP Markdown Extra)+- `markdown_github` (deprecated GitHub-Flavored Markdown)+- `markdown_mmd` (MultiMarkdown)+- `markdown_strict` (Markdown.pl)+- `commonmark` (CommonMark)+- `gfm` (Github-Flavored Markdown)+- `commonmark_x` (CommonMark with many pandoc extensions)++To see which extensions are supported for a given format,+and which are enabled by default, you can use the command++    pandoc --list-extensions=FORMAT++where `FORMAT` is replaced with the name of the format.++Note that the list of extensions for `commonmark`,+`gfm`, and `commonmark_x` are defined relative to default+commonmark.  So, for example, `backtick_code_blocks`+does not appear as an extension, since it is enabled by+default and cannot be disabled.++# Citations++When the `--citeproc` option is used, pandoc can automatically generate+citations and a bibliography in a number of styles.  Basic usage is++    pandoc --citeproc myinput.txt++To use this feature, you will need to have++- a document containing citations (see [Citation syntax]);+- a source of bibliographic data: either an external bibliography+  file or a list of `references` in the document's YAML metadata;+- optionally, a [CSL] citation style.++## Specifying bibliographic data++You can specify an external bibliography using the+`bibliography` metadata field in a YAML metadata section or the+`--bibliography` command line argument. If you want to use+multiple bibliography files, you can supply multiple+`--bibliography` arguments or set `bibliography` metadata field+to YAML array.  A bibliography may have any of these formats:++  Format            File extension+  ------------      --------------+  BibLaTeX          .bib+  BibTeX            .bibtex+  CSL JSON          .json+  CSL YAML          .yaml+  RIS               .ris++Note that `.bib` can be used with both BibTeX and BibLaTeX files;+use the extension `.bibtex` to force interpretation as BibTeX.++In BibTeX and BibLaTeX databases, pandoc parses LaTeX markup+inside fields such as `title`; in CSL YAML databases, pandoc+Markdown; and in CSL JSON databases, an [HTML-like markup][CSL+markup specs]:++`<i>...</i>`+:   italics++`<b>...</b>`+:   bold++`<span style="font-variant:small-caps;">...</span>` or `<sc>...</sc>`+:   small capitals++`<sub>...</sub>`+:   subscript++`<sup>...</sup>`+:   superscript++`<span class="nocase">...</span>`+:   prevent a phrase from being capitalized as title case++As an alternative to specifying a bibliography file using+`--bibliography` or the YAML metadata field `bibliography`, you+can include the citation data directly in the `references` field+of the document's YAML metadata. The field should contain an+array of YAML-encoded references, for example:++    ---+    references:+    - type: article-journal+      id: WatsonCrick1953+      author:+      - family: Watson+        given: J. D.+      - family: Crick+        given: F. H. C.+      issued:+        date-parts:+        - - 1953+          - 4+          - 25+      title: 'Molecular structure of nucleic acids: a structure for+        deoxyribose nucleic acid'+      title-short: Molecular structure of nucleic acids+      container-title: Nature+      volume: 171+      issue: 4356+      page: 737-738+      DOI: 10.1038/171737a0+      URL: https://www.nature.com/articles/171737a0+      language: en-GB+    ...++If both an external bibliography and inline (YAML metadata)+references are provided, both will be used. In case of+conflicting `id`s, the inline references will take precedence.++Note that pandoc can be used to produce such a YAML metadata+section from a BibTeX, BibLaTeX, or CSL JSON bibliography:++    pandoc chem.bib -s -f biblatex -t markdown+    pandoc chem.json -s -f csljson -t markdown++Indeed, pandoc can convert between any of these+citation formats:++    pandoc chem.bib -s -f biblatex -t csljson+    pandoc chem.yaml -s -f markdown -t biblatex++Running pandoc on a bibliography file with the `--citeproc`+option will create a formatted bibliography in the format+of your choice:++    pandoc chem.bib -s --citeproc -o chem.html+    pandoc chem.bib -s --citeproc -o chem.pdf++### Capitalization in titles++If you are using a bibtex or biblatex bibliography, then observe+the following rules:++  - English titles should be in title case.  Non-English titles should+    be in sentence case, and the `langid` field in biblatex should be+    set to the relevant language.  (The following values are treated+    as English:  `american`, `british`, `canadian`, `english`,+    `australian`, `newzealand`, `USenglish`, or `UKenglish`.)++  - As is standard with bibtex/biblatex, proper names should be+    protected with curly braces so that they won't be lowercased+    in styles that call for sentence case.  For example:++        title = {My Dinner with {Andre}}++  - In addition, words that should remain lowercase (or camelCase)+    should be protected:++        title = {Spin Wave Dispersion on the {nm} Scale}++    Though this is not necessary in bibtex/biblatex, it is necessary+    with citeproc, which stores titles internally in sentence case,+    and converts to title case in styles that require it.  Here we+    protect "nm" so that it doesn't get converted to "Nm" at this stage.++If you are using a CSL bibliography (either JSON or YAML), then observe+the following rules:++  - All titles should be in sentence case.++  - Use the `language` field for non-English titles to prevent their+    conversion to title case in styles that call for this. (Conversion+    happens only if `language` begins with `en` or is left empty.)++  - Protect words that should not be converted to title case using+    this syntax:++        Spin wave dispersion on the <span class="nocase">nm</span> scale++### Conference Papers, Published vs. Unpublished++For a formally published conference paper, use the biblatex entry type+`inproceedings` (which will be mapped to CSL `paper-conference`).++For an unpublished manuscript, use the biblatex entry type+`unpublished` without an `eventtitle` field (this entry type+will be mapped to CSL `manuscript`).++For a talk, an unpublished conference paper, or a poster+presentation, use the biblatex entry type `unpublished` with an+`eventtitle` field (this entry type will be mapped to CSL+`speech`). Use the biblatex `type` field to indicate the type,+e.g. "Paper", or "Poster". `venue` and `eventdate` may be useful+too, though `eventdate` will not be rendered by most CSL styles.+Note that `venue` is for the event's venue, unlike `location`+which describes the publisher's location; do not use the latter+for an unpublished conference paper.+++## Specifying a citation style++Citations and references can be formatted using any style supported by the+[Citation Style Language], listed in the [Zotero Style Repository].+These files are specified using the `--csl` option or the `csl`+(or `citation-style`) metadata field.  By default, pandoc will+use the [Chicago Manual of Style] author-date format.  (You can+override this default by copying a CSL style of your choice+to `default.csl` in your user data directory.)+The CSL project provides further information on [finding and+editing styles].++The `--citation-abbreviations` option (or the+`citation-abbreviations` metadata field) may be used to specify+a JSON file containing abbreviations of journals that should be+used in formatted bibliographies when `form="short"` is+specified.  The format of the file can be illustrated with an+example:+++    { "default": {+        "container-title": {+                "Lloyd's Law Reports": "Lloyd's Rep",+                "Estates Gazette": "EG",+                "Scots Law Times": "SLT"+        }+      }+    }+++## Citations in note styles++Pandoc's citation processing is designed to allow you to+move between author-date, numerical, and note styles without+modifying the Markdown source.  When you're using a note+style, avoid inserting footnotes manually. Instead, insert+citations just as you would in an author-date style---for+example,++    Blah blah [@foo, p. 33].++The footnote will be created automatically. Pandoc will take+care of removing the space and moving the note before or+after the period, depending on the setting of+`notes-after-punctuation`, as described below in [Other relevant+metadata fields].++In some cases you may need to put a citation inside a regular+footnote.  Normal citations in footnotes (such as `[@foo, p.+33]`) will be rendered in parentheses.  In-text citations (such+as `@foo [p. 33]`) will be rendered without parentheses. (A+comma will be added if appropriate.)  Thus:++    [^1]:  Some studies [@foo; @bar, p. 33] show that+    frubulicious zoosnaps are quantical.  For a survey+    of the literature, see @baz [chap. 1].+++## Placement of the bibliography++If the style calls for a list of works cited, it will be placed+in a div with id `refs`, if one exists:[^note-on-refs]++    ::: {#refs}+    :::++Otherwise, it will be placed at the end of the document.+Generation of the bibliography can be suppressed by setting+`suppress-bibliography: true` in the YAML metadata.++[^note-on-refs]:+    Note that if `--file-scope` is used, a div written this way will be+    given an identifier of the form `FILE__refs`, to avoid duplicate+    identifiers (see `--file-scope`). In view of this possibility,+    pandoc will place the bibliography in any div whose identifier is+    `refs` *or* ends with `__refs`.++If you wish the bibliography to have a section heading, you can+set `reference-section-title` in the metadata, or put the heading+at the beginning of the div with id `refs` (if you are using it)+or at the end of your document:++    last paragraph...++    # References++The bibliography will be inserted after this heading.  Note that+the `unnumbered` class will be added to this heading, so that the+section will not be numbered.++If you want to put the bibliography into a variable in your+template, one way to do that is to put the div with id `refs`+into a metadata field, e.g.++    ---+    refs: |+       ::: {#refs}+       :::+    ...++You can then put the variable `$refs$` into your template where+you want the bibliography to be placed.++## Including uncited items in the bibliography++If you want to include items in the bibliography without actually+citing them in the body text, you can define a dummy `nocite` metadata+field and put the citations there:++    ---+    nocite: |+      @item1, @item2+    ...++    @item3++In this example, the document will contain a citation for `item3`+only, but the bibliography will contain entries for `item1`, `item2`, and+`item3`.++It is possible to create a bibliography with all the citations,+whether or not they appear in the document, by using a wildcard:++    ---+    nocite: |+      @*+    ...++For LaTeX output, you can also use [`natbib`] or [`biblatex`] to+render the bibliography. In order to do so, specify bibliography+files as outlined above, and add `--natbib` or `--biblatex`+argument to pandoc invocation. Bear in mind that bibliography+files have to be in either BibTeX (for `--natbib`)+or BibLaTeX (for `--biblatex`) format.++## Other relevant metadata fields++A few other metadata fields affect bibliography formatting:++`link-citations`+:   If true, citations will be hyperlinked to the+    corresponding bibliography entries (for author-date and+    numerical styles only).  Defaults to false.++`link-bibliography`+:   If true, DOIs, PMCIDs, PMID, and URLs in bibliographies will+    be rendered as hyperlinks.  (If an entry contains a DOI, PMCID,+    PMID, or URL, but none of these fields are rendered by the style,+    then the title, or in the absence of a title the whole entry, will+    be hyperlinked.)  Defaults to true.++`lang`+:   The `lang` field will affect how the style is localized,+    for example in the translation of labels, the use+    of quotation marks, and the way items are sorted.+    (For backwards compatibility, `locale` may be used instead+    of `lang`, but this use is deprecated.)++    A BCP 47 language tag is expected:  for example, `en`,+    `de`, `en-US`, `fr-CA`, `ug-Cyrl`.  The unicode extension+    syntax (after `-u-`) may be used to specify options for+    collation (sorting) more precisely. Here are some examples:++    - `zh-u-co-pinyin`: Chinese with the Pinyin collation.+    - `es-u-co-trad`: Spanish with the traditional collation+      (with `Ch` sorting after `C`).+    - `fr-u-kb`: French with "backwards" accent sorting+      (with `coté` sorting after `côte`).+    - `en-US-u-kf-upper`: English with uppercase letters sorting+       before lower (default is lower before upper).++`notes-after-punctuation`+:    If true (the default for note styles), pandoc will put+     footnote references or superscripted numerical citations+     after following punctuation.  For example, if the source+     contains `blah blah [@jones99].`, the result will look like+     `blah blah.[^1]`, with the note moved after the period and+     the space collapsed.  If false, the space will still be+     collapsed, but the footnote will not be moved after the+     punctuation.  The option may also be used in numerical styles+     that use superscripts for citation numbers (but for these+     styles the default is not to move the citation).+++# Slide shows++You can use pandoc to produce an HTML + JavaScript slide presentation+that can be viewed via a web browser.  There are five ways to do this,+using [S5], [DZSlides], [Slidy], [Slideous], or [reveal.js].+You can also produce a PDF slide show using LaTeX [`beamer`], or+slide shows in Microsoft [PowerPoint] format.++Here's the Markdown source for a simple slide show, `habits.txt`:++    % Habits+    % John Doe+    % March 22, 2005++    # In the morning++    ## Getting up++    - Turn off alarm+    - Get out of bed++    ## Breakfast++    - Eat eggs+    - Drink coffee++    # In the evening++    ## Dinner++    - Eat spaghetti+    - Drink wine++    ------------------++    ![picture of spaghetti](images/spaghetti.jpg)++    ## Going to sleep++    - Get in bed+    - Count sheep++To produce an HTML/JavaScript slide show, simply type++    pandoc -t FORMAT -s habits.txt -o habits.html++where `FORMAT` is either `s5`, `slidy`, `slideous`, `dzslides`, or `revealjs`.++For Slidy, Slideous, reveal.js, and S5, the file produced by+pandoc with the `-s/--standalone` option embeds a link to+JavaScript and CSS files, which are assumed to be available at+the relative path `s5/default` (for S5), `slideous` (for+Slideous), `reveal.js` (for reveal.js), or at the Slidy website+at `w3.org` (for Slidy).  (These paths can be changed by setting+the `slidy-url`, `slideous-url`, `revealjs-url`, or `s5-url`+variables; see [Variables for HTML slides], above.) For+DZSlides, the (relatively short) JavaScript and CSS are included+in the file by default.++With all HTML slide formats, the `--self-contained` option can+be used to produce a single file that contains all of the data+necessary to display the slide show, including linked scripts,+stylesheets, images, and videos.++To produce a PDF slide show using beamer, type++    pandoc -t beamer habits.txt -o habits.pdf++Note that a reveal.js slide show can also be converted to a PDF+by printing it to a file from the browser.++To produce a PowerPoint slide show, type++    pandoc habits.txt -o habits.pptx++## Structuring the slide show++By default, the *slide level* is the highest heading level in+the hierarchy that is followed immediately by content, and not another+heading, somewhere in the document. In the example above, level-1 headings+are always followed by level-2 headings, which are followed by content,+so the slide level is 2. This default can be overridden using the+`--slide-level` option.++The document is carved up into slides according to the following+rules:++  * A horizontal rule always starts a new slide.++  * A heading at the slide level always starts a new slide.++  * Headings *below* the slide level in the hierarchy create+    headings *within* a slide.  (In beamer, a "block" will be+    created.  If the heading has the class `example`, an+    `exampleblock` environment will be used; if it has the class+    `alert`, an `alertblock` will be used; otherwise a regular+    `block` will be used.)++  * Headings *above* the slide level in the hierarchy create+    "title slides," which just contain the section title+    and help to break the slide show into sections.+    Non-slide content under these headings will be included+    on the title slide (for HTML slide shows) or in a+    subsequent slide with the same title (for beamer).++  * A title page is constructed automatically from the document's title+    block, if present. (In the case of beamer, this can be disabled+    by commenting out some lines in the default template.)++These rules are designed to support many different styles of slide show. If+you don't care about structuring your slides into sections and subsections,+you can either just use level-1 headings for all slides (in that case, level 1+will be the slide level) or you can set `--slide-level=0`.++Note:  in reveal.js slide shows, if slide level is 2, a two-dimensional+layout will be produced, with level-1 headings building horizontally+and level-2 headings building vertically. It is not recommended that+you use deeper nesting of section levels with reveal.js unless you set+`--slide-level=0` (which lets reveal.js produce a one-dimensional layout+and only interprets horizontal rules as slide boundaries).++### PowerPoint layout choice++When creating slides, the pptx writer chooses from a number of pre-defined+layouts, based on the content of the slide:++Title Slide+:   This layout is used for the initial slide, which is generated and+    filled from the metadata fields `date`, `author`, and `title`, if+    they are present.++Section Header+:   This layout is used for what pandoc calls “title slides”, i.e.+    slides which start with a header which is above the slide level in+    the hierarchy.++Two Content+:   This layout is used for two-column slides, i.e. slides containing a+    div with class `columns` which contains at least two divs with class+    `column`.++Comparison+:   This layout is used instead of “Two Content” for any two-column+    slides in which at least one column contains text followed by+    non-text (e.g. an image or a table).++Content with Caption+:   This layout is used for any non-two-column slides which contain text+    followed by non-text (e.g. an image or a table).++Blank+:   This layout is used for any slides which only contain blank content,+    e.g. a slide containing only speaker notes, or a slide containing+    only a non-breaking space.++Title and Content+:   This layout is used for all slides which do not match the criteria+    for another layout.++These layouts are chosen from the default pptx reference doc included with+pandoc, unless an alternative reference doc is specified using+`--reference-doc`.++## Incremental lists++By default, these writers produce lists that display "all at once."+If you want your lists to display incrementally (one item at a time),+use the `-i` option. If you want a particular list to depart from the+default, put it in a `div` block with class `incremental` or+`nonincremental`. So, for example, using the `fenced div` syntax, the+following would be incremental regardless of the document default:++    ::: incremental++    - Eat spaghetti+    - Drink wine++    :::++or++    ::: nonincremental++    - Eat spaghetti+    - Drink wine++    :::++While using `incremental` and `nonincremental` divs is the+recommended method of setting incremental lists on a per-case basis,+an older method is also supported: putting lists inside a blockquote+will depart from the document default (that is, it will display+incrementally without the `-i` option and all at once with the `-i`+option):++    > - Eat spaghetti+    > - Drink wine++Both methods allow incremental and nonincremental lists to be mixed+in a single document.++If you want to include a block-quoted list, you can work around+this behavior by putting the list inside a fenced div, so that+it is not the direct child of the block quote:++    > ::: wrapper+    > - a+    > - list in a quote+    > :::++## Inserting pauses++You can add "pauses" within a slide by including a paragraph containing+three dots, separated by spaces:++    # Slide with a pause++    content before the pause++    . . .++    content after the pause++Note: this feature is not yet implemented for PowerPoint output.++## Styling the slides++You can change the style of HTML slides by putting customized CSS files+in `$DATADIR/s5/default` (for S5), `$DATADIR/slidy` (for Slidy),+or `$DATADIR/slideous` (for Slideous),+where `$DATADIR` is the user data directory (see `--data-dir`, above).+The originals may be found in pandoc's system data directory (generally+`$CABALDIR/pandoc-VERSION/s5/default`). Pandoc will look there for any+files it does not find in the user data directory.++For dzslides, the CSS is included in the HTML file itself, and may+be modified there.++All [reveal.js configuration options] can be set through variables.+For example, themes can be used by setting the `theme` variable:++    -V theme=moon++Or you can specify a custom stylesheet using the `--css` option.++To style beamer slides, you can specify a `theme`, `colortheme`,+`fonttheme`, `innertheme`, and `outertheme`, using the `-V` option:++    pandoc -t beamer habits.txt -V theme:Warsaw -o habits.pdf++Note that heading attributes will turn into slide attributes+(on a `<div>` or `<section>`) in HTML slide formats, allowing you+to style individual slides.  In beamer, a number of heading+classes and attributes are recognized as frame options and+will be passed through as options to the frame: see+[Frame attributes in beamer], below.++## Speaker notes++Speaker notes are supported in reveal.js, PowerPoint (pptx),+and beamer output. You can add notes to your Markdown document thus:++    ::: notes++    This is my note.++    - It can contain Markdown+    - like this list++    :::++To show the notes window in reveal.js, press `s` while viewing the+presentation. Speaker notes in PowerPoint will be available, as usual,+in handouts and presenter view.++Notes are not yet supported for other slide formats, but the notes+will not appear on the slides themselves.++### Speaker notes on the title slide (PowerPoint)++For PowerPoint output, the title slide is generated from the document's+YAML metadata block. To add speaker notes to this slide, use a `notes`+field in the metadata:++    ---+    title: My Presentation+    author: Jane Doe+    notes: |+      Welcome everyone to this presentation.++      Remember to introduce yourself and mention the key topics.+    ---++The `notes` field can contain multiple paragraphs and Markdown formatting.++## Columns++To put material in side by side columns, you can use a native+div container with class `columns`, containing two or more div+containers with class `column` and a `width` attribute:++    :::::::::::::: {.columns}+    ::: {.column width="40%"}+    contents...+    :::+    ::: {.column width="60%"}+    contents...+    :::+    ::::::::::::::++Note: Specifying column widths does not currently work for PowerPoint.++### Additional columns attributes in beamer++The div containers with classes `columns` and `column` can optionally have+an `align` attribute.+The class `columns` can optionally have a `totalwidth` attribute or an+`onlytextwidth` class.++    :::::::::::::: {.columns align=center totalwidth=8em}+    ::: {.column width="40%"}+    contents...+    :::+    ::: {.column width="60%" align=bottom}+    contents...+    :::+    ::::::::::::::++The `align` attributes on `columns` and `column` can be used with the+values `top`, `top-baseline`, `center` and `bottom` to vertically align+the columns. It defaults to `top` in `columns`.++The `totalwidth` attribute limits the width of the columns to the given value.++    :::::::::::::: {.columns align=top .onlytextwidth}+    ::: {.column width="40%" align=center}+    contents...+    :::+    ::: {.column width="60%"}+    contents...+    :::+    ::::::::::::::++The class `onlytextwidth` sets the `totalwidth` to `\textwidth`.++See Section 12.7 of the [Beamer User's Guide] for more details.++## Frame attributes in beamer++Sometimes it is necessary to add the LaTeX `[fragile]` option to+a frame in beamer (for example, when using the `minted` environment).+This can be forced by adding the `fragile` class to the heading+introducing the slide:++    # Fragile slide {.fragile}++All of the other frame attributes described in Section 8.1 of+the [Beamer User's Guide] may also be used: `allowdisplaybreaks`,+`allowframebreaks`, `b`, `c`, `s`, `t`, `environment`, `label`, `plain`,+`shrink`, `standout`, `noframenumbering`, `squeeze`.+`allowframebreaks` is recommended especially for bibliographies, as+it allows multiple slides to be created if the content overfills the+frame:++    # References {.allowframebreaks}++In addition, the `frameoptions` attribute may be used to+pass arbitrary frame options to a beamer slide:++    # Heading {frameoptions="squeeze,shrink,customoption=foobar"}++## Background in reveal.js, beamer, and pptx++Background images can be added to self-contained reveal.js slide shows,+beamer slide shows, and pptx slide shows.++### On all slides (beamer, reveal.js, pptx)++With beamer and reveal.js, the configuration option `background-image` can be+used either in the YAML metadata block or as a command-line variable to get the same image on every slide.++Note that for reveal.js, the `background-image` will be used as+a `parallaxBackgroundImage` (see below).++For pptx, you can use a `--reference-doc` in which+background images have been set on the [relevant+layouts](#powerpoint-layout-choice).++#### `parallaxBackgroundImage` (reveal.js)++For reveal.js, there is also the reveal.js-native option+`parallaxBackgroundImage`, which produces a parallax scrolling background.+You must also set `parallaxBackgroundSize`, and can optionally set+`parallaxBackgroundHorizontal`+and `parallaxBackgroundVertical` to configure the scrolling behaviour.+See the [reveal.js+documentation](https://revealjs.com/backgrounds/#parallax-background)+for more details about the meaning of these options.++In reveal.js's overview mode, the parallaxBackgroundImage will show up+only on the first slide.++### On individual slides (reveal.js, pptx)++To set an image for a particular reveal.js or pptx slide, add+`{background-image="/path/to/image"}` to the first slide-level heading on the+slide (which may even be empty).++As the [HTML writers pass unknown attributes+through](#extension-link_attributes), other reveal.js background settings also+work on individual slides, including `background-size`, `background-repeat`,+`background-color`, `transition`, and `transition-speed`. (The `data-` prefix+will automatically be added.)++Note: `data-background-image` is also supported in pptx for consistency with+reveal.js – if `background-image` isn’t found, `data-background-image` will be+checked.++### On the title slide (reveal.js, pptx)++To add a background image to the automatically generated title slide for+reveal.js, use the `title-slide-attributes` variable in the YAML metadata block.+It must contain a map of attribute names and values. (Note that the `data-`+prefix is required here, as it isn’t added automatically.)++For pptx, pass a `--reference-doc` with the background+image set on the “Title Slide” layout.++### Example (reveal.js)++```+---+title: My Slide Show+parallaxBackgroundImage: /path/to/my/background_image.png+title-slide-attributes:+    data-background-image: /path/to/title_image.png+    data-background-size: contain+---++## Slide One++Slide 1 has background_image.png as its background.++## {background-image="/path/to/special_image.jpg"}++Slide 2 has a special image for its background, even though the heading has no content.+```++# EPUBs++## EPUB Metadata++There are two ways to specify metadata for an EPUB. The first is to use+the `--epub-metadata` option, which takes as its argument an XML file+with [Dublin Core elements].++The second way is to use YAML, either in a+[YAML metadata block][Extension: `yaml_metadata_block`] in a Markdown+document, or in a separate YAML file specified with `--metadata-file`.+Here is an example of a YAML metadata block with EPUB metadata:++    ---+    title:+    - type: main+      text: My Book+    - type: subtitle+      text: An investigation of metadata+    creator:+    - role: author+      text: John Smith+    - role: editor+      text: Sarah Jones+    identifier:+    - scheme: DOI+      text: doi:10.234234.234/33+    publisher:  My Press+    rights: © 2007 John Smith, CC BY-NC+    ibooks:+      version: 1.3.4+    ...++The following fields are recognized:++`identifier`+  ~ 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 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+    `type`, or a list of such objects.  Valid values for `type` are+    `main`, `subtitle`, `short`, `collection`, `edition`, `extended`.++`creator`+  ~ Either a string value, or an object with fields `role`, `file-as`,+    and `text`, or a list of such objects.  Valid values for `role` are+    [MARC relators], but+    pandoc will attempt to translate the human-readable versions+    (like "author" and "editor") to the appropriate marc relators.++`contributor`+  ~ Same format as `creator`.++`date`+  ~ A string value in `YYYY-MM-DD` format.  (Only the year is necessary.)+    Pandoc will attempt to convert other common date formats.++`lang` (or legacy: `language`)+  ~ A string value in [BCP 47] format.  Pandoc will default to the local+    language if nothing is specified.++`subject`+  ~ Either a string value, or an object with fields `text`, `authority`,+    and `term`, or a list of such objects. Valid values for `authority`+    are either a [reserved authority value] (currently `AAT`, `BIC`,+    `BISAC`, `CLC`, `DDC`, `CLIL`, `EuroVoc`, `MEDTOP`, `LCSH`, `NDC`,+    `Thema`, `UDC`, and `WGS`) or an absolute IRI identifying a custom+    scheme. Valid values for `term` are defined by the scheme.++`description`+  ~ A string value.++`type`+  ~ A string value.++`format`+  ~ A string value.++`relation`+  ~ A string value.++`coverage`+  ~ A string value.++`rights`+  ~ A string value.++`belongs-to-collection`+  ~ A string value.  Identifies the name of a collection to which+    the EPUB Publication belongs.++`group-position`+  ~ The `group-position` field indicates the numeric position in which+    the EPUB Publication belongs relative to other works belonging to+    the same `belongs-to-collection` field.++`cover-image`+  ~ A string value (path to cover image).++`css` (or legacy: `stylesheet`)+  ~ A string value (path to CSS stylesheet).++`page-progression-direction`+  ~ Either `ltr` or `rtl`. Specifies the `page-progression-direction`+    attribute for the [`spine` element].++`accessModes`+  ~ An array of strings ([schema][accessibility schema]).+    Defaults to `["textual"]`.++`accessModeSufficient`+  ~ An array of strings ([schema][accessibility schema]).+    Defaults to `["textual"]`.++`accessibilityHazards`+  ~ An array of strings ([schema][accessibility schema]).+    Defaults to `["none"]`.++`accessibilityFeatures`+  ~ An array of strings ([schema][accessibility schema]).+    Defaults to++        - "alternativeText"+        - "readingOrder"+        - "structuralNavigation"+        - "tableOfContents"++`accessibilitySummary`+  ~ A string value.++`ibooks`+  ~ iBooks-specific metadata, with the following fields:++    - `version`: (string)+    - `specified-fonts`: `true`|`false` (default `false`)+    - `ipad-orientation-lock`: `portrait-only`|`landscape-only`+    - `iphone-orientation-lock`: `portrait-only`|`landscape-only`+    - `binding`: `true`|`false` (default `true`)+    - `scroll-axis`: `vertical`|`horizontal`|`default`++[accessibility schema]:  https://kb.daisy.org/publishing/docs/metadata/schema.org/index.html+[MARC relators]: https://loc.gov/marc/relators/relaterm.html+[reserved authority value]: https://idpf.github.io/epub-registries/authorities/+[`spine` element]: http://idpf.org/epub/301/spec/epub-publications.html#sec-spine-elem++## The `epub:type` attribute++For `epub3` output, you can mark up the heading that corresponds to an EPUB+chapter using the [`epub:type` attribute][epub-type]. For example, to set+the attribute to the value `prologue`, use this Markdown:++    # My chapter {epub:type=prologue}++Which will result in:++    <body epub:type="frontmatter">+      <section epub:type="prologue">+        <h1>My chapter</h1>++Pandoc will output `<body epub:type="bodymatter">`, unless+you use one of the following values, in which case either+`frontmatter` or `backmatter` will be output.++`epub:type` of first section      `epub:type` of body+----------------------------      ------------------+prologue                          frontmatter+abstract                          frontmatter+acknowledgments                   frontmatter+copyright-page                    frontmatter+dedication                        frontmatter+credits                           frontmatter+keywords                          frontmatter+imprint                           frontmatter+contributors                      frontmatter+other-credits                     frontmatter+errata                            frontmatter+revision-history                  frontmatter+titlepage                         frontmatter+halftitlepage                     frontmatter+seriespage                        frontmatter+foreword                          frontmatter+preface                           frontmatter+frontispiece                      frontmatter+appendix                          backmatter+colophon                          backmatter+bibliography                      backmatter+index                             backmatter++[epub-type]: http://www.idpf.org/epub/31/spec/epub-contentdocs.html#sec-epub-type-attribute++## Linked media++By default, pandoc will download media referenced from any `<img>`, `<audio>`,+`<video>` or `<source>` element present in the generated EPUB,+and include it in the EPUB container, yielding a completely+self-contained EPUB.  If you want to link to external media resources+instead, use raw HTML in your source and add `data-external="1"` to the tag+with the `src` attribute.  For example:++    <audio controls="1">+      <source src="https://example.com/music/toccata.mp3"+              data-external="1" type="audio/mpeg">+      </source>+    </audio>++If the input format already is HTML then `data-external="1"` will work+as expected for `<img>` elements. Similarly, for Markdown, external+images can be declared with `![img](url){external=1}`. Note that this+only works for images; the other media elements have no native+representation in pandoc's AST and require the use of raw HTML.++## EPUB styling++By default, pandoc will include some basic styling+contained in its `epub.css` data file.  (To see this,+use `pandoc --print-default-data-file epub.css`.)+To use a different CSS file, just use the `--css` command+line option.  A few inline styles are defined in addition; these+are essential for correct formatting of pandoc's HTML output.++The `document-css` variable may be set if the more opinionated+styling of pandoc's default HTML templates is desired (and+in that case the variables defined in [Variables for HTML] may+be used to fine-tune the style).++# Chunked HTML++`pandoc -t chunkedhtml` will produce a zip archive of linked+HTML files, one for each section of the original document.+Internal links will automatically be adjusted to point to+the right place, images linked to under the working directory+will be incorporated, and navigation links will be added.+In addition, a JSON file `sitemap.json` will be included+describing the hierarchical structure of the files.++If an output file without an extension is specified, then+it will be interpreted as a directory and the zip archive+will be automatically unpacked into it (unless it already+exists, in which case an error will be raised).  Otherwise+a `.zip` file will be produced.++The navigation links can be customized by adjusting the+template.  By default, a table of contents is included only+on the top page. To include it on every page, set the+`toc` variable manually.++# Jupyter notebooks++When creating a [Jupyter notebook], pandoc will try to infer the+notebook structure.  Code blocks with the class `code` will be+taken as code cells, and intervening content will be taken as+Markdown cells.  Attachments will automatically be created for+images in Markdown cells. Metadata will be taken from the+`jupyter` metadata field.  For example:++````+---+title: My notebook+jupyter:+  nbformat: 4+  nbformat_minor: 5+  kernelspec:+     display_name: Python 2+     language: python+     name: python2+  language_info:+     codemirror_mode:+       name: ipython+       version: 2+     file_extension: ".py"+     mimetype: "text/x-python"+     name: "python"+     nbconvert_exporter: "python"+     pygments_lexer: "ipython2"+     version: "2.7.15"+---++# Lorem ipsum++**Lorem ipsum** dolor sit amet, consectetur adipiscing elit. Nunc luctus+bibendum felis dictum sodales.++``` code+print("hello")+```++## Pyout++``` code+from IPython.display import HTML+HTML("""+<script>+console.log("hello");+</script>+<b>HTML</b>+""")+```++## Image++This image ![image](myimage.png) will be+included as a cell attachment.+````++If you want to add cell attributes, group cells differently, or+add output to code cells, then you need to include divs to+indicate the structure. You can use either [fenced+divs][Extension: `fenced_divs`] or [native divs][Extension:+`native_divs`] for this.  Here is an example:++````+:::::: {.cell .markdown}+# Lorem++**Lorem ipsum** dolor sit amet, consectetur adipiscing elit. Nunc luctus+bibendum felis dictum sodales.+::::::++:::::: {.cell .code execution_count=1}+``` {.python}+print("hello")+```++::: {.output .stream .stdout}+```+hello+```+:::+::::::++:::::: {.cell .code execution_count=2}+``` {.python}+from IPython.display import HTML+HTML("""+<script>+console.log("hello");+</script>+<b>HTML</b>+""")+```++::: {.output .execute_result execution_count=2}+```{=html}+<script>+console.log("hello");+</script>+<b>HTML</b>+hello+```+:::+::::::+````++If you include raw HTML or TeX in an output cell, use the+[raw attribute](#extension-raw_attribute), as shown+in the last cell of the example above.  Although pandoc can+process "bare" raw HTML and TeX, the result is often+interspersed raw elements and normal textual elements, and+in an output cell pandoc expects a single, connected raw+block.  To avoid using raw HTML or TeX except when+marked explicitly using raw attributes, we recommend+specifying the extensions `-raw_html-raw_tex+raw_attribute` when+translating between Markdown and ipynb notebooks.++Note that options and extensions that affect reading and+writing of Markdown will also affect Markdown cells in ipynb+notebooks.  For example, `--wrap=preserve` will preserve+soft line breaks in Markdown cells; `--markdown-headings=setext` will+cause Setext-style headings to be used; and `--preserve-tabs` will+prevent tabs from being turned to spaces.++# Vimdoc++Vimdoc writer generates Vim help files and makes use of the following metadata+variables:++``` yaml+abstract: "A short description"+author: Author+title: Title++# Vimdoc-specific+filename: "definition-lists.txt"+vimdoc-prefix: pandoc+```++Complete header requires `abstract`, `author`, `title` and `filename` to+be set. Compiling file with such metadata produces the following file+(assumes `--standalone`, see [Templates]):++``` vimdoc+*definition-lists.txt*  A short description++                            Title by Author+++                                 Type |gO| to see the table of contents.++[...]++ vim:tw=72:sw=4:ts=4:ft=help:norl:et:+```++If `vimdoc-prefix` is set, all non-command tags are prefixed with its+value, it is used to prevent tag collision: all headers have a tag+(either inferred or explicit) and multiple help pages can have the same+header names, therefore collision is to be expected. Let our input be+the following markdown file:++``` markdown+## Header++`:[range]Fnl {expr}`{#:Fnl}+:   Evaluates {expr} or range++`vim.b`{#vim.b}+:   Buffer-scoped (`:h b:`) variables for the current buffer. Invalid or unset+    key returns `nil`. Can be indexed with an integer to access variables for a+    specific buffer.++[Span]{#span}+:   generic inline container for phrasing content, which does not inherently+    represent anything.+```++Convert it to vimdoc:++``` vimdoc+------------------------------------------------------------------------+Header                                                            *header*++:[range]Fnl {expr}                                                  *:Fnl*+    Evaluates {expr} or range+`vim.b`                                                            *vim.b*+    Buffer-scoped (|b:|) variables for the current buffer. Invalid or+    unset key returns `nil`. Can be indexed with an integer to access+    variables for a specific buffer.+Span                                                                *span*+    generic inline container for phrasing content, which does not+    inherently represent anything.+```++Convert it to vimdoc with metadata variable set (e.g. with+`-M vimdoc-prefix=pandoc`)++``` vimdoc+------------------------------------------------------------------------+Header                                                     *pandoc-header*++:[range]Fnl {expr}                                                  *:Fnl*+    Evaluates {expr} or range+`vim.b`                                                     *pandoc-vim.b*+    Buffer-scoped (|b:|) variables for the current buffer. Invalid or+    unset key returns `nil`. Can be indexed with an integer to access+    variables for a specific buffer.+Span                                                         *pandoc-span*+    generic inline container for phrasing content, which does not+    inherently represent anything.+```++`vim.b` and `Span` got their prefixes but not `:Fnl` because ex-commands+(those starting with `:`) don't get a prefix, since they are considered+unique across help pages.++In both cases `:help b:` became reference `|b:|` (also works with+`:h b:`). Links pointing to either <https://vimhelp.org/> or+<https://neovim.io/doc/user> become references too.++Vim traditionally wraps at 78, but Pandoc defaults to 72. Use+`--columns 78` to match Vim.++# Syntax highlighting++Pandoc will automatically highlight syntax in [fenced code blocks] that+are marked with a language name.  The Haskell library [skylighting] is+used for highlighting. Currently highlighting is supported only for+HTML, EPUB, Docx, Ms, Man, Typst, and LaTeX/PDF output. To see a list+of language names that pandoc will recognize, type `pandoc+--list-highlight-languages`.++The color scheme can be selected using the `--syntax-highlighting`+option. The default color scheme is `pygments`, which imitates the+default color scheme used by the Python library pygments (though+pygments is not actually used to do the highlighting). To see a+list of highlight styles, type `pandoc --list-highlight-styles`.++If you are not satisfied with the predefined styles, you can use+`--print-highlight-style` to generate a JSON `.theme` file which+can be modified and used as the argument to+`--syntax-highlighting`. To get a JSON version of the `pygments`+style, for example:++    pandoc -o my.theme --print-highlight-style pygments++Then edit `my.theme` and use it like this:++    pandoc --syntax-highlighting my.theme++If you are not satisfied with the built-in highlighting, or you+want to highlight a language that isn't supported, you can use the+`--syntax-definition` option to load a [KDE-style XML syntax definition+file](https://docs.kde.org/stable5/en/kate/katepart/highlight.html).+Before writing your own, have a look at KDE's [repository of syntax+definitions](https://github.com/KDE/syntax-highlighting/tree/master/data/syntax).++If you receive an error that pandoc "Could not read highlighting theme",+check that the JSON file is encoded with UTF-8 and has no Byte-Order Mark (BOM).++To disable highlighting, use `--syntax-highlighting=none`.++To use a format's idiomatic syntax highlighting instead of+pandoc's built-in highlighting, use `--syntax-highlighting=idiomatic`.+Currently, `idiomatic` only affects the following formats:++- In reveal.js, it causes reveal.js's highlighting plugin to be+  used for source code highlighting.  The style may be customized+  by setting the `highlightjs-theme` variable.++- In Typst, it causes Typst's built-in highlighting to be used.+  (This is also the default for Typst.)++- In LaTeX, it causes the [`listings`][] package  to be used. Note that+  `listings` does not support multi-byte encoding for source code. To handle+  UTF-8 you would need to use a custom template. This issue is fully+  documented here: [Encoding issue with the listings package][].++- In other formats, `idiomatic` will have the same result as `default`.++[skylighting]: https://github.com/jgm/skylighting++# Custom Styles++Custom styles can be used in the docx, odt and ICML formats.++## Output++By default, pandoc's odt, docx and ICML output applies a predefined set of+styles for blocks such as paragraphs and block quotes, and uses largely+default formatting (italics, bold) for inlines. This will work for most+purposes, especially alongside a [reference doc](#option--reference-doc) file.+However, if you need to apply your own styles to blocks, or match a preexisting+set of styles, pandoc allows you to define custom styles for blocks and text+using `div`s and `span`s, respectively.++If you define a Div, Span, or Table with the attribute+`custom-style`, pandoc will apply your specified style to the+contained elements (with the exception of elements whose function+depends on a style, like headings, code blocks, block quotes, or+links). So, for example, using the `bracketed_spans` syntax,++    [Get out]{custom-style="Emphatically"}, he said.++would produce a file with "Get out" styled with character+style `Emphatically`. Similarly, using the `fenced_divs` syntax,++    Dickinson starts the poem simply:++    ::: {custom-style="Poetry"}+    | A Bird came down the Walk---+    | He did not know I saw---+    :::++would style the two contained lines with the `Poetry` paragraph style.++Styles will be defined in the output file as inheriting+from normal text (docx) or Default Paragraph Style (odt), if the+styles are not yet in your [reference doc](#option--reference-doc).+If they are already defined, pandoc will not alter the definition.++This feature allows for greatest customization in conjunction with+[pandoc filters]. If you want all paragraphs after block quotes to be+indented, you can write a filter to apply the styles necessary. If you+want all italics to be transformed to the `Emphasis` character style+(perhaps to change their color), you can write a filter which will+transform all italicized inlines to inlines within an `Emphasis`+custom-style `span`.++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++## Input++The docx reader, by default, only reads those styles that it can+convert into pandoc elements, either by direct conversion or+interpreting the derivation of the input document's styles.++By enabling the [`styles` extension](#ext-styles) in the docx reader+(`-f docx+styles`), you can produce output that maintains the styles+of the input document, using the `custom-style` class. A `custom-style`+attribute will be added for each style. Divs will be created to+hold the paragraph styles, and Spans to hold the character styles.+Table styles will be applied directly to the Table.++For example, using the `custom-style-reference.docx` file in the test+directory, we have the following different outputs:++Without the `+styles` extension:++    $ pandoc test/docx/custom-style-reference.docx -f docx -t markdown+    This is some text.++    This is text with an *emphasized* text style. And this is text with a+    **strengthened** text style.++    > Here is a styled paragraph that inherits from Block Text.++And with the extension:++    $ pandoc test/docx/custom-style-reference.docx -f docx+styles -t markdown++    ::: {custom-style="First Paragraph"}+    This is some text.+    :::++    ::: {custom-style="Body Text"}+    This is text with an [emphasized]{custom-style="Emphatic"} text style.+    And this is text with a [strengthened]{custom-style="Strengthened"}+    text style.+    :::++    ::: {custom-style="My Block Style"}+    > Here is a styled paragraph that inherits from Block Text.+    :::++With these custom styles, you can use your input document as a+reference-doc while creating docx output (see below), and maintain the+same styles in your input and output files.++# Custom readers and writers++Pandoc can be extended with custom readers and writers written+in [Lua].  (Pandoc includes a Lua interpreter, so Lua need not+be installed separately.)++To use a custom reader or writer, simply specify the path to the+Lua script in place of the input or output format. For example:++    pandoc -t data/sample.lua+    pandoc -f my_custom_markup_language.lua -t latex -s++If the script is not found relative to the working directory,+it will be sought in the `custom` subdirectory of the user data+directory (see `--data-dir`).++A custom reader is a Lua script that defines one function,+Reader, which takes a string as input and returns a Pandoc+AST.  See the [Lua filters documentation] for documentation+of the functions that are available for creating pandoc+AST elements.  For parsing, the [lpeg] parsing library+is available by default. To see a sample custom reader:++    pandoc --print-default-data-file creole.lua++If you want your custom reader to have access to reader options+(e.g. the tab stop setting), you give your Reader function a+second `options` parameter.++A custom writer is a Lua script that defines a function+that specifies how to render each element in a Pandoc AST.+See the [djot-writer.lua] for a full-featured example.++Note that custom writers have no default template.  If you want+to use `--standalone` with a custom writer, you will need to+specify a template manually using `--template` or add a new+default template with the name+`default.NAME_OF_CUSTOM_WRITER.lua` to the `templates`+subdirectory of your user data directory (see [Templates]).++[Lua]: https://www.lua.org+[lpeg]:  http://www.inf.puc-rio.br/~roberto/lpeg/+[djot-writer.lua]: https://github.com/jgm/djot.lua/blob/main/djot-writer.lua++# Reproducible builds++Some of the document formats pandoc targets (such as EPUB,+docx, and ODT) include build timestamps in the generated document.+That means that the files generated on successive builds will+differ, even if the source does not.  To avoid this, set the+`SOURCE_DATE_EPOCH` environment variable, and the timestamp will+be taken from it instead of the current time.+`SOURCE_DATE_EPOCH` should contain an integer unix timestamp+(specifying the number of seconds since midnight UTC January 1, 1970).++For reproducible builds with LaTeX, you can either specify the+`pdf-trailer-id` in the metadata or leave it undefined, in which+case pandoc will create a trailer-id based on a hash of the+`SOURCE_DATE_EPOCH` and the document's contents.++Some document formats also include a unique identifier.  For+EPUB, this can be set explicitly by setting the `identifier`+metadata field (see [EPUB Metadata], above).++# Accessible PDFs and PDF archiving standards++PDF is a flexible format, and using PDF in certain contexts+requires additional conventions. For example, PDFs are not+accessible by default; they define how characters are placed on a+page but do not contain semantic information on the content.+However, it is possible to generate accessible PDFs, which use+tagging to add semantic information to the document.++Pandoc defaults to LaTeX to generate PDF. LaTeX's `\DocumentMetadata`+interface supports PDF standards and tagging when using LuaLaTeX;+set the `pdfstandard` variable to enable this (see below). For older+LaTeX installations, alternative engines must be used.++The PDF standards PDF/A and PDF/UA define further restrictions+intended to optimize PDFs for archiving and accessibility. Tagging+is commonly used in combination with these standards to ensure+best results.++Note, however, that standard compliance depends on many things,+including the colorspace of embedded images. Pandoc cannot check+this, and external programs must be used to ensure that generated+PDFs are in compliance.++## LaTeX++Set the `pdfstandard` variable to produce tagged PDFs conforming+to PDF/A, PDF/X, or PDF/UA standards. For example:++    pandoc -V pdfstandard=ua-2 --pdf-engine=lualatex doc.md -o doc.pdf++Multiple standards can be combined:++    ---+    pdfstandard:+      - ua-2+      - a-4f+    ---++The required PDF version is inferred automatically. This feature+requires LuaLaTeX in TeX Live 2025 with LaTeX kernel 2025-06-01+or newer.++## ConTeXt++ConTeXt always produces tagged PDFs, but the quality depends on+the input. The default ConTeXt markup generated by pandoc is+optimized for readability and reuse, not tagging. Enable the+[`tagging`](#extension--tagging) format extension to force markup+that is optimized for tagging. For example:++    pandoc -t context+tagging doc.md -o doc.pdf++A recent `context` version should be used, as older versions+contained a bug that lead to invalid PDF metadata.++## WeasyPrint++The HTML-based engine WeasyPrint includes experimental support for+PDF/A and PDF/UA since version 57. Tagged PDFs can created with++    pandoc --pdf-engine=weasyprint \+           --pdf-engine-opt=--pdf-variant=pdf/ua-1 ...++The feature is experimental and standard compliance should not be+assumed.++## Prince XML++The non-free HTML-to-PDF converter `prince` has extensive support+for various PDF standards as well as tagging. E.g.:++    pandoc --pdf-engine=prince \+           --pdf-engine-opt=--tagged-pdf ...++See the prince documentation for more info.++## Typst++Typst 0.12 can produce PDF/A-2b:++    pandoc --pdf-engine=typst --pdf-engine-opt=--pdf-standard=a-2b ...++## Word Processors++Word processors like LibreOffice and MS Word can also be used to+generate standardized and tagged PDF output. Pandoc does not+support direct conversions via these tools. However, pandoc can+convert a document to a `docx` or `odt` file, which can then be+opened and converted to PDF with the respective word processor.+See the documentation for [Word][word-accessible-pdfs] and+[LibreOffice][lo-pdf-export].++[word-accessible-pdfs]: https://support.microsoft.com/en-us/office/create-accessible-pdfs-064625e0-56ea-4e16-ad71-3aa33bb4b7ed+[lo-pdf-export]: https://help.libreoffice.org/latest/en-US/text/shared/01/ref_pdf_export_general.html+++# Running pandoc as a web server++If you rename (or symlink) the pandoc executable to+`pandoc-server`, or if you call pandoc with `server` as the first+argument, it will start up a web server with a JSON API. This+server exposes most of the conversion functionality of pandoc. For+full documentation, see the [pandoc-server] man page.++If you rename (or symlink) the pandoc executable to+`pandoc-server.cgi`, it will function as a CGI program+exposing the same API as `pandoc-server`.++`pandoc-server` is designed to be maximally secure; it uses+Haskell's type system to provide strong guarantees that no I/O+will be performed on the server during pandoc conversions.++[pandoc-server]: https://github.com/jgm/pandoc/blob/master/doc/pandoc-server.md++# Running pandoc as a Lua interpreter++Calling the pandoc executable under the name `pandoc-lua` or with+`lua` as the first argument will make it function as a standalone+Lua interpreter. The behavior is mostly identical to that of the+[standalone `lua` executable][lua standalone], version 5.4.+All `pandoc.*` packages, as well as the packages `re` and `lpeg`,+are available via global variables. Furthermore, the globals+`PANDOC_VERSION`, `PANDOC_STATE`, and `PANDOC_API_VERSION` are+set at startup. For full documentation, see the [pandoc-lua] man page.++[lua standalone]: https://www.lua.org/manual/5.4/manual.html#7+[pandoc-lua]: https://github.com/jgm/pandoc/blob/master/doc/pandoc-lua.md++# A note on security++1. Although pandoc itself will not create or modify any files other+   than those you explicitly ask it create (with the exception+   of temporary files used in producing PDFs), a filter or custom+   writer could in principle do anything on your file system. Please+   audit filters and custom writers very carefully before using them.++2. Several input formats (including LaTeX, Org, RST, and Typst)+   support `include` directives that allow the contents of a file to be+   included in the output. An untrusted attacker could use these+   to view the contents of files on the file system. (Using the+   `--sandbox` option can protect against this threat.)++3. Several output formats (including RTF, FB2, HTML with+   `--self-contained`, EPUB, Docx, and ODT) will embed encoded+   or raw images into the output file.  An untrusted attacker+   could exploit this to view the contents of non-image files on the+   file system.  (Using the `--sandbox` option can protect+   against this threat, but will also prevent including images in+   these formats.)++4. In reading HTML files, pandoc will attempt to include the+   contents of `iframe` elements by fetching content from the+   local file or URL specified by `src`. If untrusted HTML is+   processed on a server, this has the potential to reveal anything+   readable by the process running the server. Using the `-f html+raw_html`+   will mitigate this threat by causing the whole `iframe`+   to be parsed as a raw HTML block. Using `--sandbox` will also+   protect against the threat.++5. If your application uses pandoc as a Haskell library (rather than+   shelling out to the executable), it is possible to use it in a mode+   that fully isolates pandoc from your file system, by running the+   pandoc operations in the `PandocPure` monad. See the document+   [Using the pandoc API](https://pandoc.org/using-the-pandoc-api.html)+   for more details. (This corresponds to the use of the `--sandbox`+   option on the command line.)++6. Pandoc's parsers can exhibit pathological performance on some+   corner cases.  It is wise to put any pandoc operations under+   a timeout, to avoid DOS attacks that exploit these issues.+   If you are using the pandoc executable, you can add the+   command line options `+RTS -M512M -RTS` (for example) to limit+   the heap size to 512MB.  Note that the `commonmark` parser+   (including `commonmark_x` and `gfm`) is much less vulnerable+   to pathological performance than the `markdown` parser, so+   it is a better choice when processing untrusted input.++7. The HTML generated by pandoc is not guaranteed to be safe.+   If `raw_html` is enabled for the Markdown input, users can+   inject arbitrary HTML.  Even if `raw_html` is disabled,+   users can include dangerous content in URLs and attributes.+   To be safe, you should run all HTML generated from untrusted+   user input through an HTML sanitizer.++# Authors++Copyright 2006--2024 John MacFarlane (jgm@berkeley.edu). Released under the [GPL], version 2 or greater.  This software carries no warranty of any kind.  (See COPYRIGHT for full copyright and warranty notices.) For a full list of contributors, see the file
README.md view
@@ -28,6 +28,7 @@  <div id="input-formats"> +- `asciidoc` ([AsciiDoc](https://asciidoc.org/) markup) - `bibtex` ([BibTeX](https://ctan.org/pkg/bibtex) bibliography) - `biblatex` ([BibLaTeX](https://ctan.org/pkg/biblatex) bibliography) - `bits` ([BITS](https://jats.nlm.nih.gov/extensions/bits/) XML, alias@@ -81,11 +82,18 @@ - `mediawiki` ([MediaWiki   markup](https://www.mediawiki.org/wiki/Help:Formatting)) - `man` ([roff man](https://man.cx/groff_man(7)))+- `mdoc` ([mdoc](https://mandoc.bsd.lv/man/mdoc.7.html) manual page+  markup) - `muse` ([Muse](https://amusewiki.org/library/manual)) - `native` (native Haskell)-- `odt` ([ODT](https://en.wikipedia.org/wiki/OpenDocument))-- `opml` ([OPML](http://dev.opml.org/spec2.html))+- `odt` ([OpenDocument text+  document](https://en.wikipedia.org/wiki/OpenDocument))+- `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))+- `pptx`+  ([PowerPoint](https://en.wikipedia.org/wiki/Microsoft_PowerPoint)) - `ris` ([RIS](https://en.wikipedia.org/wiki/RIS_(file_format))   bibliography) - `rtf` ([Rich Text@@ -100,6 +108,9 @@   markup](https://twiki.org/cgi-bin/view/TWiki/TextFormattingRules)) - `typst` ([typst](https://typst.app)) - `vimwiki` ([Vimwiki](https://vimwiki.github.io))+- `xlsx` ([Excel+  spreadsheet](https://en.wikipedia.org/wiki/Microsoft_Excel#File_formats))+- `xml` (XML version of native AST) - the path of a custom Lua reader, see [Custom readers and   writers](https://pandoc.org/MANUAL.html#custom-readers-and-writers)   below@@ -110,12 +121,25 @@  <div id="output-formats"> -- `asciidoc` (modern [AsciiDoc](https://www.methods.co.nz/asciidoc/) as-  interpreted by [AsciiDoctor](https://asciidoctor.org/))-- `asciidoc_legacy` ([AsciiDoc](https://www.methods.co.nz/asciidoc/) as-  interpreted by+- `ansi` (text with [ANSI escape+  codes](https://en.wikipedia.org/wiki/ANSI_escape_code), for terminal+  viewing)+- `asciidoc` (modern [AsciiDoc](https://asciidoc.org/) as interpreted by+  [AsciiDoctor](https://asciidoctor.org/))+- `asciidoc_legacy` ([AsciiDoc](https://asciidoc.org/) as interpreted by   [`asciidoc-py`](https://github.com/asciidoc-py/asciidoc-py)). - `asciidoctor` (deprecated synonym for `asciidoc`)+- `bbcode` [BBCode](https://www.bbcode.org/reference.php)+- `bbcode_fluxbb` [BBCode+  (FluxBB)](https://web.archive.org/web/20210623155046/https://fluxbb.org/forums/help.php#bbcode)+- `bbcode_phpbb` [BBCode+  (phpBB)](https://www.phpbb.com/community/help/bbcode)+- `bbcode_steam` [BBCode+  (Steam)](https://steamcommunity.com/comment/ForumTopic/formattinghelp)+- `bbcode_hubzilla` [BBCode+  (Hubzilla)](https://hubzilla.org/help/member/bbcode)+- `bbcode_xenforo` [BBCode+  (xenForo)](https://www.xenfocus.com/community/help/bb-codes/) - `beamer` ([LaTeX beamer](https://ctan.org/pkg/beamer) slide show) - `bibtex` ([BibTeX](https://ctan.org/pkg/bibtex) bibliography) - `biblatex` ([BibLaTeX](https://ctan.org/pkg/biblatex) bibliography)@@ -150,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@@ -180,10 +204,11 @@ - `ms` ([roff ms](https://man.cx/groff_ms(7))) - `muse` ([Muse](https://amusewiki.org/library/manual)) - `native` (native Haskell)-- `odt` ([OpenOffice text+- `odt` ([OpenDocument text   document](https://en.wikipedia.org/wiki/OpenDocument))-- `opml` ([OPML](http://dev.opml.org/spec2.html))-- `opendocument` ([OpenDocument](http://opendocument.xml.org))+- `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)) - `pdf` ([PDF](https://www.adobe.com/pdf/)) - `plain` (plain text)@@ -208,6 +233,9 @@   slide show) - `tei` ([TEI Simple](https://github.com/TEIC/TEI-Simple)) - `typst` ([typst](https://typst.app))+- `vimdoc`+  ([Vimdoc](https://vimhelp.org/helphelp.txt.html#help-writing))+- `xml` (XML version of native AST) - `xwiki` ([XWiki   markup](https://www.xwiki.org/xwiki/bin/view/Documentation/UserGuide/Features/XWikiSyntax/)) - `zimwiki` ([ZimWiki@@ -254,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 @@ -265,7 +294,7 @@  ## License -© 2006-2023 John MacFarlane (jgm@berkeley.edu). Released under the+© 2006-2024 John MacFarlane (jgm@berkeley.edu). Released under the [GPL](https://www.gnu.org/licenses/old-licenses/gpl-2.0.html "GNU General Public License"), version 2 or greater. This software carries no warranty of any kind. (See COPYRIGHT for full copyright and warranty notices.)
benchmark/benchmark-pandoc.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE OverloadedStrings #-} {--Copyright (C) 2012-2023 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2012-2024 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
changelog.md view
@@ -1,2307 +1,6049 @@ # Revision history for pandoc -## pandoc 3.1.13 (2024-04-07)--  * Org reader:--    + Fix treatment of `id` property under heading (#9639).--  * DocBook reader:--    + Add empty title to admonition div if not present (#9569).-      This allows admonition elements (e.g. `<note>`) to work with-      `gfm` admonitions even if the `<title>` is not present.--  * DokuWiki reader:--    + Link text cannot contain formatting (e.g., `//` is not italics) (#9630).-    + An explicitly empty link text (`[[url|]]`) works the same as an omitted-      link text (#9632).--  * Typst reader:--    + Support Typst 0.11 table features: col/rowspans, table head-      and foot (#9588).-    + Parse cell col/rowspans.--  * CSLJson writer:--    + Put `$` or `$$` around math in `csljson` output (#9616).--  * ConTeXt writer:--    + Fix options order with `\externalfigure`. The dimensions should-      come before the class if both are present.--  * Typst writer:--    + Put label after Span, not before. Labels get applied to preceding markup-      item.-    + Support Typst 0.11 table features (#9588): colspans, rowspans,-      cell alignment overrides, relative column widths,-      header and footer, multiple table bodies with intermediate headers.-      Row heads are not yet supported.-    + The default typst template has been modified so that tables-      don't have lines by default. As is standard with pandoc, we only-      add a line under a header or over a footer. However, a different-      default stroke pattern can easily be added in a template.-    + More reliable escaping in inline `[..]` contexts (#9586). For example,-      we need to escape `[\1. April]` or it will be treated as an ordered list.-    + Handle `unnumbered` on headings (#9585).--  * LaTeX writer:--    + Fix math inside strikeout (#9597).--  * Text.Pandoc.Writers.Shared:--    + Export `isOrderedListMarker` [API change].--  * Change lhs tests so they don't use `--standalone`.-    This will avoid test failures due to minor changes in-    skylighting versions, e.g. #9589.--  * Use latest texmath, typst.--  * Require pandoc-lua-marshal 0.2.6 (#9613, Albert Krewinkel).-    Fixes an issue arising when the value of `content` properties-    on *BlockQuote*, *Figure*, and *Div* elements was an empty list.--  * Update lua-filters.md (#9611, Carlos Scheidegger).---## pandoc 3.1.12.3 (2024-03-17)--  * Markdown reader: Fix bug with footnotes at end of fenced div (#9576).--  * LaTeX reader:--    + Improve tokenization of `@` (#9555). Make tokenization sensitive to-      `\makeatletter`/`\makeatother`. Previously we just always treated-      `@` as a letter.  This led to bad results, e.g. with the sequence `\@`.-      E.g., `a\@ b` would parse as "ab" and `a\@b` as "a".-    + Make `withRaw` work inside `parseFromToks` (#9517).-      This is needed for raw environments to work inside table cells.-    + Better handling of table colwidths (#9579). Previously the parser just-      failed if the column width specified in `p{}` wasn't a multiple of-      `\linewidth`. This led to cases where content was skipped.--  * Typst writer:--    + Add 'kind' parameter to figures with tables (#9574).-    + Avoid unnecessary box around image in figure (#9236).-    + Omit width/height in images unless explicitly specified (#9236).-      Previously we computed width/heigth for images that didn't have-      size information, because otherwise typst would expand the image-      to fit page width. This typst behavior has changed in 0.11.-      This change fixes a bug in which images would sometimes overflow-      page margins, depending on their intrinsic size.-    + Don't add hard-coded `inset` to tables (#9580). Instead, set this-      globally in the default template, allowing it to be customized.--  * LaTeX template: Fix block headings support for unnumbered paragraphs-    (#9542, #6018, Oliver Fabel).--  * HTML templates: Replace polyfill provider (#9537, @SukkaW).-    Replace polyfill.io with cdnjs.cloudflare.com/polyfill.-    polyfill.io has been acquired by Funnull, and the service has-    become unstable.--  * Korean translations: delete colon in translation for 'to'.-    This was invalid YAML, and not desired anyway, since a colon-    is added.--  * Use latest commonmark, commonmark-extensions.-    This fixes a 3.12 regression in parsing of commonmark/gfm autolinks-    (jgm/commonmark-hs#151).--  * Depend on djot 0.1.1.3, which fixes a serious parsing bug affecting-    regular paragraphs after lists.--  * Depend on latest skylighting, skylighting-core, typst-hs, texmath.--  * MANUAL.txt: Change broken link to IDML cookbook (#9563).--## pandoc 3.1.12.2 (2024-02-29)--  * Docx reader:--    + Ensure that table captions are counted (#9518).-    + Detect caption by style name not id (#9518).-      The styleId can change depending on the localization.-    + Avoid emitting empty paragraph where caption was.--  * Markdown reader: fix regression in link parsing with wikilinks extensions-    (#9481).  This fixes a regression introduced in 3.1.12.--  * Org reader/writer: support admonitions (#9475).--  * Org writer: omit extra blank line at end of quote block.--  * Typst writer: ensure that `-`, `+`, etc. are escaped at beginning of block-    (#9478). Our recent relaxing of escaping (#9386) caused problems for-    things like emphasized `-` characters that were rendered using-    `#strong[-]#`.  This now gets rendered as `#strong[\-]`.--  * LaTeX writer: fix bug when a language is specified in two different ways-    (#9472). If you used `lang: de-DE` but then had a span or div with-    `lang=de`, the preamble would try to load `ngerman` twice, leading-    to an error. This fix ensures that a language is only loaded once.--  * Docx writer: Don't copy over `footnotePr` in `settings.xml`-    from reference.docx (#9522).--  * EPUB writer: omit EPUB2-specific meta tag on EPUB3 (#9493).-    This caused a validation failure in epubs with cover images.--  * Lua: avoid crashing when an error message is not valid UTF-8 (Albert-    Krewinkel).--  * Text.Pandoc.SelfContained:--    + Add `role="img"` to svgs.-    + Add `aria-label` to svg elements with `alt` text if present.-      Screen readers ignore `alt` attributes on svg elements but do-      pay attention to `aria-label` (#9525).--  * Text.Pandoc.Shared: Fix regression in section numbering in-    `makeSections` (#9516). Starting with pandoc 3.1.12, unnumbered-    sections incremented the section number.--  * Text.Pandoc.Class: fix `openUrl` TLS negotiation (#9483).-    With the release of TLS 2.0.0, the TLS library started requiring-    Extended Main Secret for the TLS handshake. This caused problems-    connecting to zotero's server and others that do not support TLS 1.3.-    This commit relaxes this requirement.--  * Depend on djot 0.1.1.0 (fixes rendering on multiline block attributes).--  * Use new releases of skylighting-format-blaze-html (#9520).-    Fixes auto-wrapping of long source lines in HTML print media.--  * Use new commonmark-extensions (fixes issue with the-    `rebase_relative_paths` extension when used with commonmark/gfm.--  * Makefile: improve epub-validation target (#9493).-    Use `--epub-cover-image` to catch issues that only arise with that.--## pandoc 3.1.12.1 (2024-02-17)--  * EPUB writer: omit EPUBv3-specific accessibility features on epub2-    (#9469). Fixes a regression in 3.1.12.--  * More fixes for SVG ids with `--self-contained` (#9467).-    This generalizes the fix to #9420 so it applies to things like-    `style="fill(url(#..."` and should fix problems with SVGs including-    gradients.--  * Powerpoint writer: properly handle math in headings and tables (#9465).-    This ensures that paragraphs containing math are wrapped in-    a `mc:AlternateContent` node as required.--  * Makefile: make validate-epub check v2 output too.--## pandoc 3.1.12 (2024-02-14)--  * Add `djot` as input and output format. Djot is a light markup syntax-    (https://djot.net).--    + New module Text.Pandoc.Readers.Djot [API change]. The function-      `readDjot` is also exported by Text.Pandoc.Readers.-    + New module Text.Pandoc.Writers.Djot [API change]. The function-      `writeDjot` is also exported by Text.Pandoc.Writers.--  * `--number-sections` now uses the first digit for the number of-    the top-level section, no matter what its level. So if the top-level-    section is level-2, numbers will be `1`, `2`, etc. rather than-    `0.1`, `0.2`, as in the past (#5071). For some backwards compatibility,-    we revert to the old behavior when the `--number-offset` option is used.--  * DocBook reader:--    + Better handling of `<procedure>` and `<substeps>` (#9341):-      `<procedure>` now gets parsed as an ordered list, and-      `<substeps>` as a sublist.--  * Man reader:--    + Move spaces outside of emph/strong (#9445).--  * MediaWiki reader:--    + Don't make leading blanks underscores in image links (#9425).-    + Allow lowercase `image:` (#9424).--  * BibTeX reader:--    + Support `pagetotal` in converting BibLaTeX.--  * Markdown reader:--    + Fix wikilinks extensions to allow newlines in titles (#9454).--  * EPUB reader:--    + Don't put `#` characters in identifiers.--  * LaTeX reader:--    + Improve treatment of `\cref`, `\Cref` (#7463). Use the-      reference-type `ref+label` and `ref+Label`. Also, associate with-      `\vref` `ref` instead of `ref+page`.-    + Limited support for `\Cref` (#7463).-    + Generate relative widths for `\linewidth`, `\textheight` (#9388).--  * Typst reader:--    + Fix handling of `\overline` (#9294). Due to a typo, it was being-      incorrectly rendered as an `\underset`.-    + Improve handling of inline `#quote` (#9413).-    + Fix handling of `dot()`, `tilde()`, `ddot()` (jgm/typst-hs#38).-    + Fix character used for `norm` (jgm/typst-hs#38).--  * Typst writer:--    + Use reference form (e.g. `@jones2000[p. 30]`) for citations when-      possible.-    + Use `#ref` or `@` for links with `reference-type="ref"` (#7463).-      This attribute is added to LaTeX `\cref`, for example.-    + Improve citation support (#9452). Emit `form: "prose"` or `form: "year"`-      qualifiers if the citation is author-in-text or suppress-author.-      Strip initial comma from suffix, since typst will add an extra one.-    + Unescape URI escapes in image paths (#9389).-    + Handle labels and citaiton ids with spaces and other special-      characters (#9387). In these cases, we produce an explicit `label()`-      rather than using `<>` or `@`.-    + Avoid producing illegal labels (#9387).-    + Avoid unnecessary escapes (#9386).--  * LaTeX writer:--    + Make writer sensitive to `empty_paragraphs` extension (#9443).-    + Fix beamer highlighting (mh4ckt3mh4ckt1c4s).-    + Create valid table even when table is empty (#9350).-    + Set font fallback for babel main font (Max Heller).-    + Add some kerns where needed between quotes (#9371).--  * HTML writer:--    + Add suffix to multiple footnote section ids, so they are-      unique (Sam May). This is necessary when `--reference-location`-      is `block` or `section`.--  * EPUB writer:--    + Add ARA roles for accessibility (#9378, Iacobus1983).-      Footnote references are given role "doc-noteref", footnote text-      gets "doc-footnote", and nav gets "doc-toc".-    + Ensure that an alt attribute is always added (#9354). This seems to-      be required by iBooks; even an empty alt attribute will satisfy it.-    + Add `xml:lang` to package element (#9372).-    + Add accessibility metadata to EPUB metadata (#9372, #9400,-      Iacobus1983 and John MacFarlane). Reasonable default values are-      used to ensure that pandoc's EPUBs conform to the EU Accessibilty Act-      requirements, but values can be overridden using metadata.--  * Docx writer:--    + Restore ability to center-justify table (#9393). The fix to-      #5947 caused all tables to be left indented. This was necessary-      to avoid extra indentation in table cells when a table appeared-      in a list item. This change makes the changes conditional, so-      that they only affect tables in list items.--  * Man writer:--    + Fix bug with long URLs (#9458). URLs with more than 68 characters didn't-      display properly because of wrapping.-    + Support (limited) syntax highlighting in code blocks (#9446).-      Currently only boldface and italics are supported. The `monochrome`-      style might be of use for those generating man pages.--  * Org writer:--    + Escape special lines in code blocks (#9218, Albert Krewinkel).--  * Markdown writer:--    + Use different width fences for nested divs (#9450). Outer divs-      have longer fences. This aids clarity for the reader, making it-      easier to see where the div ends. It also makes the output-      compatible with some other implementations, e.g. micromark,-      which require different-width fences for nesting.-    + Fix output for pipe tables with a huge number-      of columns (#9346). Previously we got invalid pipe tables when the-      number of table columns exceeded the setting of `--columns`.--  * Powerpoint writer:--    + Fix regression in layout for slides with figures (#9442).-    + Use internal column widths in pptx writer tables (#5706,-      Tomas Dahlqvist). The table writer used to only divide all-      available width evenly for all columns. In this update the code-      uses the incoming widths if they are available. If they are not-      set the earlier even distribution is used. Some of the golden-      templates are adjusted slightly because of different rounding when-      using the new calculation model.--  * Custom writers:--    + Fix handling of common state (#9229, Albert Krewinkel).-      The CommonState (`PANDOC_STATE` in Lua) may change between the time that-      a custom writer script is first loaded and when the writer is run.-      However, the writer was always using the initial state, which led to-      problems, e.g. when the mediabag was updated in a filter, as those-      updates where not visible to the writer. The state is now updated-      right before the writer function runs.--  * Text.Pandoc.SelfContained:--    + Fix id replacements in SVGs with clipping paths (#9420).-      This fixes `--embed-resources` when SVGs have `clip-path` attributes.-    + Fix size of duplicated SVGs with `--embed-resources` (#9439).--  * ConTeXt template: support font fallback (#9361, Lawrence Chonavel).--  * Text.Pandoc.Shared:--    + `addPandocAttributes`: use `wrapper` attribute, not `wrap`, for-      Divs and Spans added as wrappers to hold attributes on elements-      that do not accept them.-    + `makeSections` behavior changes:-      - When the optional base level parameter is provided, we no-        longer ensure that the sequence of heading levels is gapless-        (#9398). Instead, we set the lowest heading level to-        the specified base level, and adjust the others accordingly. If-        an author wants to skip a level, e.g. from level 1 to level 3,-        they can do that. In general, the heading levels specified-        in the source document are preserved; `makeSections` only-        puts them into a hierarchical structure.-      - Section numbers are now assigned differently, as described above-        under `--number-sections` changes (#5071).-    + Improve `makeSections` code for section number calculation.--  * Text.Pandoc.Chunks:--    + Autogenerate unique ids for sections missing them (#9383).-      This is needed for TOC generation to work properly. We can't-      create TOC links if there are no ids. This fixes some EPUB validation-      issues we've been getting since switching over to Chunks for chunking.-    + Improve `fixTOCTreePaths`. We weren't adding ids for section headings-      that don't head a chunk, but these headings are needed for a TOC.--  * Lua: catch encoding error in `pandoc.read` (#9385, Albert Krewinkel).-    Fixed a bug that could lead to an un-catchable error and program-    termination when `pandoc.read` was called with invalid UTF-8 input.--  * LaTeX template: support font fallback (lawcho).  This support is-    LuaLaTeX-specific.  See MANUAL.txt for documentation.--  * Text.Pandoc.Readers: Add `readMan` to exports [API change] (George Stagg).--  * Text.Pandoc.PDF:--    + Reliably detect when TOC has changed (#9295). Sometimes the TOC-      changes but there are no warnings: this happens when no labels-      are present. In this case we must rerun LaTeX. So we now take the-      SHA1 hash of the TOC file and rerun LaTeX if it changes between runs.-    + Increase maximum number of LaTeX runs to 4 (#9299). On some documents,-      4 runs are needed (e.g. when a LastPage reference is used).-    + Avoid `readFileLazy`, which caused improperly cleaned-up-      temp directories on Windows (#9460).--  * MANUAL.txt:--    + Harmonize spelling of Markdown and MultiMarkdown (#9402, Salim B).-    + Add `<pre>` to list of exceptions for `markdown_in_html_blocks`-      extension (#9305).-    + Add clarification to docs for `--resource-path` (#9417).--  * Makefile: Validate generated EPUB as part of prerelease checks.--  * Add validation for docx golden files to CI (Edwin Török).--## pandoc 3.1.11.1 (2024-01-05)--  * Docx reader:--    + Fix HYPERLINK with only switch and no argument (#9246).--  * Org reader:--    + Parse caption and label for grid tables (#9279).--  * MediaWiki reader:--    + Handle multiline math in list items (#9293).--  * OPML writer:--    + Respect `--wrap` options & `--columns` in contents of notes (#9297).--  * ODT/OpenDocument writers:--    + Properly handle highlighting styles (#9287). These styles were-      going into an `office:styles` element in `content.xml`, but this-      is invalid. Instead they must go in `styles.xml`. The variable-      `highlighting-styles` no longer has any effect on the default-      opendocument template, and highlighting styles are not included-      in `opendocument` output.--  * Markdown writer:--    + Add table identifier at end of caption if present (#9279).--  * Text.Pandoc.PDF:--    + Expand list of environment variables to display in verbose output-      (#9303).-    + Ensure that we find all the LaTeX warnings requiring a rerun (#9284).-      This should fix a regression from 3.1.9 that led to incorrect-      alignments in tables (and possibly other issues).--  * Docx writer:--    + Ensure that pandoc's output validates (Edwin Török, #9273, #9269,-      John MacFarlane, #9265, #9266, #9264).-    + Don't emit empty table rows, which seem to cause problems for-      Word (#9224).--  * LaTeX writer:--    + Omit superfluous page locator label when used with `--natbib` or-      `--biblatex` (#9275). These will treat a bare number as a-      page locator, and they will be able to localize it. Note that the-      recognition of the locator label is locale-sensitive; if `lang` is-      `de`, then `S. 33` is a page reference, and `p. 33` is not!--  * Text.Pandoc.Chunks: Fine tune `makeChunks` (#9281).--    + Ensure that chunks not based on sections (those with the-      "preamble" class) get unique identifiers, by appending chunk number.-    + This will also ensure that they get unique path names when-      the path is generated from the identifier.--  * Default HTML5 template: remove html5shiv (and support for IE < 9).--  * Makefile:--    + Fix `make quick-stack`: `j` was expecting a number (Edwin Török).-    + Run built pandoc (instead of pandoc in path).-    + Add `validate-epub` target, using `epubcheck` to test the golden files.-    + Add `validate-docx-golden-tests` target.--## pandoc 3.1.11 (2023-12-15)--  * Typst writer:--    + Emit `;` after typst code, unless followed by space (#9252).-      Otherwise there's the potential that the typst code will swallow-      up a following character.--  * Text.Pandoc.Logging:--    + Add `MakePDFWarning` constructor to LogMessage [API change].-    + Add `MakePDFInfo` constructor to LogMessage [API change].--  * Text.Pandoc.PDF:--    + LaTeX warnings are passed on to the user as warnings.-    + Use `report` with `MakePDFWarning` and `MakePDFInfo` to relay-      verbose information and warnings, instead of writing directly-      to stderr.-    + Parse logs to determine whether additional runs needed, instead of-      running a fixed number of times (#9255). (The number of times-      that was appropriate given pandoc's default templates didn't-      always work for custom templates, and thus pandoc 3.1.10's-      change in the number of runs led to some regressions in PDF-      production.)--  * Makefile: in `make prelease`, add checks that pandoc-cli and-    pandoc have the same version, that pandoc-cli depends on this-    exact version of pandoc, that there is an entry for this version-    in the changelog, and that the version numbers in the-    generated man pages are correct.--  * Regenerate man pages with pandoc 3.1.10. This properly escapes hyphens-    and fixes version numbers in man pages for `pandoc-server` and-    `pandoc-lua`.--  * Depend on texmath 0.12.8.6. This omits unneeded `lr`s in typst-    math output.--  * Depend on typst 0.5. This allows the typst reader to support-    multiline strings, the version type, and the `as`-    keyword with `import`.--## pandoc 3.1.10 (2023-12-12)--  * Link pandoc-cli version to pandoc version. Henceforth pandoc-cli's-    version will be synchronized with pandoc's, and pandoc-cli will-    depend on an exact pandoc version. This will avoid confusion by-    ensuring that `cabal install pandoc-cli-X.Y.Z` installs pandoc-    version X.Y.Z. It will make things more straightforward for-    upstream packagers (see #9232). This scheme does not follow the-    Haskell PVP, but that should cause no harm, because this package-    does not expose a library.--  * Add `alerts` markdown extension. This enables GitHub style markdown-    alerts as a commonmark extension. This extension is now default for-    `gfm`. It can't be used with `markdown`, only with `commonmark` and-    variants.--  * Markdown reader:--    + Preserve newlines in math instead of changing to spaces.-      Otherwise we can get unwanted results if there's-      a `%` comment (#9193).-    + Make attributes work with reference links (#9171).--  * HTML reader:--    + Improve handling of invalidly nested sublists (#9187, cf. #8150).--  * MediaWiki reader:--    + Allow attribute keys with hyphens (#9178).--  * ODT reader:--    + Support attr `text:continue-numbering` (#8979, Stephan Meijer).--  * Typst reader:--    + Allow references (e.g. `@foo`) to become citations-      if there is no corresponding label in the document.-    + Collapse adjacent `cite` elements.-    + Handle supplements in `cite`.-    + Change `cite` (only one key allowed, a label) (typst 0.9 breaking change).-    + Support `quote` element (typst 0.9).--  * LaTeX reader:--    + Handle otherlanguage environment and language-name environments like-    `\begin{french}...\end{french}` (#9202).-    + Fix theorem label parsing (#8872, Hikaru Ibayashi).--  * Docx reader:--    + Unwrap content of shaped textboxes (Stephan Meijer, #9214).-    + Improve handling of `w:sym` (#9220). We now look up symbols in symbol-      fonts using the table defined at Text.Pandoc.Readers.Docx.Symbols.-    + Add unexported module Text.Pandoc.Readers.Docx.Symbols. This gives us a-      table to use to resolve characters included in docx via `w:sym` element.--  * Man reader:--    + Properly handle `.sp` macro inside lists and block quotes (#9201).--  * LaTeX writer:--    + Fix bug with big footnotes inside emphasis (#8982, Hikaru Ibayashi).-    + Handle identifiers inside heading contents. `\phantomsection` can't-      be used in this case, so we need `\hypertarget` (#9209).--  * LaTeX template:--    + Include `bookmark` package unconditionally. This package-      produces better PDF bookmarks than `hyperref` and does it on the-      first pass.--  * Typst writer:--    + Use `quote` for block quotes.-    + Support `--toc-depth` as in other writers (#9242).-    + Put inline image dimensions on enclosing box, not image (#9104).-    + Better handling of tables with captions (#9194).-      We now put these in a figure with a caption argument.-    + Update typst writer to typst 0.9 citation format (#9188).--  * Typst template:--    + Remove custom definition of `blockquote` in default template.-      (We now use built-in `quote`.)-    + Support table of contents.-    + Support csl (#9186, Ian Max Andolina). Typst now supports CSL for its-      native citation engine, so pandoc should use a specified `csl`-      style in the template, falling back to `bibliographystyle` if-      `csl` is not specified.--  * Docx writer:--    + Use different style for block quotes in notes (#9243).-      Using "Footnote Block Text" for the style name, so it can be-      given a different font size if footnotes are.-    + Allow embedded fonts to be used in reference.docx (#6728).--  * HTML5 writer:--    + To conform to validator's expectations, `doc-footnote` role is used-      with `aside` and `doc-endnotes` with `section`.-    + `aside` is used only for notes at ends of sections or blocks;-      if all the notes come at the end of the document, `section` is-      used so we can have the `doc-endnotes` role.--  * JATS writer:--    + Handle case where there is material after refs div (#9166). Previously in-      such cases the references were not being moved to back matter.--  * Ms writer:--    + Don't do normal escapes in filename arguments for PSPIC etc.--  * T.P.RoffChar: escape `-` as `\-`. The `groff_man (7)` man page indicates-    that `-` characters will be treated as typographic hyphens and are not-    appropriate for cases where the output should be copy-pasteable as an-    ASCII hyphen-minus character.  (E.g. in command line options.)-    However, until a recent update groff man did not actually do this;-    it treated `-` and `\-` the same.  With the new update (1.23.0)-    the two are distinguished (see https://lwn.net/Articles/947941/-    for background), so now it is important that pandoc escape `-`.--  * Text.Pandoc.Extension: add `Ext_alerts` constructor [API change].--  * Text.Pandoc.PDF: We now default to running LaTeX only-    once in producing a PDF (instead of twice). This is made possible by the-    shift to the `bookmark` package, which does not require a second pass for-    PDF bookmarks. If a table of contents is present, we still have to run-    three times to get the page numbers, and if beamer is used we still do a-    minimum of two runs.--  * Text.Pandoc.Shared:--    + `renderTags'`: use minimized tag for `rect`.-    + Allow svg `path` element to be minimized.-    + Export `combineAttr` [API change].-    + Improve `isTightList` so that it recognizes an item containing only a list-      which is itself tight as potentially an item in a tight list (#9161).--  * Text.Pandoc.MIME: Ensure we use `.svg` not `.svgz` as extension-    for `image/svg+xml` mime type. This fixes issues with embedded-    SVG images in docx output, among other things (#9195).--  * Text.Pandoc.Class: `openURL` improvements for data uris.-    Only treat data URI as `base64` if ';base64' is specified.-    Otherwise treat as UTF-8 (not 100% reliable but should cover most-    other cases). Strip off `;base64` (or `;charset=...` or whatever)-    from mime type (#9195).--  * Text.Pandoc.SelfContained: Improve treatment of embedded SVGs-    (#9206, #8948).--    + Ensure unique ids for elements by prefixing SVG id.-    + Ensure SVG `id` attribute except when `use` element is used.-    + Remove `width`, `height` attributes from svg element when `use`-      element is used. Instead, add `width` and `height` 100% to the-      `use` element. This seems to get the sizing right.--  * Text.Pandoc.Citeproc: Don't link citations if-    `suppress-bibliography` specified, for there will be nothing to-    link to (#9163).--  * epub.css: add styling for sup and sub (#9160).--  * Switch from `base64` to `base64-bytestring` (#9233).--  * Use newest versions of commonmark, commonmark-extensions,-    commonmark-pandoc, texmath, typst, skylighting, skylighting-core.--  * Benchmark: use standalone documents for reader tests.-    Otherwise typst reader benchmark fails. Note: this means that we are now-    parsing longer documents, so bench results on readers won't be comparable-    to before.--  * MANUAL.txt: update defaults file docs for bibliography fields (#9173).-    Recommend using top-level `bibliography` `csl`, etc. instead-    of a nested `metadata` field. Reason: `${USERDATA}` and `${HOME}`-    are only expanded in these contexts, not in `metadata`.--  * Move man pages to pandoc-cli package (#9245).--## pandoc 3.1.9 (2023-10-27)--  * Make `reference-section-title` work with `jats+element_citations`-    (#9021).--  * Add `bits` as synonym of `jats` as input format.--  * JATS reader:--    + Modify JATS reader to handle BITS too (#9138, Julia Diaz).-      Add provision for title-group, book, book-part-wrapper, book-meta,-      book-part-meta, book-title, book-title-group, index, toc, legend,-      title, collection-meta-    + Fix handling of alt-text (#9130, Julia Diaz). Previously we were-      looking for an attribute that doesn't exist in JATS; alt-text is-      provided by a child element.--  * CommonMark reader:--    + Handle `Ext_tex_math_gfm` (#9121). Parse GFM-specific math-      constructions when `tex_math_gfm` enabled.--  * DokuWiki reader:--    + Allow autolinks to be avoided using e.g. `https:%%//%%...` (#9153).-    + Parse `<code>` and `<file>` as block-level code (#9154).-      Previously we treated them as inline code in some contexts,-      but that is not how DokuWiki works.--  * LaTeX reader:--    + Better handle spacing commands `\hfill`, `\vfill`, `\hskip`,-      `\vskip`, etc. (#9150).-    + Fix incorrect abbreviation for astronomical unit (#9125,-      Michael McClurg).--  * Markdown reader:--    + Fix blindspot with superscript in links (#8981).-      Previously `[^super^](#ref)` wasn't parsed as a link, due to-      code that was meant to prevent footnote markers from being-      recognized as reference links.  This commit tightens up that-      code to avoid this bad effect. We have also added a new-      restriction on footnote labels: they cannot contain the characters-      `^`, `[`, or `]`. Though this is technically a breaking change, we-      suspect that the impact will be minimal, as it's very unlikely-      people would be using these characters in their note labels.-    + Don't apply `--default-image-extension` to data URIs (#9118).-    + More accurate check that a normalCite is not a link,-      bracketed span, or reference (#9080).--  * HTML reader:--    + Allow th to close td and vice versa (#9090).-    + Parse task lists using input elements (#9047, Seth Speaks).--  * Creole reader:--    + Handle empty cells correctly (#9141, Sascha Wilde).--  * Org writer:--    + Escape literal `*`, `|`, `#` at beginning of line with ZWS (#9159).--  * ICML writer:--    + Prevent doubled attributes (#9158).--  * Powerpoint writer:--    + Fix a corruption error caused when the document used both a-      regular png and a png in a data URI (#9113). (Similarly for any-      other image format.) The problem was that duplicate entries in-      `[Content Types].xml` were being created, one for the mime type-      `image/png`, one for `image/png;base64`.--  * LaTeX writer:--    + Fix rowspans in tables so they use the width of-      the column (`=` as the width parameter) (#9140).-    + Don't treat table as "simple" if they have col widths.-      This should help fix a problem wherein some grid tables with-      colspans were overly wide (#9140).-    + Fix uneven indents in line block output (#9088).--  * JATS writer: fix 3.1.4 regression in handling block-level metadata-    (#9092).--  * Ms writer: improvements in image handling (#4475).--    + PDFPIC is now used for PDF images in figures.-    + Inline images that are postscript or PDF are rendered using-      PSPIC or PDFPIC. This isn't ideal, because they will still be-      rendered as if in a separate paragraph, but it's probably-      better than just printing the image name.-    + Units are included in height.--  * HTML writer:--    + If raw format is an HTML side deck format, emit it (James J Balamuta).--  * Typst writer:--    + Add `#box` around image to make it inline. (#9104)-      An `#image` by itself in typst is a block-level element.-      To force images to be inline (as they are in pandoc), we need-      to add a box with an explicit width. When a width is not given-      in image attributes, we compute one from the image itself, when-      possible.-    + Don't allow long heading to wrap (#9132).-    + Escape `(` (#9137). If unescaped `(` occurs in-      certain contexts, it can be parsed as function application.--  * Man writer:--    + Fix some spacing issues around links (#9120).-      We need to use `\c` before a `.UR` or `.MT`, to avoid-      an extra space, and also after.  To ensure that a space-      at the beginning of the following line doesn't get swallowed-      up, we escape it with `\`.-    + Use UR, MT macros for URLs, emails (#9120).--  * Text.Pandoc.Extensions:--    + Add `Ext_tex_math_gfm` constructor to Extension (#9121).-      [API change]. This handles two GitHub-specific syntaxes for math.-      This is now default for `gfm`, in addition to `tex_math_dollars`.-    + Remove duplicates for `Ext_raw_html` and `Ext_pipe_tables`-      in some of the lists (Tim Stewart).--  * Text.Pandoc.Metadata: Add helpful message on some metadata-    YAML errors (#9155).--  * Text.Pandoc.Shared:--    + `splitSentences`: don't split after initials.-      This improves the man and ms writer output, preventing-      sentence breaks after initials.-    + Add `addPandocAttributes` function [API change].-      This is meant to simplify addition of attributes to Pandoc-      elements: for elements that don't have a slot for attributes, an-      enclosing Div or Span is added to hold the attributes.--  * MANUAL.txt:--    + Clarify that formatting can't cross line boundaries-      in line blocks (#9119).-    + Fix legacy option for citation (#8737, 3w36zj6)--  * Update `et` translations (priiduonu).--  * Updated `no` translations (Stephan Daus).-    Renamed no.yaml (macrolanguage Norwegian) to nb.yaml (Norwegian Bokmål).-    Created soft symbolic link from no.yaml pointing to nb.yaml.--  * Lua subsystem: Use the newest LPeg version (lpeg-1.1.*) (#9107,-    Albert Krewinkel).--  * Default `epub.css`: Apply style to h6, format styles, and-    combine identical styles under shared selectors (samuel-weinhardt).--  * Update nix flake with dependencies (piq9117).--  * LaTeX template: fix `\CSLBlock` vertical space (John Purnell).--  * Allow tasty 1.5 and Diff 0.5.--  * Require commonmark-extensions 0.2.4, commonmark 0.2.4.--  * Require texmath 0.12.8.4. This should improve math in-    powerpoint, fixing empty boxes around roots in some cases.--  * Require typst 0.3.2.1--## pandoc 3.1.8 (2023-09-08)--  * JATS reader:--    + Ignore `<processing-meta>` element (#9057, Julia Diaz).-    + Fix conversion of date to ISO 8601 format (#8865).--  * LaTeX template:--    + Add code allow `\cite` to break across lines (#9050).-    + Fix regression with CSL `display="block"` (#7363).-      This restores the line break before the block.-    + Rewrite `CSLReferences` environment to avoid depending on-      `enumitem`, which plays badly with beamer.  Instead we use-      a regular list environment. Thanks to @jpcirrus for the-      concept (#9053).-    + Restore the pre-3.1.7 format of the `CSLReferences`-      environment, which again has two parameters. The first-      determines whether a hanging indent is used (1 = yes, 0 = no),-      and the second is the entry line spacing (0 = none).-    + Add a strut to avoid inconsistencies in spacing (#9058).-    - Remove a break at the end of `CSLRightInline` to avoid-      inconsistencies in spacing. It shouldn't be necessary-      because the paragraph should extend to the right margin (#9058).--  * LaTeX writer:--    + Fix regression with figure labels (#9045). In 3.1.7, pandoc-      added two labels to LaTeX figure environments, one with a-      phantomsection.-    + Fix default citeproc entry-spacing. According to the CSL manual,-      the default entry spacing is 1. We were treating it as 0 (#9058).--  * HTML writer:--    + Use the ID prefix in the ID for the footnotes section (#9044,-      Benjamin Esham).-    + Fix CSL entry-spacing default (#9058).--  * Text.Pandoc.Citeproc:  always include an `entry-spacing` attribute-    in the Div if the bibliography element contains an entry-spacing-    attribute (previously we omitted it when it was 0) (#9058).--  * Clean up pandoc's own man pages by regenerating with pandoc 3.1.7.--  * pandoc-lua-engine: bump lower bound for pandoc (#9046).--  * Depend on texmath 0.12.8.2, fixing binom in typst writer (#9063).--## pandoc 3.1.7 (2023-08-31)--  * Org reader:--    + Don't parse alphabetical lists unless the `fancy_lists` extension is-      enabled (#9042).-    + Allow escaping commas in macro arguments (Amneesh Singh).--  * JATS reader:--    + Support for `<permissions>` metadata (#9037, Julia Diaz).-      metadata objects with multiple fields are created, matching the-      structure in JATS.-    + Correct name of JATS element `attrib`.--  * Markdown reader:--    + Support images with wikilink syntax, e.g. `![[foo|bar]]`, when-      one of the `wikilinks` extension is enabled (#8853).-    + Allow a citation or reference link to be parsed after a `!` (#8254).-    + Fix dropped `!` before nonexistent reference (#9038).--  * LaTeX writer:--    + Fix regression in escaping URLs (#9043).-    + Use `\cite` and `\bibitem` to link up citations, even with citeproc.-      (#9031). This will give us better accessibility; when tagging is-      enabled, the citation can be linked to the bibliography entry.-      This changes some of the details of the layout and the default-      template. We now make `CSLReferences` a special enumitem list-      that will contain `\bibitem`s. Internal links inside citations to-      ids beginning in `ref-` are creating using `\cite` instead of-      `\hyperref`.-    + Use `\phantomsection` and `\label` instead of `\hypertarget` (#9022).-    + Use `\hyperref` for LaTeX internal links, `\hyperlink` for-      beamer (since `\hyperref` doesn't seem to work) (#9022).-    + Backslash-escape `%` and `#` in URLs (#9014).--  * JATS writer:--    + Fix placement of ref-list when no title is specified for the-      reference section (#9017). (In this case we place it in `back`-      with an empty title.)--  * Man writer:--    + Avoid a `.PP` right after a section heading (#9020).-      This is at best a no-op (in groff man and mandoc) and at worst-      (in some formatters) may create extra whitespace.-    + We revert the fanciness introduced in #7506, which employs a-      custom font name `V` and a macro that makes this act like boldface-      in a terminal and monospace in other formats.  Unfortunately,-      this code uses a mechanism that is not portable (and does not-      work in mandoc) (#9020).-    + Instead of using `V` for inline code, we simply use `CR`.-      Note that `\f[CR]` is emitted instead of plain `\f[C]`,-      because there is no `C` font in man.  (This produces warnings-      in recent versions of groff, #9020.)-    + For code blocks, we now use the `.EX` and `.EE` macros,-      together with `.IP` for spacing and indentation.  This gives-      more standard code that can be better interpreted e.g. by mandoc-      (#9020).--  * Man template: don't emit `.hy`, regardless of setting of-    `hyphenate` variable (#9020).--  * LaTeX template: special redefinition of `\st` for CJK (#9019).-    soul's version raises on error on CJK text.--  * Use latest skylighting-format-blaze-html (#7248).-    This works around a longstanding iOS Safari bug that caused long-    lines to be displayed in a different font size in highlighted code.--  * Allow skylighting 0.14 (and require it in pandoc core).--  * Allow text 2.1.--## pandoc 3.1.6.2 (2023-08-22)--  * Org reader: allow example lines to end immediately after the colon-    (Brian Leung).--  * Docx reader:--    + Omit "Table NN" from caption (#9002).-    + Avoid spurious block quotes in list items (#8836).--  * JATS reader: Fix display of block elements (#8889, Julia Diaz).-    A number of block elements, like disp-quote, list, and disp-formula, were-    always treated as inlines if appearing inside paragraphs, even if their-    usage granted a separate block.--  * HTML reader: avoid duplicate id on header and div (#8991).--  * Typst writer:--    + Use `~` for nonbreaking space, and escape literal `~` (#9010).-    + Put the label in right place for Div, use `#block` (#8991).-      Previously we were putting the label at the beginning of-      the Div's contents, but according to the documentation such a-      label gets attached to the *preceding* element.  We now use an-      explicit `#block` and add the label at the end.--  * LaTeX writer:--    + Improve escaping of URIs in href, url (#8992).-    + Improve internal links and targets (#8744). We no longer-      wrap section headings in a `\hypertarget`. This is unnecessary-      (hyperref creates an anchor based on the label) and it interferes with-      tagging. In addition, we now use `\hyperref` rather than `\hyperlink`-      for internal links. Currently `\hypertarget` is still being used for-      link anchors not on headings. Thanks to @u-fischer.--  * HTML format templates (style.html): Fix typo in clause for svg-    (Jackson Schuster).--  * Use lastest texmath, typst-symbols, typst. Targets typst 0.7.---## pandoc 3.1.6.1 (2023-08-11)-- * HTML reader: properly calculate RowHeadColumns (#8984). This fixes a-   bug in the calculation of the number of header columns in table row.-   It also changes the algorithm for determining the table body's-   RowHeadColumns based on the numbers of head columns in each row.-   Previously we used the max, and #8634 switched to the min, which-   led to bad results. Now we only set RowHeadColumns to a non-zero value-   if *all* rows have the same number of head columns.--  * OpenDocument writer:--    + Implement syntax highlighting for inline and block code (#6710).-    + Support highlighted text in ODT/OpenDocument writers for Span-      with class `mark` (#8960). The color can be adjusted by-      modifying the Highlighted style.--  * Typst writer: escape `//` so it doesn't get interpreted as a comment-    (#8966).--  * ChunkedHTML writer: Fix regression including MathJax script (#8967).-    The fix for #8620 caused the script to be included when the table of-    contents but not the body text of a page contains math.  But it broke the-    case where the table of contents doesn't contain math but the page does.-    This patch fixes the issue.--  * Text.Pandoc.SelfContained:--    + Retain attributes in SVG tag when referring to another-      SVG's content using `<use>` (#8969).-    + Allow units in width and height for SVG. Units are optional but allowed.-    + Don't coerce calculated SVG dimensions to Int.-    + fix calculation of SVG width and height. We were computing width and-      height from viewBox incorrectly (#8969).-    + Add clause for SVG to default CSS for HTML (#8969).-    + Ensure that width and height attributes don't get specified-      twice is both the img tag and the svg include them (#8965).-    + Omit unnecessary attributes xmlns, xmlns:xlink, and version on-      SVG element (#8965).-    + Use 20 character rather than 40 character hashes for generated IDs-      (#8965).--  * Use pandoc-types 1.23.1. This fixes a regression with toJSONFilter (#8976),-    which in 1.23.0.1 no longer worked on pure values of type `a -> [a]`.--  * Use ghc 9.6 for release builds (#8947).--  * Fix some links in FAQs (Diogo Almiro).---## pandoc 3.1.6 (2023-07-20)--  * Fix CVE-2023-38745, a 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 emitting 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-    (#8788, Sam S. Almahri). The default is true if no value is specified,-    so this is fully backwards-compatible.--  * Support `--id-prefix` for markdown output (#8878)--  * Markdown reader:--    + Add strictness annotations to fix a memory leak (#8762).--  * Typst reader:--    + Use typst-hs 0.3.0.0, which is more robust, fixes many bugs, and-      targets typst 0.6.-    + Package loading is now supported, as long as the package has been-      cached or is local.-    + Rewrite Typst reader in a way that makes it easier to extend.-    + Filter out CR in raw.-    + Handle block content for link element.-    + Handle block-level content in text element.-    + Handle style, align, place in inline contexts too.-    + Improve info message for skipped elements.--  * Add typst reader tests (#8942).--  * MediaWiki reader:--    + Revise treatment of "link trail." Previously we only included ASCII-      letters. That is correct for English but not for, e.g., Spanish (see-      comment in #8525). A safer approach is to include all letters except-      those in the CJK unified ideograph ranges.--  * AsciiDoc writer:--    + Make modern AsciiDoc the target for `asciidoc` (#8936).-      The AsciiDoc community now regards the dialect parsed by `asciidoctor`-      as the official AsciiDoc syntax, so it should be the target of our-      `asciidoc` format. The `asciidoc` output format now behaves like-      `asciidoctor` used to. `asciidoctor` is a deprecated synonym. For-      the old `asciidoc` behavior (targeting the Python script),-      use `asciidoc_legacy`. The templates have been consolidated. Instead of-      separate `default.asciidoctor` and `default.asciidoc` templates, there-      is just `default.asciidoc`.-    + Text.Pandoc.Writers.AsciiDoc API changes:-      - `writeAsciiDoc` now behaves like `writeAsciiDoctor` used to.-      - `writeAsciiDoctor` is now a deprecated synonym for `writeAsciiDoc`.-      - New exported function `writeAsciiDocLegacy` behaves like-        `writeAsciDoc` used to.-    + Update line-through for asciidoc writer to custom inline style (#8933,-      Kevin Broch).--  * Typst writer:--    + Support `unlisted` class in headings (#8941).-    + Consolidate bibliography files into one `#bibliography` command (#8937).-    + Improve handling of autolinks (#8931).--  * Docx writer:--    + Make relative widths work in tables. This didn't work before because we-      were missing an attribute that tells Word to used fixed widths rather-      than computing optimal ones.--  * DokuWiki writer: fix lists with Div elements (#8920).-    The DokuWiki writer doesn't render Divs specially, so their presence in-    a list (e.g. because of custom-styles) need not prevent a regular-    DokuWiki list from being used. (Falling back to raw HTML in this case is-    pointless because no new information is given.)--  * LaTeX writer:--    + Fix babel name for `fa` (should be `persian`).-    + Prevent babel language from being imported twice (#8925).--  * Text.Pandoc.Class:--    + Add `toTextM` [API change]. This is like `Text.Pandoc.UTF8.toText`,-      except:--      - it takes a file path as first argument, in addition to-        bytestring contents-      - it raises an informative error with source position if-        the contents are not UTF8-encoded--    This replaces `utf8ToText` whenever we have the filename and are-    in a PandocMonad instance. This will lead to more informative error-    messages for UTF8-encoding, indicating the file path and byte offset-    where the error occurs (#8884).--  * Remove invalid term "Subject" from Turkish translations (#8921).--  * stack.yaml: add pkg-config to nix packages (#8927, pacien).--  * Allow aeson 2.2.--  * MANUAL: Add clarification on --section-divs. Closes #8882.---## pandoc 3.1.4 (2023-06-24)--  * Fix a security vulnerability in MediaBag and T.P.Class.IO.writeMedia.-    This vulnerability, discovered by Entroy C, allows users to write-    arbitrary files to any location by feeding pandoc a specially crafted-    URL in an image element.  The vulnerability is serious for anyone-    using pandoc to process untrusted input.  The vulnerability does-    not affect pandoc when run with the `--sandbox` flag. [CVE-2023-35936]--  * Allow `epub-title-page` to be used in defaults files (#8908).--  * Issue `Extracting` info message (in `--verbose` mode) when using-    `--extract-media` or extracting media temporarily in PDF production.--  * HTML reader: Update TableBody RowHeadColumns caculation (#8634,-    Ruqi). This change sets RowHeadColumns to the minimum value of each row,-    which gives better results in cases where rows have different numbers-    of leading th tags.--  * Dokuwiki reader: retain image query parameters as attributes (#8887, echo0).--  * Textile reader: Add support for link references (#8706, Stephen Altamirano).-    Textile supports what it calls "link alias", which are analogous to-    Markdown's reference-style links.--  * LaTeX reader: support alt text on images (#8743, Albert Krewinkel).--  * Commonmark reader: Make `implicit_figures` work again.-    Support for this (introduced in #6350) disappeared when we made an-    architectural change.--  * JATS reader:--    + Add footer and multiple body parsing to table reader (#8765, Noah Malmed).-    + Parse references title from ref-list (#8365).--  * JATS writer:--     + Make `--number-sections` work.-     + Include title in ref-list (#8364). Previously the reference title ended-       up in a separate section at the back of the body instead of in the ref-list-       in the back matter.--  * Mediawiki writer: allow highlighting to work for F# language-    (Adelar da Silva Queiróz).--  * LaTeX writer: Fix escaping of `&` in `\href` and `\url` (#8903).--  * Docx writer:--    + Fix localization of "Abstract" title (#8702).-    + Allow `abstract-title` to be specified in docx metadata (#8794).--  * ChunkedHTML writer: Make math work in top-level page (#8915).--  * Text.Pandoc.Logging: add new log message type `ScriptingWarning`-    [API change] (Albert Krewinkel).--  * Lua: report warnings from Lua scripts (Albert Krewinkel).-    Lua's warning system is plugged into pandoc's reporting architecture.-    Warnings that are raised with the Lua `warn` function are now reported-    together with other messages.--  * Use crypton-connection instead of connection (#8896, Felix Yan).-    Follows the change introduced in tls 1.7.0.--  * Bump versions for skylighting-core, skylighting.--  * Include lua/module/sample.svg in cabal extra-source-files (Felix Yan).--  * Add Nynorsk (New Norwegian) translations (Per Christian Gaustad).--  * Add tests for `fillMediaBag`/`extractMedia`.--  * INSTALL.md:--    + Mention alternatives to LaTeX to generate PDF (Norwid Behrnd).-    + Update Linux install links (harabat).--  * pandoc-extras.md: add to "Academic publishing workflows" (#8696,-    Vladimir Alexiev).--## pandoc 3.1.3 (2023-06-07)--  * New output format: `typst`.--  * New module: Text.Pandoc.Readers.Typst [API change].--  * DocBook reader:--    + Support more emphasis roles (Albert Krewinkel).-      The role "bf" is taken to indicate "bold face", i.e.,-      "strongly emphasized" text, while "underline" leads to-      underlined text.--  * JATS reader:--    + Improve title and label parsing in the JATS reader (#8718,-      Noah Malmed.)-    + Add rowspan, colspan and alignment to cells in jats table-      reader (#8408, Noah Malmed)--  * Org reader (Albert Krewinkel):--    + Require abstract environment to use lowercase.-    + Treat `#+NAME` as synonym for `#+LABEL` (#8578).--  * ODT reader:--    + Allow lists in table cells (#8892).-    + Allow frames inside spans (#8886).--  * RST reader:--    + Fix sorting on anonymous keys (#8877). This fixes a link-      resolution bug bug affecting RST documents with anonymous links.--  * HTML reader:--    + Fix iframe with data URI of an image (#8856).-      In this case we don't want to try to parse the data at the URL.-      Instead, create an image inside a div.--  * RTF reader:--    + Fix bug in table parsing (#8767). In certain cases, text before a-      table was being incorporated into the table itself.--  * Docx reader:--    + Introduce support for Intense Quote (Stephan Meijer).--  * Markdown reader:--    + Disallow escaping of `~` and `"` in `markdown_strict` (#8777,-      Albert Krewinkel). This matches the behavior of the legacy-      `Markdown.pl` as well as what is described in the manual.--  * LaTeX reader: ignore args to column type in `\multicolumn` (#8789).--  * HTML writer:--    + Use first paragraph in task item as checkbox label (#8729, Albert-      Krewinkel).--  * Ms writer:--    + Coerce titles to inlines (#8835). Block-level formatting is not-      allowed inside `.TL`.--  * LaTeX writer:--    + Fix width for multicolumn simple table (#8831).--  * Jira writer:--    + Use first code block class as highlighting language (#8814, Albert-      Krewinkel). The writer no longer searches the list of-      classes for a known programming language but always uses-      the first class in that list as the language identifier.--  * OpenDocument writer:--    + Handle row header column cells as header cells (#8764, Michael Stahl).-    + Fix invalid `text:p` inside `text:p` from meta (#8256).--  * ODT writer:--    + Don't add settings.xml (Michael Stahl). This will cause defaults-      to be used, which is what we want.-    + Don't add unnecessary Configurations2 directory (Michael Stahl).-    + Don't add thumbnail (Michael Stahl).-    + Put `manifest.version` on directory file-entry (Michael Stahl).-      See ODF 1.3 part 2, 4.16.14.1.-    + Stop validator complaints by producing ODF 1.3 (Michael Stahl).--  * MediaWiki writer:--    + Remove links from inside links in mediawiki writer (#8739,-      Wout Gevaert).--  * Typst writer:--     + Omit bibliography if `citations` not enabled (#8763).-      With this change, the typst writer will omit the `#bibliography`-      command when `citations` is not enabled.  (If you want to use-      pandoc's own `--citeproc`, you should combine it with-      `-t typst-citations` to disable native typst citations.-    + Use `<..>` for labels, create internal links.-    + Use `#footnote` for notes (#8893).-    + Fix alignment issue in lists.  It's an aesthetic issue-      only; the first line had an extra space indent after the-      list marker.--  * Commonmark writer:--    + Use shortcut reference links: commonmark supports these.--  * EPUB template: add `lang` attribute to `<html>` (Gabriel Lewertoski).--  * Template styles.html: fix task-list styling in reveal.js-    (#8731, Albert Krewinkel).--  * LaTeX template: Fix `\babelfont` (#8728).--  * Text.Pandoc.Parsing:--    + Remove unnecessary 'spaces' in `parseFromString`.--  * Text.Pandoc.ImageSize: Drop BOM at start of SVG if present.-    Otherwise our code can fail to determine image size.--  * Lua subsystem:--    + Fix value of PANDOC_SCRIPT_FILE for custom readers & writers-      (#8781, Albert Krewinkel). The value did not hold the actual-      file path for scripts in the *custom* folder of the datadir.--  * Fix YAML in translation files for `cs` and `pl` (#8787).--  * Fix pdf output via typst (#8754).  One must now use `typst-    compile` rather than `typst`.--  * MANUAL.txt:--    + Added note that the user will need to create the user data-      dir (#8727).-    + Add `wikilinks` to non-default extensions (Ilona).-    + Update link to custom djot writer (Albert Krewinkel).-    + Better link to citation syntax.-    + Fix typo (sdhoward).-    + Note that `#` fancy list markers don't work with commonmark (#8772,-      William Lupton).-    + Add commonmark `fenced_div` note (#8773, William Lupton).-    + Move highlighting documentation, with minor adjustments-      (William Lupton).-    + Fix inaccurate statement about spaces and tabs in template-      syntax-      (Frank Seifferth).--  * Update documentation for org-mode (Christian Christiansen, #8716).--  * doc/lua-filter.md:--    + Fix typos (#8734, perro tuerto).-    + Fix anchor (Toni Dietze).-    + Use full field name in example (#8857, Matt Dodson).-    + Fix copy-paste error (#8798, thron7).--  * CONTRIBUTING.md: update info on ghc versions.--  * INSTALL.md:--    + Fix cabal install instructions (Albert Krewinkel).-    + Use more relevant link to NetBSD/pkgsrc entry (Charlotte Koch).-    + Fix Windows install instructions for winget (#8799).--  * Tests: Rename test/docx/block_quotes_parse_indent.native for-    consistency (Stephan Meijer).--  * Add `tls` constraint on cabal.project. This is needed to-    avoid problems caused by the transition to `crypton`.--  * Require texmath 0.12.8.---## pandoc 3.1.2 (2023-03-26)--  * Add a Lua REPL (Albert Krewinkel). This can be started-    with `pandoc lua -i`.  It is also possible to instruct a filter to-    open the REPL at a certain point, for debugging (see `pandoc.cli.repl`).--  * Support `typst` as a `--pdf-engine`.--  * Add typst writer (#8713).  New module Text.Pandoc.Writers.Typst,-    exporting `writeTypst` [API change].--  * Org reader:--    + Allow zero width space as an escape character (#8716,-      Christian Christiansen). Allow the character U+200B to be used as-      an escape character as described in the Org-mode documentation-      (<https://orgmode.org/manual/Escape-Character.html>).--  * DocBook reader:--    + Handle "book" for xref references (#8712, Andres Freund)-      This also adds a test xref to book and part.-    + Handle `<part>` (#8712).--  * HTML reader:--    + Fix behavior with `-native_spans-raw_html` (#8711). Previously with-      this configuration, `<span>`s were not treated as inline elements at all.--  * HTML writer:--    + Avoid duplicate classes (#8705).-    + Use img element instead of embed for `.svg.gz` and `.png.gz` etc. (#8699).-    + HTML writer footnotes changes (#8695): when `--reference-location=section`-      or `=block`, use an `aside` element for the notes rather than a `section`.-      When `--reference-location=section`, include the `aside` element inside-      the section element, rather than outside. (In slide shows, this option-      causes footnotes on a slide to be displayed at the bottom of the slide.)--  * EPUB writer:--    + Use different structure for epub footnotes (#8676, see #8672, #5583).-      Many EPUB readers are thrown off by pandoc's current footnote-      output.  Both the ol and the fact that the footnote backlink is-      at the end of the note seem to pose problems.-      With this commit, we now create a list of aside (or div) elements,-      instead of an ordered list. Each element begins with a note number-      that is linked back to the note reference.  (So, the backlink occurs-      at the beginning rather than the end.) Thanks to @Porges and @lewer.--  * Docx writer:--    + Include abstract title (#8702). Uses localized term for abstract.--  * Markdown writer:--    + Use implicit figures if there's a caption but no alt (#8689,-      Albert Krewinkel).--  * Jira reader (Albert Krewinkel):--    + Add panel title as nested div (#8681).-    + Require jira-wiki-markup 1.5.1 (#8680). This fixes a bug in the parser-      that caused text between two exclamation marks to be parsed as an-      image. The first `!` of image markup must now be followed by a-      non-space character; otherwise, the enclosed text is parsed as-      normal content.-    -  * Ms writer:--    + Fix handling of Figure (#8660).--  * ICML writer:--    + Fix images with data (#8675). The Contents element-      should be inside Properties.--  * LaTeX writer:--    + Add Chinese to Babel languages.-    + Fix background image in Beamer when there are figure environments (#8671,-      Martín Pozo).--  * LaTeX template:--    + Add `babelfonts` variable to default LaTeX template.-      This allows specifying certain fonts to be used with-      certain babel languages. Thanks to Frederik Elwert.-    + Fix highlight/underline with lualatex (#8707). We need the lua-ul package-      instead of soul, which doesn't work with lualatex.--  * Lua (Albert Krewinkel):--    + Add `pandoc.cli.repl` function-    + Fix `json.encode` for nested AST elements. Ensures that objects with-      nested AST elements can be encoded as JSON.-    + Auto-generate docs for pandoc modules.-    + Load text module as `pandoc.text`. This only affects the name in the-      Lua-internal documentation. It is still possible to load the modules-      via `require 'text'`, although this is deprecated.-    + Move docs from module `text` to `pandoc.text`-      The latter is easier to use and more consistent with the other modules.-    + Keep the Lua stack clean A metatable used during initialization was-      not properly removed from the stack. Likewise, accessing the-      CommonState from Lua previously led to the pollution of the-      Lua stack with a left-over value.-    * Add function `pandoc.format.from_path`.-    + Allow to get the JSON encoding of log messages.--  * Text.Pandoc.Format: Add new function `formatFromFilePaths` [API change]-    (#8710, Albert Krewinkel).--  * The old Text.Pandoc.App.FormatHeuristics module has been removed.--  * In `--version`, use Windows `%APPDATA%` variable to describe-    user data dir (#8686, Pablo Rodríguez).--  * Text.Pandoc.App.CommandLineOptions: don't lowercase arg to `--from`/`--read`-    (Albert Krewinkel). This prevented users to use custom writers with-    uppercase characters in their filenames. Format-normalization,-    including lower-casing of format identifiers, happens during-    format parsing.--  * Documentation:--    + Add `doc/nix.md`.-    + Add `doc/extras.md`. This was formally in the website repo.-    + `doc/lua-filters.md`: improve docs for `pandoc.zip`.--  * Factor out `make_macos_release.sh` from the release candidate workflow.-    Use cabal instead of stack to build the macos binary.--  * Modify linux/make_artifacts.sh so it will work on cirrus.--  * Switch to hslua-2.3--  * Depend on latest releases of texmath, doclayout.--## pandoc 3.1.1 (2023-03-05)--  * EPUB reader: Give additional information in error if the epub-    zip container can't be unpacked.--  * TSV reader: don't gobble tabs as whitespace (#8661).--  * Org reader: accept empty tables (#8659).--  * LaTeX reader: fix multiplication syntax for tabular (#8658).-    We recognized `*{6}{...}` but not `*6{...}` or `*6c`.--  * Docx reader: parse image alt texts in LibreOffice generated files.-    LibreOffice tags images slightly differently than Word; this change lets-    the parses take that difference into account when looking for an image-    description (alt text).--  * DocBook reader:--    + Fix `<xref>` references to tables in DocBook files-      (#8626, Pavol Otto).-    + Parse `figure` as a Figure element in the AST (#8668).--  * JATS reader: avoid generating duplicate figure captions (#8669).--  * RST reader: align with spec in syntax for role names (#8653).-    In particular, we now allow colons in row names.--  * Add note on converting from .doc format to FAQs (#8654).--  * Trap error in getAppUserDataDirectory (#8648).-    This can raise an error if pandoc is run in a non-user environment.--  * LaTeX writer: do not use longtable foot with Beamer (#8638, Albert-    Krewinkel). The table foot is made part of the table body, as-    otherwise it won't show up in the output. The root cause for-    this is that longtable cannot detect page breaks in Beamer.-    -  * LaTeX template: Add CJKsansfont and CJKmonofont for XeLaTeX-    (#8656, Yudong Jin). `CJKsansfont` and `CJKmonofont` will be-    set for xelatex only if `CJKmainfont` is also provided.--  * URL style in ConTeXt (#8612, Thomas Hodgson). Previously, a-    URL like this would be in monospace text:-    `\useURL[url1][https://example.com]`.  Now, it will match the-    main text unless the `linkstyle` variable is set, which-    controls the styling of all links.  Closes #8602.--  * Asciidoc writer: Properly escape `|` in table cells (#8665).--  * asciidoc{,tor} template: fix revision date when author is unset-    (#8637, arcnmx). Revision line syntax is only valid in-    combination with an author line, so the date attribute must be-    set explicitly when the author is missing--  * HTML writer: allow "track" element to be treated as block-level HTML-    (#8629).--  * Include needed polyfill when MathJaX is used (#8625).--  * JATS writer: include alt-text in `<graphic>`,-    `<inline-graphic>` elements (#8631, Albert Krewinkel).--  * Chunked HTML writer:  Retain metadata in processing sections-    for chunked HTML (#8620).  Previously we suppressed metadata-    in all but the top page, in order to prevent the title block-    from being printed on every page. This prevented use of-    custom variables set by metadata fields.  This commit moves-    to a better solution: a conditional in the default template-    restricts the title block to the top page.--  * Lua API:--    + Add new function `pandoc.system.cputime` (Albert-      Krewinkel).  The function returns the CPU time consumed by-      pandoc and can be used to benchmark Lua computations.-    + Add module `pandoc.json` to handle JSON encoding (#8605,-      Albert Krewinkel).--  * Use pandoc-lua-marshal 0.2.1 (Albert Krewinkel).-    All major AST elements now have `__tojson` metamethods that return the-    JSON representation of an element. This allows to JSON-encode these-    elements with libraries that respect the `__tojson` metamethod,-    including dkjson.--  * Use latest zip-archive.  This allows pandoc to open certain-    epubs that it could not open before.--  * Use commonmark-extensions 0.2.3.4. This fixes some bugs involving-    definition lists and inline formatting.--  * Use latest skylighting-format-context--  * MANUAL.txt:--    + Document chunk-template in defaults file.-    + Remove obsolete "raw content in a style" section.-    + Revise documentation for `--mathml` to reflect support in all major-      browsers (#8667).--  * docs/custom-readers.md: Update JSON parsing example. The example now-    uses the built-in `pandoc.json` library to parse the API output.--  * doc/press.md: Add article on CiTO in J Cheminform by @egonw.--  * doc/lua-filters.md: fix typo in `run_json_filter` (Morgan Willcock).---## pandoc 3.1 (2023-02-09)--  * Fix regression with `--print-highlight-style` option (#8586).--  * Add new `--chunk-template` option (#8581), allowing more control-    over the filenames in chunked HTML output.--  * Text.Pandoc.App: Add `optChunkTemplate` constructor to Opt [API change].--  * Text.Pandoc.Options: add `writerChunkTemplate` constructor to-    `WriterOptions` [API change].--  * Text.Pandoc.Chunks: add Data, Typeable, Generic, ToJSON, FromJSON-    instances for `PathTemplate` [API change].--  * Text.Pandoc.Citeproc: Fix bug in `metaValueToReference` (#8611).-    This bug caused us to get some repeated content when converting-    MetaBlock to Inlines.--  * Textile reader:--    + Support footnote backlinks (#8585, Stephen Altamirano).-    + Don't allow brackets in URLs (#8582).--  * ODT reader: fix blockquote indent detection (#3437, Daniel Kessler).--  * LaTeX writer: include short figure/table caption if one is given-    (Albert Krewinkel). Short captions are used by LaTeX when generating-    the list of figures or list of tables. Adding a short caption will-    now overwrite the full caption in these lists.--  * Powerpoint writer: fix handling of simple figures (#8565,-    Albert Krewinkel). This ensures that simple figures are displayed-    in the same way as before the introduction of a dedicated `Figure`-    constructor in the AST.--  * Improve handling of `%` in bib(la)tex parsing (#8597, #8595).--  * Use released skylighting 0.13.2.1--  * INSTALL.md: direct people to cabal install pandoc-cli.--  * doc/lua-filters.md: document 'Figure' type and constructor (Albert-    Krewinkel). Fix typos (Martin Joerg).--  * Fix link in manual (#8583, Salim B).--## pandoc 3.0.1 (2023-01-25)--  * Fix use of extensions with custom readers (#8571).--  * Text.Pandoc.Writers.Shared: export `setupTranslations` [API change].-    Use this in HTML and OpenDocument writers, to ensure that-    translations are set up properly even when we don't go through-    `convertWithOpts`.--  * LaTeX reader: fix regression in macro resolution for environments (#8573).--  * Chunked HTML writer: Fix handling of images with absolute URLs (#8567).--  * HTML writer:--    + Don't omit newlines in task lists.-    + Don't disable checkboxes in task lists (#8562).--  * Ensure that automatically set variables `pandoc-version`, `outputfile`,-    `title-prefix`, `epub-cover-image`, `curdir`, `dzslides-core` can be-    overridden by `--variable` on the command line. Previously they would-    create lists in the template Context, which is not desirable.--  * Fix man page copying in `linux/make_artifacts.sh` (#8566).-    Previously we were copying the pandoc-server.1 pandoc page to pandoc-lua.1.--  * pandoc.cabal: remove pandoc.cabal, stack.cabal from extra-source-files-    (#8560). The problem is that if these are in extra-source-files, then they-    get put in the tarball, and then anyone trying to build the source-    from an unpacked tarball will run into the problem that cabal.project-    and stack.yaml refer to pandoc-server, pandoc-lua-engine, and-    pandoc-cli, which aren't in the tarball.--  * Require texmath 0.12.6 for better MathML output.--  * Fix typo in Lua filter documentation (Carlos Scheidegger).--  * Fix formatting of link in pandoc-server.md (James Scott-Brown).--  * Minor changelog fixups.--## pandoc 3.0 (2023-01-18)--  * Split pandoc-server, pandoc-cli, and pandoc-lua-engine-    into separate packages (#8309). Note that installing-    the `pandoc` package from Hackage will no longer give you the-    `pandoc` executable; for that you need to install `pandoc-cli`.--  * Pandoc now behaves like a Lua interpreter when called as-    `pandoc-lua` or when `pandoc lua` is used (#8311, Albert Krewinkel).-    The Lua API that is available in filters is automatically-    available to the interpreter. (See the `pandoc-lua` man page.)--  * Pandoc behaves like a server when called as `pandoc-server`-    or when `pandoc server` is used. (See the `pandoc-server` man page.)--  * A new command-line option `--list-tables`, causes tables to be-    formatted as list tables in RST (#4564, with Francesco Occhipinti).--  * New command line option: `--epub-title-page=true|false` allows-    the EPUB title page to be omitted (#6097).--  * `--reference-doc` can now accept a URL argument (#8535) and-    load a remote reference doc.--  * `--version` output no longer contains version info for dependent-    packages. Instead, it contains a "Features" line that indicates-    whether the binary was compiled with support for acting as a server,-    and for using Lua filters and Custom writers.--  * A new option `--split-level` replaces `--epub-chapter-level`-    and affects both EPUB and chunked HTML output.  `--epub-chapter-level`-    will still work but is deprecated.--  * Multiple input files with `--file-scope`: fix case where the links-    are URL-encoded, e.g. with `%20` (#8467).--  * Produce error if `--csl` is used more than once (#8195, Prat).--  * Remove deprecated `--atx-headers` option.--  * Remove deprecated option `--strip-empty-paragraphs`.--  * In `--verbose` mode add message when running citeproc (as with-    other filters).--  * Add new `mark` extension for highlighted text in Markdown,-    using `==` delimiters (#7743).--  * Add new extensions `wikilinks_title_after_pipe` and-    `wikilinks_title_before_pipe` for `commonmark` and `markdown`.-    (#2923, Albert Krewinkel). The former enables links of style-    `[[Name of page|Title]]` and the latter `[[Title|Name of-    page]]`. Titles are optional in both variants, so this works-    for both: `[[https://example.org]]`, `[[Name of page]]`. The-    writer is modified to render links with title `wikilink` as-    a wikilink if a respective extension is enabled. Pandoc will-    use `wikilinks_title_after_pipe` if both extensions are-    enabled.--  * Add prefixes to identifiers with `--file-scope` (#6384).-    This change only affects the case where `--file-scope` is used-    and more than one file is specified on the command line.-    In this case, identifiers will be prefixed with a string-    derived from the file path, to disambiguate them. For example,-    an identifier `foo` in `contents/file1.txt` will become-    `contents__file1.txt__foo`.  Links will be adjusted accordingly:-    if `file2.txt` links to `file1.txt#foo`, then the link will-    be changed to point to `#file1.txt__foo`.  Similarly, a link-    to `file1.txt` will point to `#file1.txt`.  A Div with an-    identifier derived from the file path will be added around-    each file's content, so that links to files will still work.--  * New output format: `chunkedhtml`. This creates a zip file-    containing multiple HTML files, one for each section,-    linked with "next," "previous," "up," and "top" links.-    (If `-o` is used with an argument without an extension,-    it is treated as a directory and the zip file is automatically-    extracted there, unless it already exists.) The top page will-    contain a table of contents if `--toc` is used.  A-    `sitemap.json` file is also included. The option-    `--split-level` determines the level at which sections are-    to be split.--  * Support complex figures (Albert Krewinkel, Aner Lucero).-    There is now a dedicate Figure block constructor for-    figures.  The old hack of representing a figure as-    `Para [Image attr [..alt..] (source, "fig:title")]`-    has been dropped.  Here is a summary of figure support-    in different formats:--    + Markdown reader: paragraphs containing just an image are treated as-      figures if the `implicit_figures` extension is enabled. The identifier-      is used as the figure's identifier and the image description is also-      used as figure caption; all other attributes are treated as belonging-      to the image.-    + Markdown writer: figures are output as implicit figures if possible,-      via HTML if the `raw_html` extension is enabled, and as Div elements-      otherwise.-    + HTML reader: `<figure>` elements are parsed as figures, with the-      caption taken from the respective `<figcaption>` elements.-    + HTML writer: the alt text is no longer constructed from the caption,-      as was the case with implicit figures. This reduces duplication, but-      comes at the risk of images that are missing alt texts. Authors should-      take care to provide alt texts for all images. Some readers, most-      notably the Markdown reader with the `implicit_figures` extension,-      add a caption that's identical to the image description. The writer-      checks for this and adds an `aria-hidden` attribute to the-      `<figcaption>` element in that case.-    + JATS reader: The `<fig>` and `<caption>` elements are parsed into-      figure elements, even if the contents is more complex.-    + JATS writer: The `<fig>` and `<caption>` elements are used write-      figures.-    + LaTeX reader: support for figures with non-image contents and for-      subfigures.-    + LaTeX writer: complex figures, e.g. with non-image contents and-      subfigures, are supported. The `subfigure` template variable is set if-      the document contains subfigures, triggering the conditional loading-      of the *subcaption* package. Contants of figures that contain tables-      are become unwrapped, as longtable environments are not allowed within-      figures.-    + DokuWiki, Haddock, Jira, Man, MediaWiki, Ms, Muse, PPTX, RTF, TEI,-      ZimWiki writers: Figures are rendered like Div elements.-    + Asciidoc writer: The figure contents is unwrapped; each image in the-      the figure becomes a separate figure.-    + Classic custom writers: Figures are passed to the global function-      `Figure(caption, contents, attr)`, where `caption` and `contents` are-      strings and `attr` is a table of key-value pairs.-    + ConTeXt writer: Figures are wrapped in a "placefigure" environment-      with `\startplacefigure`/`\endplacefigure`, adding the features-      caption and listing title as properties. Subfigures are place in a-      single row with the `\startfloatcombination` environment.-    + DocBook writer: Uses `mediaobject` elements, unless the figure contains-      subfigures or tables, in which case the figure content is unwrapped.-    - Docx writer: figures with multiple content blocks are rendered as-      tables with style `FigureTable`; like before, single-image figures are-      still output as paragraphs with style `Figure` or `Captioned Figure`,-      depending on whether a caption is attached.-    + DokuWiki writer: Caption and "alt-text" are no longer combined. The-      alt text of a figure will now be lost in the conversion.-    + FB2 writer: The figure caption is added as alt text to the images in-      the figure; pre-existing alt texts are kept.-    + ICML writer: Only single-image figures are supported. The contents of-      figures with additional elements gets unwrapped.-    + OpenDocument writer: A separate paragraph is generated for each block-      element in a figure, each with style `FigureWithCaption`. Behavior for-      single-image figures therefore remains unchanged.-    + Org writer: Only the first element in a figure is given a caption;-      additional block elements in the figure are appended without any-      caption being added.-    + RST writer: Single-image figures are supported as before; the contents-      of more complex images become nested in a container of type `float`.-    + Texinfo writer: Figures are rendered as float with type `figure`.-    + Textile writer: Figures are rendered with the help of HTML elements.-    + XWiki: Figures are placed in a group.--  * Changes in custom readers/writers:--    + It is now possible to have a custom reader and a custom writer for-      a format together in the same file.  The file may also define-      a custom template for the writer.-    + Pandoc now checks the folder `custom` in the user's data directory-      for a matching script if it can't find one in the local directory.-      Previously, the `readers` and `writers` data directories were-      searched for custom readers and writers, respectively. Scripts in-      those directories must be moved to the `custom` folder.-    + Custom readers used to implement a fallback behavior that allowed to-      consume just a string value as input to the `Reader` function. This-      has been removed, the first argument is now always a list of-      sources. Use `tostring` on that argument to get a string.--  * New module Text.Pandoc.Writers.ChunkedHTML,-    exporting `writeChunkedHtml` [API change].--  * We now set the `pandoc-version` variable centrally rather-    than in the writers.  One effect is the man writer now emits-    a comment with the pandoc version.--  * pandoc-server:--    + Add simple CORS support to pandoc-server (#8427).-    + Print message to stderr when starting the server.--  * Docx reader:--    + Mark unnumbered headings with class `unnumbered` (#8148,-      Albert Krewinkel). This change ensures good conversion-      results when converting with `--number-sections`.-    + Support parsing of highlighted text.-    + Fix handling of `oMathPara` in `w:p` with other content (#8483).--  * ODT reader:--    + Fix relative links. ODT adds a `../` to relative links-      (see #3524); this needs to be removed when converting from ODT.-    + Handle "section" elements (#8409).-    + Rename Text.Pandoc.Readers.Odt -> Text.Pandoc.Readers.ODT,-      for consistency with Writers.ODT. Rename `readOdt` -> `readODT`.-      [API change]--  * DocBook reader:--    + Support href on link even in a fragment (#8437).-      (We now just look for an `href` attribute without-      worrying about the namespace.)-    + Parse title from imageobject/objectinfo (#8437).--  * JATS reader:--    + Handle uri element in references (#8270).--  * Ipynb reader:--    + Add cell id to attachment filename when storing in MediaBag (#8415).-      Otherwise attachments with the same name can overwrite each other.--  * LaTeX reader:--    + Skip parenthenized args of toprule, midrule, etc (#8242).-    + Handle `##` macro arguments properly (#8243).-    + Remove unused function `toksToString` in Parsing module.-    + Support more `soul` commands, including `\hl`.-    + Add `unnumbered` class for `\part*` (#8447)-    + Fix `TEXINPUTS` handling (#8392). If `TEXINPUTS` ends with `:`,-      then the system default `TEXINPUTS` is added.  We handle this by-      just adding the working directory in this case.-    + Parse short table caption (see jgm/pandoc-types#103).-      This is not too useful yet, because writers don't do anything with-      the short caption.--  * MediaWiki reader:--    + Parse table cell with attributess, to support rowspan, colspan (#8231,-      Ruqi).-    + Refine "blending" rules for MediaWiki links (#8525, Ruqi).-      The rules for "blending" characters outside a link into the link are-      described here: https://en.wikipedia.org/wiki/Help:Wikitext#Blend_link-      These pose a problem for CJK languages, which generally don't have-      spaces after links. However, it turns out that the blending behavior, as-      implemented on Wikipedia, is (contrary to the documentation) only for-      ASCII letters. This commit implements that restriction, which fixes-      the problem for CJK.--  * HTML reader:--    + Fix regression for `<tt>` (#8330). It was no longer being parsed as-      Code (Justin Wood).--  * RST reader:--    + Support `mark` role for round-trip.--  * Textile reader:--    + Support linked images (#8541).-    + Fix strong emph ending with link (#8540).-    + Adding a Parser to look for ordered list start attribute numbers-      if any (#2465, vkraven).-    + Handle empty paragraphs (#8487). Also, if attributes are added-      explicitly to a paragraph, put it in a Div with the attributes.--  * Markdown reader:--    + Allow fenced code block "bare" language to be combined-      with attributes (#8174, Siphalor), e.g.-      ````-      ```haskell {.class #id}-      ```-      ````-    + Allow table caption labels to start with lowercase `t` (#8259).-    + Grid tables: allow specifying a table foot by enclosing it with-      part separator lines, i.e., row separator lines consisting only-      of `+` and `=` characters (#8257, Albert Krewinkel). E.g.:-      ```-      +------+-------+-      | Item | Price |-      +======+=======+-      | Eggs | 5£    |-      +------+-------+-      | Spam | 3£    |-      +======+=======+-      | Sum  | 8£    |-      +======+=======+-      ```-    + Fix `implicit_header_references` with duplicate headings (#8300).-      Documentation says that when more than one heading has the same text,-      an implicit reference `[Heading text][]` refers to the first one.-      Previously pandoc linked to the last one instead. This patch-      makes pandoc conform to the documented behavior.-    + Parse highlighted text inside `==..==` if `mark` extension enabled.--  * Org reader:--    + Allow org-ref v2 citations with `&` prefix (#8302).-    + Make `#+pandoc-emphasis-pre` work as expected (#8360, Amir Dekel).--  * BibTeX reader:--    + Fix handling of `%` in `url` field (#7678).-      `%` does not function as a comment character inside `url`-      (where URL-encoding is common).-    + Allow `url` field in `bibtex` as well as `biblatex` (#8287).-      This field is not officially supported for BibTeX, but many styles-      can handle it (<https://www.bibtex.com/f/url-field/>),-      and others will ignore it.-    + Support `software` type in biblatex <-> CSL conversions (#8504).-    + Make sure `version` field comes through in biblatex (#8504).--  * BibTeX writer:--    + Pass through `url` even for `bibtex` (#8287).--  * Org writer:--    + Pass through unknown languages in code blocks (#8278), instead-      of producing `begin_example`.-    + Use span attributes `tag-name` in headers as tags (#8513, Albert-      Krewinkel). This enables round-tripping of tags in Org headings.--  * EndNote reader:--    + Better error when parsing EndNote references fails.--  * DocBook writer:--    + Rename Text.Pandoc.Writers.Docbook -> Text.Pandoc.Writers.DocBook.-      Rename `writeDocbook` -> `writeDocBook`, for consistency with-      the DocBook reader's naming. [API change]-    + Fix position of textobject (#8437). It is a child of-      `inlinemediaobject`, not `imageobject`.-    + Add regression tests for #8437.-    + Render image alt text using textobject element (#8437).-    + Don't indent contents of title element.-    + Store "unnumbered" class in DocBook role attribute (#1402, lifeunleaded).--  * ConTeXt writer (Albert Krewinkel):--    + Support syntax highlighting for code.-    + Always use `\type` for inline code.-      Inline codes that contained curly braces where previously rendered-      with `\mono`; this led to unexpected results when the presentation-      of `\type` was customized, as those changes would not have-      been applied to code rendered with `\mono`.-    + Add support for unlisted, unnumbered headings (#8486).-    + Support `tagging` extension (Albert Krewinkel). Paragraphs-      are enclosed by `\bpar` and `\epar` commands, and `highlight` commands-      are used for emphasis. This results in much better tagging in PDF output.--  * LaTeX writer:--    + Do not repeat caption on headless tables (Albert Krewinkel).-      The caption of headless tables was repeated on each page that-      contained part of the table. It is now made part of the-      "first head", i.e. the table head that is printed only once.-    + Add separator line between table's body and its foot-      (Albert Krewinkel).-    + Ignore languages with no babel equivalent, instead of generating an-      invalid command in the preamble (#8325).-    + Use `\includesvg` for SVGs and include the `svg` package (#8334).-    + Use `soul` instead of `ulem` for strikeout, underline (#8411).-      This handles things like hyphenation, line breaks, and nonbreaking-      spaces better.-    + Use `\toprule\noalign{}` instead of `\toprule()` in tables,-      and similarly for `\midrule` and `\bottomrule` (#8223).-      This facilitates redefining `\toprule`, `\midrule`, and `\bottomrule`-      without needing to gobble the ()s. (Those who redefine these macros-      on the assumption that they will be followed by `()` may need to-      change their definitions.)-    + Support highlighted text for Span with class `mark`.--  * JATS writer:--    + Use `<break/>` for LineBreak in the limited contexts that accept it-      (#8344).-    + Officially deprecate `writeJATS` in favor of `writeJatsArchiving`.--  * RTF writer:--    + Add space after unicode escape commands (#8264).  This fixes-      a bug that caused characters to disappear after unicode escapes.--  * RST writer:--    + Render tables as list tables when the `--list-tables` option is-      specified (`writerListTables`) (#4564, Francesco Occhipinti).-    + Improve inline escaping rules (#8380).-    + Use special `mark` role for Span with class `mark`.--  * Commonmark writer:--    + Ensure that we don't have blank lines in raw HTML (#8307).--  * HTML writer:--    + Only add role attribute in HTML5 (#8241). It is not valid in HTML4.-    + Avoid aria-hidden in code blocks for HTML4 (#8241).-    + Only treat `. . .` as a slide pause in slides, and not in regular-      HTML output (#8281).-    + Properly merge classes for headings of level > 6 (#8363).-    + Prevent `<a>` inside `<a>` (#7585). If a link text contains a link,-      we replace it with a span.-    + Replace deprecated aria roles for bibliography entries (#8354).-      `doc-biblioentry` -> `listitem`, `doc-bibliography` -> `list`.-    + Remove obsolete stuff about mathml-script.-      This was a shim we used to include for mathml support.-      We don't do anything with this any more, so this is dead code.-    + Include math links if there are raw commands or environments that-      can be interpreted as math e.g. by MathJax (#8469).-    + Add prooftree to list of math environments (#8462). This will cause-      raw LaTeX prooftree environments to be rendered appropriately when-      `--mathjax` is used.--  * HTML, Markdown writers: filter out empty class attributes (#8251).-    These should not be generated by any pandoc readers, but they-    might be produced programatically.+## pandoc 3.10 (2026-06-03)++  * Add `--typst-input` CLI option (#11588). This allows one to+    pass parameters to typst, which are available at `sys.inputs`,+    just as `typst` itself does with its `--input` option.++  * Avoid trailing spaces in `--help` output (#11623).++  * Make groff the default pdf-engine for `ms` output (#11558).+    Formerly it was pdfroff.++  * Set default User-Agent request header to `pandoc/VERSION`.+    This can be overridden using the `--request-header` option.++  * Markdown reader:++     + Allow grid tables to be indented (#11671, Johan Larsson). Like+      the other table syntaxes (pipe, simple, and multiline tables)+      and block-level constructs generally, a grid table may now be+      indented by up to three spaces and still be recognized as a+      table. Previously the grid-table parser required the table to+      begin at the left margin, so an indented grid table was parsed+      as a paragraph.+    + Fix calculation of column widths for default columns in grid tables+      (#11664). This fixes a bug which produced too-narrow columns in some+      cases.+    + Don't produce empty Raw element with `--strip-comments` (#11625).+    + Fix quotes in inline notes (#11613, Andrew Dunning).+    + Allow spaces inside attributes in super/sub (#11589).+    + Simplify `checkNotes`, remove dead code+    + Various small performance optimizations.++  * HTML reader:++    + Parse aside as a Div with class "aside" (instead of using+      raw HTML) (#11626).+    + Add "header" class to Divs created from headers.++  * Docx reader:++    + Fix bug in bitmask checking (#8299). This led to some table rows+      being wrongly considered header rows.+    + Improve treatment of `tblHeader` element (#8299).+      If `tblHeader` exists but has `w:val="0"`, then don't consider+      the element a header.+    + With `citations` extension, prefer `citation-key` as the key for+      item data, if it is defined (#11581; cf. #10366, #11567). The `id` key+      used by Zotero is not exposed by their API and is generally not what+      is wanted when converting to biblatex.+    + Don't look to `ext` tags for image extent (#11580).+      This reverts a change from 7ff1b798c4e6681ef9050899442d80883116573a.+      The change was mistaken and could cause images to be parsed with+      the wrong sizes.++  * Man reader:++    + Support `auto_identifiers`, `gfm_auto_identifiers`, and+      `ascii_identifiers` extensions (#8852, Meher Chaitanya).+      Section headings parsed from .SH and .SS macros now receive+      auto-generated id attributes when the extension is enabled (as+      it is by default). This enables `--toc` to produce working anchor links.+    + Better handling of `.TP` macro (#11668). We parse these as+      DefinitionList items, but we previously sometimes stopped prematurely+      in including material in the definition.  We should include everything+      until we hit a new indentation-changing macro.++  * Roff reader:++    + Handle `\` line continuation in table cells (#11635).++  * LaTeX reader:++    + Evaluate theorem name when used rather than evaluating it when+      the `\newtheorem` command is encountered (#11608). It may include+      macros only defined later.+    + Put identifier from label on table attributes rather than adding+      an enclosing Div (#11604).++  * Typst reader:++    + Fix issue parsing figure inside rotate or box (#11598).+    + Implement "rotate" as pass-through (#11531). Information about the+      angle is encoded in an attribute of an enclosing span or div.++  * RTF reader:++    + Fix tables parsed as deeply nested tables (#11682).++  * Docx writer:++    + Fix display of paragraph with just inline math (#11674).+      Word displays a paragraph containing just one inline math+      element as if it were display math. We don't want that,+      so we add a zero-width space to defeat this behavior.+    + Fix FirstParagraph style lost after heading with footnote (#11573).+    + Fix empty keywords in core document properties (#11666, Sai Asish Y).++  * OpenDocument/ODT writer:++    + Use predefined styles (#9316, #5086, #2747, #3426, #7336).+      Previously the OpenDocument writer emitted a fresh automatic+      style (L1..Ln, P1..Pn, T1..Tn) for nearly every list, list-item+      paragraph, block quote, preformatted block, and inline text+      style. This commit teaches the writer to reference the+      predefined styles that LibreOffice ships and that pandoc's+      reference.odt now exports:++      - Bullet lists use `List_20_1`; ordered lists with default start and+        decimal format use `Numbering_20_1`.  Non-default ordered lists+        generate a single named override style (`Pandoc_Numbering_N`)+        memoised by (ListNumberStyle, ListNumberDelim); a non-default start+        value with the default format is expressed via `text:start-value`+        on the `text:list` element instead of a new style.+      - List-item paragraphs use `List_20_Bullet[_Tight]` and+        `List_20_Number[_Tight]`.  The Tight variants are pandoc-specific+        (zero top/bottom margin) and are injected into the user's+        reference.odt if missing, just like the Skylighting token styles.+      - Block quotes use the predefined `Quotations` paragraph style+        directly.  Nested block quotes use a single automatic style that+        inherits from Quotations and only adds extra margin-left, so a list+        inside a block quote now inherits its container's indent (#2747).+      - Preformatted blocks use `Preformatted_20_Text` directly.+      - Emphasis, Strong, Strikeout, Subscript, Superscript and Code spans+        use the predefined `Emphasis`, `Strong_20_Emphasis`, `Strikeout`,+        `Subscript`, `Superscript` and `Source_20_Text` text styles.+      - `paraStyle`/`paraStyleFromParent` no longer emit a wrapper automatic+        style when its only attribute would be `parent-style-name`; the+        parent name is returned directly.++  * EPUB writer:++    + Support multiple EPUB versions for raw content (#11628,+      nibras shami). This change ensures that raw content marked `epub2`+      will appear in (only) EPUBv2 output and content marked `epub3` will+      appear in (only) EPUBv3 output.++  * Typst writer:++    + Add zero-width space before a Span label if otherwise the label+      doesn't come after anything (#11568). (In this case typst will+      raise an error.)+    + Add newline after `#set text` directive (#11583). This ensures that+      blocks such as lists are parsed correctly after a `set text`.++  * LaTeX writer:++    + Fix `fr-CA` babel language mapping (#11575, Christophe+      Dervieux). Map fr-CA to `french` instead of deprecated `canadien`.+      The babel-french package's `canadien.ldf` is deprecated and+      broken: it never calls `\ldf@finish`, so `\bbl@main@language` is+      left undefined, causing babel to crash at `\begin{document}`.+      Since `canadien` was always just an unconditional alias for+      `french`, use `french` directly.++  * MediaWiki writer:++    + Handle some technically malformed URLs (#11562).+    + Fix escaping to avoid accidental lists (#11563).++  * Markdown writer:++    + Fix spacing issues with definition lists.+      - Properly handle the case where the first item is an indented+        code block (#11542).+      - Use correct indentation when `four_space_rule` extension is+        disabled.+    + Escape `:::` to avoid triggering unintended divs (#11571).++  * Man writer:++   + Don't run together successive definitions in a tight definition list+     with multiple definitions after a term (#11547).++  * Text.Pandoc.Writers.Shared:++    + `htmlAttrs`: use `data-` prefix when needed (#11680). This now+      behaves like the HTML writer, adding the `data-` prefix for+      custom attributes. This will affect, e.g., the mediawiki writer.++  * Text.Pandoc.Error:++    + Display IOError without stack trace (#11676).+    + Use single quotes around paths and format names (#11645) in+      displayed messages.++  * Text.Pandoc.App.Opt:++    + Opt has a new field `optTypstInputs` [API change].++  * Text.Pandoc.Options:++    + Change `defaultMathJaxURL` to use MathJax v4 (#11669).+    + ReaderOptions has a new field `readerTypstInputs` [API change].++  * Text.Pandoc.Citeproc.BibTeX:++    + Prevent wrong combination of `subtitle` and `titleaddon` with+      `maintitle` (#11677, Amir Dekel). When `maintitle` is present, `subtitle`+      should not be added to `title`, but only to `volume-title`.+    + BibLaTeX `inbook` should be CSL `book`, not `chapter` (#11552).+    + Allow `doi` field in bibtex (input and output) (#11617, Thomas Hodson).++  * Text.Pandoc.Translations:++    + Find lang-script type translations (#11648).+      E.g. for `zh-Hant-TW` look for (in order) `zh-Hant-TW.yaml`,+      `zh-Hant.yaml`, `zh.yaml`.++  * Text.Pandoc.Parsing:++    + Various small optimizations.+    + Fix bug in `extractIdClass` to ensure that both `id` and+      `class` are stripped from key/value attributes..++  * Text.Pandoc.Shared:++    + Various small optimizations.++  * ODT reference doc: demonstrate predefined styles (310327).+    This mirrors the demonstration content already present in+    the Word reference doc.++  * HTML templates:++    + Include pandoc-version in generator meta tag (#11624).+    + Styles: make screen-only CSS conditional (#11524, Keenan Brock).++  * EPUB templates:++    + Add dir attribute to html element (#11554).++  * LaTeX template: Define `\xmpquote` if not defined (#11528).+    `\xmpquote` is defined by the hyperref driver hyperxmp; we need a+    fallback for those who aren't using that.++  * Lua subsystem:++    + Add constructor `pandoc.TableBody`.++  * doc/lua-filters.md: Re-indent definition list items+    (Albert Krewinkel).++  * wasm/index.js: include filter to embed images for pdf-via-typst.+    Auto-inject `embed_images` filter for PDF via Typst. Otherwise+    conversion fails because we can't write the images in a temporary+    directory in the WASM sandbox. See jgm/pandoc#11584.++  * Fix test suite parallel execution failures (#11566).++  * linux/make_artifacts.sh: add `loong64` support (#11597,+    Olivier Benz).++  * `bash_completion.tpl`: add `groff` to `--pdf-engine` completions (#11555).++  * MANUAL.txt:++    + Improve description of reference links (#11643).+    + Update instructions for modifying reference.docx+      (#11600, Dan Jacobson). Mention LibreOffice as an alternative.+    + Clarify indentation rules for definition lists (#11542).+    + Move `--sandbox` to general options.+    + Reword restrictions on YAML metadata in commonmark (#11561).++  * Bump upper bound for time, tls, aeson.++  * Use latest releases of doclayout, asciidoc, texmath, typst,+    typst-symbols, pandoc-types, citeproc, commonmark, commonmark-pandoc,+    commonmark-extensions.++  * Add missing NAME heading to pandoc-lua, pandoc-server man pages (#11634).++## pandoc 3.9.0.2 (2026-03-19)++  * Typst template: fix regression introduced in 3.9.0.1 (#11538).++## 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.+    + Support `w:gridBefore` table row property (#11464, Jan Tojnar).++  * 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).++  * 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+    pandoc.wasm`.) A stanza in `cabal.project` contains the+    necessary build modifications. We owe this almost entirely to+    TerrorJack, who created the original proof of context and+    came up with the necessary build flags and patches to some+    dependencies.++    `pandoc.wasm` has almost all the power of regular pandoc. The+    main limitations is that it operates in a WASM sandbox and thus+    cannot use HTTP to fetch resources and cannot run system commands.+    As a result, JSON filters cannot be used, `--embed-resources`+    works only with resources that have been explicitly provided in+    the WASM sandbox, and PDFs cannot be produced (since that requires+    running external commands). However, Lua filters can be used,+    as long as they do not run system commands.++    A JavaScript bridge module, `wasm/pandoc.js`, is provided; this+    handles the setup necessary to run `pandoc.wasm` in a browser.++    In addition, a full-featured GUI interface is provided in the+    `wasm` subdirectory. `make serve` from that directory and it+    will run locally, or visit <https://pandoc.org/app>.  Note that+    once the relevant code has been downloaded by the browser, it runs+    entirely in the browser, and the conversions never touch a server.+    The GUI was developed in interaction with Claude Code.  This app+    includes a WASM version of Typst and can produce PDF output via+    Typst.++  * Defaults files may now be either JSON or YAML (though a `.yaml`+    extension will still be assumed if the file has no extension).+    The structure of a JSON defaults file is isomorphic to that of+    a YAML defaults file.++  * Variable expansion now works even for the `defaults` field of+    defaults files (#8024, Jacob Larkin).++  * `--extract-media` will now create a zip archive containing the media+    (instead of a directory) if the path provided has a `.zip` extension.++  * Processing with `--citeproc` is now affected by a+    `reset-citation-positions` class on headings. When the+    `reset-citation-positions` class is added to a top-level+    heading, `--citeproc` will reset position information at that+    point in the document. This is needed in order to ensure that+    the first citation in a chapter to a work that has been cited+    in a previous chapter will not be in abbreviated form.++  * RST reader:++    + Fix definition lists where term ends with `-` (#11323).+      This reverts some old code giving special treatment to+      lines ending in hyphens; I don't understand why it was+      there, because rst2html does not seem to do this.++  * HTML reader:++    + Revert an earlier change that caused style tags in the body+      to be ignored (#10643, #11246).+    + Parse inline style elements as RawInline (#10643, #11246).++  * Markdown reader:++    + Fix parsing of inline math (`$...$`) (#11311, benniekiss).+      Do not allow blank lines before closing `$` delimiter. This brings the+      parser in line with the documentation.+    + Allow superscripted spans (#11409). These were being parsed as inline+      notes. Now we disallow an inline note followed by+      attributes, as this is almost certainly meant to be a span.+    + Support `alerts` extension for pandoc markdown (#9716). It is not+      enabled by default.++  * MediaWiki reader:++    + Add behavior switches support (#11354, Anton Melnikov).+      They add a field to metadata without producing any text.+    + Handle non-recognized tags as plain text (#11299).+    + Better handling of inline tags (#11299). `<mark>`, `<var>`,+      `<samp>`, and `<kbd>` now produce Code or Span elements with+      classes, which can be handled by multiple output formats,+      instead of simply being parsed as raw HTML tags.++  * RTF reader:++    + Ensure a new paragraph on `\pard` (#11361, Tuong Nguyen Manh). New+      paragraphs may start with `\pard` alone without an explicit paragraph+      break with `\par` preceding it.+    + Improve hyperlink parsing more (#10942, Tuong Nguyen Manh).+      Both the field instruction and its result may be ungrouped.+    + Fix bug where list items were incorporated into a following table+      (#11364).++  * ODT reader:++    + Add table row and column spans (#11366, Tuong Nguyen Manh).+      Parse the number-rows-spanned and number-columns-spanned attributes to+      create Cells for the Table.++  * DocBook reader:++    + Support "role" attribute (#11255, Yann Trividic). The `role`+      attribute is parsed and added to Pandoc AST elements, using a+      wrapper Div if needed.+    + Omit empty title when not required (#11422).+      This affects example and sidebar elements.+    + Fix adding wrong metadata (#11300, Tuong Nguyen Manh). Now+      keep track of the current element stack to only add metadata+      if inside an appropriate parent element.++  * DocBook/JATS reader:++    + Don't export surrounding space from inline elements (#11398). Previously+      we would export leading and trailing space inside elements like+      emphasis or ulink so they appeared outside the resulting pandoc Inline+      (Emph or Link). This is not really motivated; DocBook and XML in general+      treats leading and trailing whitespace in this context as significant.++  * Docx reader:++    + Handle tables without `tblGrid` (#11380).+    + Look inside v:rect as well as v:shape (#11412).++  * LaTeX reader:++    + Handle more quote macros from fontspec and ngerman babel (#6120).++  * Org reader:++    + Don't include 'example' class when parsing org example blocks (#11339).+      These are just unmarked code blocks.++  * Texinfo writer:++    + Improve handling of certain code blocks (#11312).+      MediaWiki, for example, will parse a code block containing+      formatting as a sequence of Code elements separated by+      LineBreaks. For this we now use a texinfo example block.++  * Typst writer:++    + Escape hyphens when needed (#11334).++  * HTML writer:++    + Include all classes on highlighted code elements (#11423). Previously,+      only the language class was included, and the others were dropped.+    + Slide formats: Make `. . .` pause work in nested blocks (#7201, #7582).+    + For revealjs, add idiomatic highlight.js support (#11420, Claude Opus 4.5).+      When using `--syntax-highlighting=idiomatic` with reveal.js output, pandoc+      now generates HTML compatible with reveal.js's built-in highlight.js plugin:+      Code blocks use `<pre><code class="language-X">` format.+      The template loads highlight.js CSS, JS, and RevealHighlight plugin.++  * Markdown writer:++    + Ensure that `\ ` line breaks are used for commonmark.+    + Use setext for headers containing line breaks for commonmark (#11341).+    + Allow display math to start/end with space (#11384).+      This reverts to earlier < 3.7 behavior.+    + Properly handle tables with footers (#11416).++  * JATS writer:++    + Fix XML output for nested figures (#11362, Albert Krewinkel).+      Subfigures are now wrapped inside a `<fig-group>` element. Furthermore,+      figure content that isn't allowed as children of `<fig>` elements, such as+      raw text, gets wrapped in `<p>` elements to ensure schema-conforming XML.++  * AsciiDoc writer:++    + Use doubled delims in more contexts (#11362). Also escape the `#` character.+    + Use a span with role for SmallCaps (#11374).+    + Export spaces inside delimited constructs like emph.++  * Docx writer:++    + Skip directory entries when building media overrides (#11379, You Jiangbin).+      Pandoc's docx writer was previously adding an `<Override>` for+      `/word/media/` in `[Content_Types].xml` when the reference doc contains+      media, which violates OPC rules and causes Word to report corruption.+    + Refactor the monolithic `writeDocx` into a number of smaller functions+      (Claude Opus 4.5).+    + Replace generic XML traversal with direct path navigation (Claude+      Opus 4.5). Instead of using Data.Generics `everywhere` to traverse the+      entire XML tree when setting language attributes, navigate directly to+      the known path `w:docDefaults/w:rPr/w:lang`. This is more efficient and+      removes the dependency on `Data.Generics`.++  * EPUB writer:++    + Don't use footnote backlinks for EPUBv3. Here we use aside elements,+      which are popups, and the backlinks are not needed; in some readers+      they cause a redundant number to appear, since the reader adds a note number.++  * MediaWiki writer:++    + Use Doc Text instead of Text for document construction (with Claude Open 4.5).+      This refactors the writer to use Text.DocLayout combinators (vcat, hcat,+      literal, blankline, cr, chomp) for building output, following the pattern+      used by other text format writers (RST, Markdown, Man). This enables+      better control over line spacing and paragraph separation.+    + Improve blank space around div elements (#11417). This is merely cosmetic.++  * PPTX writer:++    + Support notes field in metadata for title slide (#5844, Chris Callison-Burch).+      This adds support for a `notes` field in the YAML metadata block that will+      be used as speaker notes for the title slide in PowerPoint output.+      Previously, there was no way to add speaker notes to the title slide since+      it is generated from metadata rather than from content blocks.++  * LaTeX writer:++    + Add PDF standard support via DocumentMetadata (#11407, Gordon Woodhull+      with Claude Opus 4.5). The `pdfstandard` variable can be+      used to specify PDF standards (PDF/A, PDF/X, PDF/UA) in+      LaTeX output. This uses LaTeX's `\DocumentMetadata`+      command, which requires LuaLaTeX. PDF version requirements+      are automatically inferred, but can be explicitly overridden.+      Automatic tagging is added for standards that require it.++  * Typst template:++    + Fix keywords usage. (#11317, har7an).+    + Disable hyphenation for title, subtitle (#11375).+    + Improve accessibility of definition lists (#11436). Before this+      change, our show rule produced an error when typst was run with+      `--pdf-standard=ua1`.++  * HTML5 template:++    + Conditionally include lang attribute, instead of providing+      it with an empty value.++  * JATS template:++    + Fix author prefix placeholder (#11381, Christophe Dervieux).++  * Text.Pandoc.Citeproc:++    + Fix biblatex parsing of `@commentary` entries (#11322).+    + Fix typo affecting `jurisdiction` biblatex type (#11321).+    + Avoid adding an extra space at the beginning of a Cite.++  * Text.Pandoc.Shared:++    + Export `hasLineBreaks` [API change]. This was formerly+      defined in the DocBook writer but more generally useful.++  * Text.Pandoc.PDF:++    + Add `SOURCE_DATE_EPOCH` to verbose environment variable info.++  * Text.Pandoc.Class:++    + Factor out `openURL` into Text.Pandoc.Class.IO.HTTP (unexported module).++  * Lua subsystem (Albert Krewinkel):++    + Mark readers and writers with their types (#11367). The+      `pandoc.readers` and `pandoc.writers` maps now have string values+      instead of boolean values. The string signals the type of the+      reader/writer, `"text"` for TextReader/TextWriter and `"bytestring"`+      for ByteStringReader/ByteStringWriter.+    + Support equallity checks of LogMessage objects.+    + Add function `pandoc.with_state` (#10859). The function allows+      to run a callback with a modified pandoc state. This provides+      the ability to temporarily modify the resource path, the user+      data directory, and the HTTP request headers.+    + Let `pandoc.with_state` error on unknown options (#11376).+    + Add function `pandoc.utils.documentation` (#10999).+      This is now used to generate much of the Lua API documentation.++  * Text.Pandoc.App:++    + Remove redundant check for asciidoc in UnknownReader.++  * Text.Pandoc.Logging:++    + Add `pretty` field to ToJSON instance for LogMessage.+      This just reproduces the output of `logMessage`, for convenience for those+      who are using the JSON output outside of Haskell.++  * Text.Pandoc.Error:++    + Change PandocHttpError constructor to take a Text instead of an+      HttpException as the second argument (see #10980) [API change]+      Motivation: exposing HttpException in the public API makes it+      difficult to provide a version of pandoc that can be compiled+      to wasm, which currently can't handle the network libraries.+    + Define `displayException` for PandocError. This is a behavior change,+      not an API change, since there was already a definition that defaulted+      to using Show. The change here is that we use `renderError` for+      a more human-readable version.++  * Drop support for compilation with GHC versions < 9.6.++  * Use released citeproc 0.13, djot 0.1.3, skylighting-format-blaze-html+    0.1.2 (see #11423), texmath 0.13.1, asciidoc 0.1.0.1, typst-0.9,+    hslua 2.5.++  * Add `-Wno-deriving-typeble` to cabal ghc-options for ghc >= 9.12.++  * Add `http` cabal flag (#10980). This allows pandoc to be+    compiled without support for making HTTP requests, which is+    useful when WASM is the target.++  * pandoc-lua-engine has a new build flag `repl`, allowing support+    for the Lua repl to be disabled for the wasm build.++  * We now sign Windows artifacts with a code signing+    certificate provided by SignPath.++  * Mention Excel in cabal description.++  * Makefile: remove some obsolete targets.++  * MANUAL.txt:++    + Fix typo about `--chunk-template` (#11358, Albert Lei).+    + Fix link for bbcode_steam (#11389).+    + Small rewrite of syntax-highlighting info.+    + Fix defaults.yaml example for `wrap`.++  * Fix a few mistakes in the contributing docs. (#11318, har7an).++  * Fix a couple small errors in `doc/lua-filters.md`,+    `doc/custom-writers.md`, and `doc/custom-readers.md`+    (#11408, #11388).++## pandoc 3.8.3 (2025-12-01)++  * Add `asciidoc` as an input format (#1456).++  * Add `xlsx` (Microsoft Excel) as an input format (Anton Antich).+    Each worksheet turns into a section containing a table.++  * Add `pptx` (PowerPoint) as new input format (Anton Antich).++  * Add `bbcode` as a new output format (#11242, reptee). Several variants+    of BBCode are also supported: `bbcode_fluxbb` (FluxBB), `bbcode_phpbb`+    (phpBB), `bbcode_steam` (Hubzilla), `bbcode_hubzilla` (Hubzilla),+    and `bbcode_xenforo` (xenForo).++  * New exported module Text.Pandoc.Readers.AsciiDoc,+    exporting `readAsciiDoc` [API change].++  * New module `Text.Pandoc.Readers.Pptx`,+    exporting `readPptx` (Anton Antich) [API change].++  * New module `Text.Pandoc.Readers.Xlsx`,+    exporting `readXlsx` (Anton Antich) [API change].++  * LaTeX reader:++    + Revert `\linebreak` as LineBreak (#11272). `\linebreak` is more+      of a hint, it shouldn't produce a hard break.+    + Better handling of `\makeatletter` in parsing raw LaTeX (#11270).+    + Fix spurious paragraph breaks in math environments (#11265,+      Emmanuel Ferdman). Previously, a math environment with extra+      space before the `\end` would get rendered with a blank line,+      which LaTeX treats as a paragraph break.+    + Change type on `rawLaTeXParser` in Text.Pandoc.LaTeX.Parsing.+      The preparser doesn't need to return a value.+    + Fix `rawTeXParser` (#11253).  Make macro expansion in raw LaTeX+      depend on the setting of the `latex_macros` extension.  Previously+      macros were always expanded, even in raw TeX in markdown. In+      addition, there was previously a bug that caused content to be+      garbled in certain cases.+    + Handle `ifstrequal` at a lower level, like the other `if`+      commands (#11253).+    + Move `ifstrequal`, `iftoggle`, etc., which were misplaced in+      `environments`, to `blockCommands`, so these commands work properly.++  * Docx reader:++    + Handle REF link instruction (#11296, Ezwal).+    + Check recursively for caption styles (Albert Krewinkel).+      The docx reader uses caption styles to identify figures and+      captioned tables. It now checks for known caption styles in the+      full styles hierarchy of a paragraph instead of just checking+      the style directly. This allows to recognize caption styles that+      are built on top of the basic *caption* style, as is sometimes+      the case in sophisticated styles.++  * Markdown reader:++    + Fix performance issue in links with `'` (#10880).++  * Typst reader:++    + Handle document metadata and `#title` (jgm/typst-hs#80).+      Note that previously, the typst reader never returned document+      metadata.  Now it does, even if the typst document does not contain+      a `#title` function that would result in actually printing the+      title block.++  * Djot reader:++    + Add Space elements (#11250). Previously we just got big+      Str elements with spaces included. But many pandoc writers+      assume that breakable spaces will be Space elements, and this+      is also required for automatic wrapping.++  * RST reader:++    + Correctly handle intraword emphasis (#11309).++  * Text.Pandoc.Readers:++    + Export `readAsciiDoc`, `readXlsx`, `readPptx` [API change].++  * New module Text.Pandoc.Writers.BBCode, exporting+    `writeBBCode`,  `writeBBCodeSteam`, `writeBBCodeFluxBB`,+    `writeBBCodePhpBB`, `writeBBCodeHubzilla`, `writeBBCodeXenforo`+    [API change].++  * LaTeX writer:++    + Make level 1-3 headings work inside blockquotes (#11281, James Barlow).+    + Remove `split` from list of math environments (#11274).+    + Improve handling of math environments in tex math (#11266).++  * HTML writer:++    + Add reveal.js `scroll` and `scrollSnap` options to writer and+      template (#10052, Asliddinbek Azizovich).+    + Use 'defer' when including mathjax script, as recommended in+      MathJax docs (#11292).++  * ANSI writer:++    + Apply row spans in tables (#10149, Tuong Nguyen Manh).+      The ANSI writer is now able to keep track of row spans and apply+      them in rows.++  * Pptx writer:++    + Handle reference doc without slides (#7536, Tuong Nguyen Manh).++  * AsciiDoc writer:++    + Add more table features (#11267, Tuong Nguyen Manh):+      Row span and column span, footer row, individual horizontal+      cell alignment.++  * Typst template:++    + Fix font for compatibility with typst 0.14, which doesn't+      permit an empty array for `font` (#11238).+    + Re-add `columns` to typst template (#11259), fixing a+      pandoc 3.8 regression.+    + Fix syntax for bibliography inclusion (#11233, Mickaël Canouil).+      Previously the syntax was wrong when multiple bibliography files+      were specified. Typst expects an array.++  * Text.Pandoc.Writers:++    + Export `writeBBCode`,  `writeBBCodeSteam`, `writeBBCodeFluxBB`,+      `writeBBCodePhpBB`, `writeBBCodeHubzilla`, `writeBBCodeXenforo`+      [API change].++  * Text.Pandoc.Writers.Shared:++    + Add functions `insertCurrentSpansAtColumn`, `takePreviousSpansAtColumn`+      and `decrementTrailingRowSpans` for applying and keeping track of+      RowSpans over multiple rows (#10149, Tuong Nguyen Manh). [API change]++  * Text.Pandoc.Logging:++    + Change message for missing HTML title warning (#11307). Suggest+      setting the `pagetitle` variable instead of setting `title` in metadata.++  * Lua subsystem:++    + Preserve common state of custom Lua readers (Albert Krewinkel).+      The common state is transferred to Lua when calling a custom Lua+      reader, and is now also transferred back after the reader has+      finished. This ensures that info messages, warnings, and+      mediabag entries are available to the main program and all+      subsequent processing steps.++  * Text.Pandoc.PDF:++    + Avoid converting SVG to PDF when non-TeX PDF engine is used (#11275).+      This fixes a 3.8 regression, which caused documents with SVGs to+      raise an error when converted to PDF using WeasyPrint.+    + Fix a 3.8 regression with typst and smart quotes (#11256).+      Before 3.8, the default behavior when producing a PDF `-t typst`+      was to produce smart quotes according to typst's defaults.+      (This could be defeated by specifying `-t typst-smart`.)+      This behavior broke in 3.8 because of a change to Text.Pandoc.PDF.+      This change caused `smart` to be disabled for all formats when+      producing PDFs, when before it was only disable for TeX-based+      formats (to avoid bad ligatures). This commit restores the old+      behavior. Possibly the regression also other affects other+      non-TeX formats, e.g. HTML.++  * Text.Pandoc.Shared:++    + Add functions `allRowsEmpty` and `tableBodiesToRows` from the+      RST writer for reuse in other writers. (Tuong Nguyen Manh) [API+      change].++  * Text.Pandoc.Citeproc:++    + Allow formatting in locator to be transmitted to citeproc.+      We do this indirectly, by rendering the formatting using the+      HTML tags that citeproc recognizes.  Fixes jgm/citeproc#68+      and jgm/citeproc#163. Note that formatting is only possible for+      locators given in the explicit form, surrounded by curly braces.+      It won't work for implicit locators, since these expect+      number-like expressions.++  * New non-exported module Text.Pandoc.Readers.OOXML.Shared+    containing functions factored out from+    Text.Pandoc.Readers.Docx.Util (Anton Antich).++  * Tests: The common file `nativeDiff` has been extracted from+    the Docx and Pptx text files and put in Tests.Helpers.++  * Use asciidoc 0.1, djot 0.1.2.4, texmath 0.13.0.2, typst 0.8.1,+    citeproc 0.12.++  * MANUAL.txt:++    + Improve `implicit_figure` documentation (#11082).+    + Give both forms of options when referring to them (#11306).++  * Update INSTALL.md (#11271).++## pandoc 3.8.2.1 (2025-10-20)++  * HTML reader: allow blank space between open and close `iframe`.++  * RTF reader: improve hyperlink parsing (#11211).++  * Org reader:++    + Parse parameter lists on unknown blocks (#11188, Albert+      Krewinkel). The reader tries to parse the rest of the opening+      line of a block, e.g., `#+begin_myblock …`, as a parameters+      list. It first assumes that the parameters are in lisp-style+      (`:key value`), then alternatively tries to read python-style+      key-value pairs (`key=value`) and falls back to reading the+      entire remaining line as a single `parameter` attribute.+    + Add support for dynamic blocks.++  * Docx writer: properly handle nested comment spans (#8189, #6959,+    mourino).++  * RST writer: Don't use simple tables with RowSpans (#11214,+    Tuong Nguyen Manh).++  * Typst writer: Escape open paren after non-space (#11210).+    This fixes an issue that occurs if an open paren comes+    right after e.g. `#strong[test]`.++  * Typst template: ensure that title block is properly centered (#11221).++  * LaTeX writer/template: small fix for unnumbered tables for+    compatibility with older LaTeX installations (#11201).+    Thanks to @priiduonu for the solution.++  * MANUAL.txt: Fixed missing backtick (#11209, FoxChillz).++  * Correct anchor references to `pandoc.text` module documentation (#11111,+    Emmanuel Ferdman).++  * Fixed golden test regeneration in Docx reader test.++  * Allow unicode-data 0.8.++  * Use citeproc 0.11. This fixes a significant performance+    regression in pandoc 3.8, which was due to a rewrite of the+    default chicago-author-date.csl file. Performance with `--citeproc`+    is now on par with what we had in pandoc 3.7, even with the+    revised Chicago styles.++## pandoc 3.8.2 (2025-10-05)++  * Markdown reader/writer: implement new `table_attributes` extension+    (#10884). When `table_attributes` is enabled (as it is by default for+    pandoc's Markdown), attributes can be attached to a table by+    including them at the end of the caption. Previously the writer+    would emit an identifier in this position, but the reader didn't+    handle it. Now arbitrary attributes are allowed, and they work in+    both the reader and writer.++  * Typst writer: don't add superfluous semicolons (#11196).+    Previously we added semicolons after inline commands not+    followed by spaces, but mainly this was to deal with one issue:+    the presence of a semicolon after an inline command, which+    would be swallowed as a command separator (#9252).+    This commits adopts an approach that should avoid so many+    superfluous semicolons: it escapes semicolons that might come+    right after a command.++  * Typst template: fix 3.8 regression in which links disappear+    (#11194). A template change in 3.8 added a show rule for links which+    causes them to disappear except in special cases.++  * Text.Pandoc.Parsing: rewrite `oneOfStrings` more efficiently.++  * LaTeX writer: Fix strikeout in links (#11192, Tuong Nguyen Manh).+    As in #1294 `\url` and `\href` need to be protected+    inside an mbox for `soul` commands.++  * Text.Pandoc.Extensions: Add `Ext_table_attributes` constructor for+    `Extension` [API change].++  * Use released texmath 0.13.0.1.++  * Update FSF contact information in COPYING (#11183, Bensun Muite).++  * MANUAL.txt: remove some redundancy (#11178, Reuben Thomas).++## pandoc 3.8.1 (2025-09-29)++  * New output format `vimdoc` (Vim documentation format) (#11132, reptee).++    + [API change] Added module Text.Pandoc.Writers.Vimdoc, exporting+      `writeVimdoc`.++  * Markdown reader:++    + Improve superscript/subscript/inline note parsing (#8652).+      We do not allow inline notes to be followed by `(` or `[`.+      Otherwise, we parse inline notes before superscripts.+      Also, the sub/superscript parsers have been adjusted so that they+      really exclude unescaped spaces (as they did not before, when the+      spaces occurred in nested inlines).+    + Fix simple table alignment (#11136, Tuong Nguyen Manh). Take wide+      characters into account when determining the alignment.++  * LaTeX reader:++    + Ignore `\pandocbounded` (#11140).++  * XML reader:++    + Parse `<MetaString>` (#11137, massifrg).++  * Typst reader:++    + Add support for reading typst pagebreak (#11101, Raymond Berger).+      The pagebreak is parsed as a HorizontalRule inside a wrapper Div+      with class `page-break`.++  * Docx reader:++    + Handle figures in indented paragraphs (#11028).+    + Change default for textwidth. This should only be used if `sectPr`+      is not found.+    + Properly calculate table column widths (#9837, #11147).+      Previously we assumed that every table took up the full text+      width. Now we read the text width from the document's `sectPr`.+    + Use Tasty.Golden for Docx reader tests. This way we can update+      them with `--accept`.++  * RST reader:++    + Fix regression in simple table parsing (#11150).+    + SkippedContent warning if table directive contains+      non-tabular content.+    + Simple tables: leading space in a cell should not cause the contents+      to be parsed as a block quote (#11146).+    + Parse `:alt:` on figure (#11140). Also give a better default if+      `alt` is not specified, using the stringified caption rather+      than the filename.+    + Support col spans for simple tables (Tuong Nguyen Manh).++  * Markdown writer:++    + Improve handling of implicit figures (#11140).+      Allow implicit figures when alt text differs from caption+      (in this case, we use an image attribute to add the alt).+    + Use approximate pipe tables when it's the only option (#11128).+      If we have a table with row/colspans that can rendered as an+      approximate pipe table (without row/colspans), and no other table+      format is enabled that could render the table, we fall back to+      an "approximate" pipe table, with no row/colspans.++  * RST writer:++    + Ensure blank line before directives (#11162).+    + Add col spans for simple tables (#10127, Tuong Nguyen Manh).++  * OpenDocument writer:++    + Add missing table elements (#10002, Tuong Nguyen Manh).+      Add missing header rows after the first one,+      footer rows as well as TableBody header rows.++  * Docx writer:++    + Fix regression (from 3.8) in highlighted code (#11156).++  * Powerpoint writer:++    + Handle single column (Tuong Nguyen Manh).++  * Typst writer:++    + Fix syntax highlighting (#11171, completes #10525).+      Previously the native typst highlighting was always used, regardless+      of the setting of `--syntax-highlighting`. With this change,+      `--syntax-highlighting=none` and `--syntax-highlighting=<stylename>`+      (with skylighting style) will work.++  * LaTeX writer:++    + Make beamer footnotes compatible with pauses (#5954).+      Previously they would appear before the content to which+      the note was attached, when there were pauses in a slide.+    + Avoid `\_` in bibliography variable (#11152).+    + Ensure that unlabelled tables don't increment counter (#11141).+    + Protect VERB in caption (#11139, Tuong Nguyen Manh).+    + Don't add links to TOC (#11124, Albert Krewinkel).+    + Fix strikeouts in beamer title (#11168, Tuong Nguyen Manh).++  * LaTeX template: Add `shorthands` variable for LaTeX output+    (#11160). If true, pandoc will allow language-specific shorthands+    when loading babel. (This is helpful, for example, in getting+    proper spacing around French punctuation.)++  * epub.css: Remove coloring for `a, a:visiting` (#11174).+    This was causing links in iOS books app not to be distinguished in+    any way (since underlining is not used there).++  * Text.Pandoc.Parsing:++    + [API chage] (Tuong Nguyen Manh). New functions `tableWithSpans`,+      `tableWithSpans'`, `toTableComponentsWithSpans` and+      `toTableComponentsWithSpans'` take a list of lists of+      (Blocks, RowSpan, ColSpan) to parse a Table with different RowSpan and+      ColSpan values accordingly. New helper functions `singleRowSpans` and+      `singleColumnSpans` help set all RowSpans or ColSpans to be 1 in case+      the table format only allows setting one or the other.++  * Text.Pandoc.Class:++    + Let `fetchItem` fail if the HTTP request is not+      successful (Albert Krewinkel). HTTP requests that don't return a 200+      error code are now treated as an error. This ensures that a warning is+      triggered when using `--embed-resources` or `--extract-media`.++  * Text.Pandoc.Writers.Shared:++    + Add new function `removeLinks` [API change] (Albert Krewinkel).+      The function converts links to spans. It is used, for example, to avoid+      nested links. The HTML writer used to put the description of nested links+      into small caps, but uses a simple *span* now.++  * Text.Pandoc.Highlighting: export typst functions+    [API change]. New exported functions `formatTypstBlock`,+    `formatTypstInline`, `styleToTypst`.++  * Text.Pandoc.XML:++    + Add `fetchpriority` to list of HTML attributes (#11176).++  * Allow unicode-data 0.7.++  * Use released djot 0.1.2.3. Fixes a bug in which indentation+    was swallowed in a code block inside a blockquote.+++## pandoc 3.8 (2025-09-06)++  * Add a new input and output format `xml`, exactly representing a Pandoc+    AST and isomorphic to the existing `native` and `json` formats (massifrg).+    XML schemas for validation can be found in `tools/pandoc-xml.*`.+    The format is documented in `doc/xml.md`. Pandoc now defaults to this+    reader and writer when the `.xml` extension is used.++    Two new exported modules are added [API change]:+    Text.Pandoc.Readers.XML, exporting `readXML`, and+    Text.Pandoc.Writers.XML, exporting `writeXML`.+    A new unexported module Text.Pandoc.XMLFormat is also added.++  * Add a new command line option `--syntax-highlighting`; this takes+    the values `none`, `default`, `idiomatic`, a style name, or a path to a+    theme file. It replaces the `--no-highlighting`, `--highlighting-style`,+    and `--listings` options, which will still work but with a deprecation+    warning. (Albert Krewinkel)++  * Create directory of output file if it doesn't exist (#11040).++  * Update `--version` copyright dates (#10961), and use a hardcoded+    string "pandoc" for the program name in `--version`, per GNU+    guidelines.++  * Add `smart_quotes` and `special_strings` extensions (Albert Krewinkel).+    Currently these only affect `org`. Org mode makes a distinction between+    smart parsing of quotes, and smart parsing of special strings like `...`.+    The finer grained control over these features is necessary to truthfully+    reproduce Emacs Org mode behavior. Special strings are enabled by default,+    while smart quotes are disabled.++  * Remove the old `compact_definition_lists` extension. This was+    neded to preserve backwards compatibility after pandoc 1.12+    was released, but at this point we can get rid of it.++  * Make `-t chunkedhtml -o -` output to stdout (as documented), rather+    than creating a directory called `-` (#11068).++  * RST reader: Support multiple header rows (#10338, TuongNM).++  * LaTeX reader:++    + Support soft hyphens (Albert Krewinkel).+    + Parse `\minisec` as unlisted level 6 headings (#10635, Albert Krewinkel).+    + Support `\ifmmode` (#10915).+    + Change handling of math environments (#9711, #9296).+      Certain environments in LaTeX will trigger math mode and can't+      occur within math mode: e.g., `align` or `equation`.  Previously+      we "downshifted" these, parsing an `align` environment as a+      Math element with `aligned`, and an `equation` environment as a+      regular display math element.  With this shift, we put these in+      Math inlines but retain the original environments.+      texmath and MathJax both handle these environments well.++  * Typst reader:++    + Fix addition of image path prefix to use posix separator.+    + Properly resolve image paths in included files (#11090).+    + Handle inline-level show rules on block content (#11017).+      Typst allows things like `smallcaps` to be applied to block-level+      content like headings.  This produces a type mismatch in pandoc,+      so before processing the output of typst-hs, we transform it,+      pulling the block-level elements outside of the inline-level+      elements.++  * Org reader:++    + Improve sub- and superscript parsing (Albert Krewinkel).+      Sub- and superscript must be preceded by a string in Org mode. Some text+      preceded by space or at the start of a paragraph was previously parsed+      incorrectly as sub- or superscript.+    + Allow "greater block" names to contain any non-space char (#4287,+      Albert Krewinkel).+    + Accept quoted values as argument values (#8869, Albert Krewinkel).+    + Recognize "fast access" characters in TODO state definitions+      (#10990, Ryan Gibb).+    + Improve org-cite parsing: Handle global prefix and suffix properly.+      Use all and only the styles mentioned in oc-basic.el.+      Allow space after `;`.++  * HTML reader:++    + Don't drop the initial newline in a `pre` element (#11064).++  * DocBook reader:++    + Add rowspan support (#10981, Sean Soon).+    + Be sensitive to startingnumber attribute on ordered lists (#10912).++  * POD reader:++    + Fix named entity lookup (#11015, Evan Silberman).++  * Man reader:++    + Support header and footer reader (Sean Soon).++  * Markdown reader:++    + Don't confuse a span after an author-in-text citation with a+      locator.  E.g. `@foo [test]{.bar}`.+      See https://github.com/jgm/pandoc/issues/9080#issuecomment-3221689892.+    + Make definition lists behave like other lists (#10889).+      If the `four_space_rule` extension is not enabled,+      figure out the indentation needed for child blocks dynamically,+      by looking at the first nonspace content after the `:` marker.+      Previously the four-space rule was always obeyed.+    + Fix tight/loose detection for definition lists, to conform to+      the documentation.++  * ODT reader:++    + Support `table-header-rows` (Tuong Nguyen Manh).++  * Docx reader:++    + Don't add highlighting if highlight color is "none" (#10900).+    + Handle strict OpenXML as well as transitional (#7691).+    + Fix `stringToInteger` (#9184). It previously converted things like+      `11ccc` to an integer; now it requires that the whole string be parsable+      as an integer.+    + Improve handling of AlternateContent. This fixes handling of+      one representation of emojis in Word (#11113).++  * LaTeX writer:++    + Control figure placement with attribute (#10369, Sean Soon).+      If a `latex-placement` attribute is present on a figure, it will be used+      as the optional positioning hint in LaTeX (e.g. `ht`). With implicit+      figures, `latex-placement` will be added to the figure (and removed from+      the image) if it is present on the image.+    + Include cancel package only if there is math that contains `\cancel`,+      `\bcancel`, or `\xcancel`.+    + Add braces around comments in `title-meta` (#10501). This is needed to+      prevent PDFs from interpreting this as a sequence of titles.+    + Set `pdf-trailer-id` if `SOURCE_DATE_EPOCH` envvar is set (#6539, Albert+      Krewinkel). The `SOURCE_DATE_EPOCH` environment variable is used to trigger+      reproducible PDF compilation, i.e., PDFs that are identical down to the+      byte level for repeated runs.+    + Be more conservative about using `\url` (#8802). We only use it when the+      URL is all ASCII, since the `\url` macro causes problems when used with+      some non-ASCII characters.+    + Support soft hyphens (Albert Krewinkel).+    + Change handling of math environments (#9711, #9296).+      When certain math environments (e.g. `align`) are found in Math+      elements, we emit them "raw" instead of putting them in `$..$`.++  * Typst writer:++    + Check `XID_Continue` in identifiers (Tuong Nguyen Manh).+    + Add escapes to prevent inadvertent lists due to automatic wrapping+      (#10047). Also simplify existing code that was meant to do this.+    + Add parentheses around typst-native year-only citations (#11044).+    + Add native Typst support for `nocite` (#10680, Albert Krewinkel).+      The `nocite` metadata field can now be used to supply+      additional citations that don't appear in the text, just as with citeproc+      and LaTeX's bibtex and natbib.+    + Set `lang` attribute in Divs (#10965).+    + Rename `numbering` variable to `section-numbering` (Albert Krewinkel).+      This is the name expected by the default template.+    + Add support for custom and/or translated "Abstract" titles (Albert+      Krewinkel, #9724).++  * Org writer:++    + Don't wrap link descriptions (#9000). Org doesn't reliable display+      these as links if they have hard breaks.+    + Disable smart quotes by default (Albert Krewinkel).++  * Markdown writer:++    + Better handling of pandoc-generated code blocks (#10926).+      Omit the wrapper sourceCode divs added by pandoc around code blocks.+      More intelligently identify which class to use for the one class+      allowed in GFM code blocks.  If there is a class of form `language-X`,+      use `X`; otherwise use the first class other than `sourceCode`.+    + Use fenced divs even with empty attributes (#10955, Carlos Scheidegger).+      Previously fenced divs were not used in this case, causing the writer to+      fall back to raw HTML.+    + Match indents in definition items (#10890, Albert Krewinkel).+      Previously, the first line of a definition details item always used a+      colon and three spaces instead of respecting the tab-stop setting, which+      could lead to round-tripping issues. Likewise, the indentation of+      continuation paragraphs in definition lists now matches the+      two-characters leader of the first line for Markua output.++  * DocBook writer:++    + Use `startingnumber` instead of `override` for start numbers on ordered+      lists (#10912).++  * ANSI writer:++    + Make `--wrap=none` work properly (#10898).++  * Djot writer:++    + Fix duplicate attributes before section headings (#10984).++  * Docx writer:++    + Ensure that documents don't start with a section separator+      (#10578, Albert Krewinkel). Any leading section separator is removed from+      the result.++  * HTML writer:++    + Unwrap "wrapper" divs (#11014). Some of the readers (e.g. djot) add+      "wrapper" divs to hold attributes for elements that have no slot for+      attributes in the pandoc AST. The HTML reader now "unwraps"+      these wrappers so that the attributes go on the intended elements.++  * Asciidoc writer:++    + Handle lists with sublists following continuations (#11006).+      These require an additional blank line in some cases.++  * HTML styles template: prefix default styles with informative CSS comment+    (Albert Krewinkel, #8819).++  * Org template: add `#+options` lines if necessary (Albert Krewinkel).+    The default template now adds `#+options` lines if non-default settings+    are used for the `smart_quotes` and `special_strings` extensions.++  * LaTeX template:++    + Don't emit empty `linkcolor=` in hypersetup (#11098).+    + Add RTL support for LuaTeX engine (Reuben Thomas).++  * Typst template:++    + Add several new variables (Christopher T. Kenny, #9956):+      `thanks`, `abstract-title`, `linestretch`, `mathfont`, `codefont`,+      `linkcolor`, `filecolor`, `citecolor`.++  * `reference.docx`:++    + Don't left-align table header row (R. N. West, #11019).+    + Update East Asia font theme in `styles.xml` to `minorEastAsia` (TomBen).+    + Update language settings in `styles.xml` for East Asia to Simplified+      Chinese (TomBen).++  * Text.Pandoc.PDF:++    + `makePDF`: automatically embed resources from media bag in HTML+      before trying to convert it with weasyprint, etc. (#11099).+      This will give better results when converting from formats like docx.+    + Use `utf8ToText` for LaTeX log messages.+    + Make images from MediaBag available in tmp dir for every PDF engine,+      not just LaTeX/ConTeXt (#10911).+    + Improve error readability when pdf-engine is not supported (Albert+      Krewinkel). Each supported engine is now printed on a line of its own.+    + Allow `pdflatex-dev` and `lualatex-dev` as PDF engines (#10991, Albert+      Krewinkel). These are the development versions of the LaTeX binaries;+      installable, e.g., with `tlmgr install latex-base-dev`.+    + Clean up `makePDF` (Albert Krewinkel).+    + Avoid encoding errors when reading LaTeX logs (#10954).++  * Text.Pandoc.Readers:++    + Raise unknown reader error for `ods`, `odp`, `odf`, `xls`,+      `xslx`, `zip` extensions.++  * Text.Pandoc.App:++    + Recognize binary signatures and fail early (Repetitive). Fail early when+      receiving binary input with recognized signature: zip[-based], including+      OpenDocument and Microsoft formats, PDF, CFBF-based (old Microsoft formats+      including .doc and .xls), DjVu.+    + Remove code duplication around version info.+      Text.Pandoc.App.CommandLineOptions and `pandoc-cli/src/pandoc.hs`+      had similar code for generating version information.+      To avoid duplication, we now export `versionInfo` from+      Text.Pandoc.App [API change]. This function has three parameters that can+      be filled in when it is called by `pandoc-cli`.++  * Text.Pandoc.Parsing:++    + `tableWith` and `tableWith'` now return a list of lists of Blocks, rather+      than a list of Blocks, for the header rows, allowing for multiple header+      rows [API change] (#10338, TuongNM).++  * Text.Pandoc.Citeproc:++    + Don't move footnotes around em-dashes (#11046).+    + Allow `--citeproc` to put the bibliography in a Div with id `refs`+      even when `--file-scope` is used (#11072). When `--file-scope`+      is used, a prefix will be added based on the filename, so the Div+      will end up having an identifier like `myfile.md__refs`.+      Previously, this prevented the bibliography from being added to+      the marked Div. Now pandoc will add the bibliography to any Div+      with the id `refs` or any id ending in `__refs`.++  * Text.Pandoc.Citeproc.BibTeX: Protect case in periodical titles (#11048).+    Thus, for example, `{npj} Quantum Information` should translate as+    `[npj]{.nocase} Quantum Information`.++  * Text.Pandoc.ImageSize:++    + Detect more JPEG file signatures (R. N. West and John MacFarlane, #11049).+    + Unpack compressed object streams in PDFs and look inside for MediaBox+      information (#10902).+    + Add Point and Pica as constructors of ImageSize [API change] (#8957).+      This will prevent unnecessary conversion of units.+    + Add Avif constructor on ImageType [API change] and support avif images+      (#10979).++  * Text.Pandoc.Writers.Shared:++    + Amend docs of `lookupMeta...` functions (#10634, Albert Krewinkel).++  * Text.Pandoc.Options:++    + Add and export `defaultWebTeXURL` WebTeX URL [API change] (#11029,+      Sean Soon). This fixes the `webtex` option when used without+      parameter in a defaults file.+    + Add type `HighlightMethod` and patterns [API Change] (Albert Krewinkel).+    + The `writerListings` and `writerHighlightStyle` fields of the+      `WriterOptions` type are replaced with `writerHighlightMethod`+      [API change] (Albert Krewinkel, #10525).++  * Text.Pandoc.Extensions:++    + Remove `Ext_compact_definition_lists` constructor for+      `Extension` [API change].+    + Add `Ext_smart_quotes` and `Ext_special_strings` constructors.+      [API change].++  * Text.Pandoc.SelfContained:++    + Try fetching relative resources without query or fragment if the original+      fetch fails. This provides a fix for #1477 in a way that doesn't raise+      the problems mentioned in #11021.++  * Text.Pandoc.Highlighting:++    + Export `defaultStyle` [API Change] (Albert Krewinkel).+      This allows to be more explicit about using a default style, and+      providing a single point of truth for its value. The variable is+      an alias for `pygments`.++  * Text.Pandoc.Class:++    + `downloadOrRead`: do not drop fragment/hash for local file paths (#11021).+      With the previous behavior it was impossible to have an image+      file containing `#` or `?`.+    + Export function `runSilently` [API Change] (Albert Krewinkel).+      The function runs an action in the PandocMonad, but returns all log+      messages reported by that action instead of adding them to the main log.+    + Make CommonState opaque. Text.Pandoc.Class now exports CommonState as+      an opaque object, without its fields. [API change]+      The internal module Text.Pandoc.Class.CommonState still exports+      the fields.+    + Text.Pandoc.Class now exports the following new functions:+      `getRequestHeaders`, `setRequestHeaders`, `getSourceURL`,+      `getTrace`. [API change]+    + CommonState now has a `stManager` field. This allows us to cache the HTTP+      client manager and reuse it for many requests, instead of creating it again+      (an expensive operation) for each request. This fixes a memory leak and+      performance issue in files with a large number of remote images (#10997).++  * Lua subsystem (Albert Krewinkel):++    + Add function `pandoc.structure.unique_identifier`.+    + Add functions `pandoc.text.superscript` and `subscript`.+    + Use proper interface functions to access the CommonState.+      The `PANDOC_STATE` is no longer a userdata object, but a table that+      behaves like the old object. Log messages in `PANDOC_STATE.log` are now+      in temporal order.+    + Add function `pandoc.path.exists`.+    + Add `normalize` function to *Pandoc* objects (#10356).+      This function performs a normalization of Pandoc documents. E.g.,+      multiple successive spaces are collapsed, and tables are normalized such+      that all rows and columns contain the same number of cells.+    + Add more UTF-8-aware file operations to `pandoc.system`.+      Functions that expect UTF-8-encoded filenames should make it easier to+      write platform-independent scripts, as the encoding of the actual+      filename depends on the system. In addition, there is a new+      generalized method to run commands, and functions to retrieve XDG+      directory names. The new functions are `command`, `copy`, `read_file`,+      `remove`, `rename`, `times`, `write_file`, `xdg`.+    + Allow hslua-2.4.+    + Require lua-module-system 1.2.3. This provides List methods to the value+      returned by `pandoc.system.list_directory` (#11032).++  * MANUAL.txt:++    + Fix broken ConTeXt links (R. N. West, #11055).+    + Add `xml` as input/output format.+    + Fix minor capitalization typo (#11052, Albert Krewinkel).++  * `doc/lua-filters`:++    + Fix docs for `pandoc.Cite` (Albert Krewinkel).+    + Don't encourage returning tables of filters from Lua filters+      (R. N. West, #10995). Use the `Pandoc:walk` method instead.++  * doc/extras.md: Fix link to pandoc-mode (Erik Post).++  * doc/lua-filters.md: Add example on using pandoc.Table constructor (#10956,+    Sean Soon).++  * Update `default.csl` from new chicago-author-date.csl, which is now+    for the 18th edition.++  * Use latest releases of citeproc, typst-hs, texmath, doclayout,+    skylighting-core, skylighting.++## pandoc 3.7.0.2 (2025-05-28)++  * RST writer:++    + Don't emit alignment markers in grid tables (#10857).++  * Asciidoc writer:++    + Add support for sidebars (GHyman83).++  * LaTeX writer:++    + Include alt option in `\includegraphics` (#6095).++  * Markdown writer:++    + Preserve figure attributes (Nikolay Yakimov, #10867).+      Fixes a regression introduced by 0d2114e, which caused the+      Markdown writer to ignore attributes on the figure if it+      has class or key-value attributes set.++  * HTML writer:++    + Use the ID prefix in the ID for the footnotes section (Benjamin Esham).++  * Text.Pandoc.Writers.Shared:++    + `gridTable`: fix (3.7) regression with missing cell alignments (#10853).+    + `gridTable`: fix headings with colspans (#10855). If the heading+      contains a colspan, we still need to include information in the header+      line about the colspecs.+    + `gridTable`: fix headerless tables. The top line should encode+      colspan information.++  * Text.Pandoc.SelfContained:++    + Fix handling of empty script element (#10862). Previously in this+      case the closing tag was dropped.+    + Do not drop `data-` attributes in script tags (#10861).++  * Lua subsystem (Albert Krewinkel):++    + Add function `pandoc.mediabag.make_data_uri` (#10876).+      The function takes a MIME type and raw data from which it creates an+      RFC 2397 data URI.++  * `tools/update-lua-module-docs`: fix handling of wikilinks+    (Albert Krewinkel).++  * `doc/lua-filters.md`: add missing docs for `pandoc.Caption`+    (Albert Krewinkel).++  * Require texmath 0.12.10.3, typst 0.8.0.1++## pandoc 3.7.0.1 (2025-05-17)++  * Text.Pandoc.Shared.Writer:  Fix numerous problems with `gridTable` and add+    tests (#10848).  These fixes affect the Markdown, RST, and Muse writers.++  * Fix context writer/template to produce tagged PDFs (#10846).+    As before, the `tagging` extension must be enabled.+    We now add the command that tells ConTeXt to start tagging.++## pandoc 3.7 (2025-05-14)++  * Add new command-line option `--variable-json` (#10341).+    This allows non-string values (booleans, lists, maps) to be given to+    template variables on the command line.++  * The `--pdf-engine` option can now take `groff` as a value.++  * Markdown writer:++    + Avoid spaces after/before open/close delimiters (#10696).+      E.g. instead of rendering `x<em> space </em>y` as `x* space *y` we render+      it as `x *space* y`.+    + Handle row/colspans in grid tables, and expand cells when it isn't+      possible to lay them out without breaking string of non-whitespace.+    + Render a figure with Para caption as implicit figure (#10755).+    + When falling back to a Div with class `figure` for a figure that+      can't be represented any other way, include a Div with class+      `caption` containing the caption.+    + Improve use of implicit figures when possible (#10758).+      When the alt differs from the caption, but only as regards formatting, we+      still use an implicit figure.+    + Omit initial newlines in gfm `math` blocks to avoid an ugly blank line.+    * Support the `four_space_rule` extension for `plain` output (#10813,+      Manolis Stamatogiannakis).++  * RST writer:++    + Handle row/colspans in grid tables, and expand cells when it isn't+      possible to lay them out without breaking string of non-whitespace.++  * Muse writer:++    + Handle row/colspans in grid tables, and expand cells when it isn't+      possible to lay them out without breaking string of non-whitespace.++  * JATS writer:++    + Fix escaping for writing-review-editing role (#10744).++  * HTML writer:++    + Remove trailing slash from default revealjs URL (#8749). This+      avoids a double slash in the URL's path component.++  * LaTeX writer:++    + Make alignment work within `multirow` in tables (#10772).++  * Typst writer:++    + Support `mark` class on spans (#10747).+    + Add equation label if math contains `\label{..}` (#10805).++  * Roff format writers (man, ms):++    + Use the most compatible form for roff escapes (#10716).+      For example, `\(xy` instead of `\[xy]`. This was the original+      AT&T troff form and is the most widely supported. The+      bracketed form causes problem for some tools, e.g.+      `makewhatis` on macOS. And emit `e` followed by an escape+      for a unicode combining accent rather than the form `\[e aa]`,+      which works for groff but not e.g. on macOS's man.+      This change affects Text.Pandoc.RoffChar,+      Text.Pandoc.Writers.Roff, and the Man and Ms writers.++  * Docx writer:++    + Ensure that figures and tables with custom styles are not dropped+      (#10705).+    + Preserve Relationships for images from reference docx (#10759).+      This should allow one to include an image in a reference.docx and+      reference it in an openxml template.+    + Don't renumber rels (#10769). We used to renumber the+      Relationships so they didn't conflict with the set of fixed+      Relationships we imposed. We are now preserving the ids+      from the reference doc's document.xml.refs, so we shouldn't+      renumber them or references introduced by the user (e.g. in+      a template) will fail.++  * Ms writer:++    + Improve PDF TOC labels. We now use the plain writer to render these,+      so that Greek characters etc. will show up properly.+    + When no `pdf-engine` variable is specified, do not use the+      `.pdfhref` macros at all (#10738). This gives better results for links+      in formats other than PDF, since the link text would simply+      disappear if it exists only in a `.pdfhref` macro. When a PDF+      engine is specified, escape the argument of `.pdfhref O` in a way+      that is appropriate.++  * OpenDocument writer:++    + Fix character styles in footnotes (#10791). Character+      styles governing the position of the footnote reference+      should not be imposed on the footnote text.++  * Powerpoint writer:++    + Use reference-doc font for captions (#9896, R. N. West).++  * DocBook writer:++    + Use literallayout element for LineBlock (#10825).++  * MediaWiki reader/writer:++    + Allow definition on same line as term (#10708).++  * LaTeX reader:++    + Skip at most one argument to LaTeX tabular newline (#7512,+      Evan Silberman).+    + Disable ligatures inside `\texttt` (#10781).+    + Support more symbol commands (#10782).++  * Commonmark Reader:++    + Handle GFM math irregularity with braces (#10631). In GFM, you need+      to use `\\{` rather than `\{` for a literal brace.++  * DocBook reader:++    + Improve handling of literallayout (#10825). This is now only made+      a CodeBlock when there is a `monospaced` class. Otherwise it is made+      a LineBlock.++  * Org reader:++    + Add AVIF to Org Reader image extensions (#10736, Christian Christiansen).+    + Don't include newlines in inine code/verbatim (#10730).+      Convert newlines to spaces as we do in other formats.+    + Change handling of inline TeX (#10836). Previously inline+      TeX was handled in a way that was different from org's own export,+      and that could lead to information loss. This was particularly noticeable+      for inline math environments such as `equation`.  Previously, an+      `equation` environment starting at the beginning of a line would create+      a raw block, splitting up the paragraph containing it (see+      #10836). On the other hand, an `equation` environment not+      at the beginning of a line would be turned into regular+      inline elements representing the math. (This would cause+      the equation number to go missing and in some cases degrade+      the math formatting.) Now, we parse all of these as raw+      "latex" inlines, which will be omitted when converting to+      formats other than LaTeX (and other formats like pandoc's+      Markdown that allow raw LaTex).++  * Beamer template: fix regression in 3.6.4, reverting the omission of+    `\date` when the document does not have a date. By default, beamer+    will display a date when no `\date` is present in the title block,+    so this was an unintended behavior change. The reverted+    change was motivated by the desire to include a custom+    `\date` in the frontmatter via header-includes. This can be+    achieved more simply by simply setting the `date` variable.+    In markdown you can even use `date` in metadata and put some+    raw LaTeX there.++  * Ms template:++    + Use T rather than P as default font family (#10738).+    + Put PDF-specific things under a conditional.+      Don't include them if `pdf-engine` isn't set.++  * Upgrade reveal.js URL to v5 (#10740, Kolen Cheung).+    v4 is no longer available on unpkg.com.++  * Text.Pandoc.PDF: Allow `groff` to be used as `--pdf-engine` with `ms`+    (#10738). When `groff` is used as a PDF engine, the `groff`+    extension to `ms` is automatically enabled. Limitations:++    - `groff` currently produces larger PDFs than `pdfroff`.+    - With `groff`, a table of contents produced with+      `--table-of-contents/--toc` will always be placed at the end of+      the document.+    - Certain characters (e.g. Greek characters) may be dropped in+      the PDF outline.++  * Text.Pandoc.Writers.Shared:++    + Export `delimited` [API change].+    + New version of `gridTable` (#6344) [API change]. This+      handles row and colspans. It also ensures that cells won't+      wrap text in places where it wouldn't normally wrap, even+      if this means making the cells wider than requested by the+      colspec (#9001, #7641). Because the parameters are+      different, this is a breaking API change.++  * Text.Pandoc.App: set `pdf-engine` variable.+    If `--pdf-engine` is specified or if a PDF is being produced, we set the+    `pdf-engine` variable. This allows writers and templates to behave+    differently depending on the PDF engine.++  * Text.Pandoc.Class and Text.Pandoc.URI:++    + Fix parsing of base64 data URIs to allow URI escapes and+      whitespace (which will be ignored) (#10704).+    + Handle percent encoding in `pBase64URI` instead of+      unescaping later, for efficiency (#10704).++  * Text.Pandoc.Citeproc.BibTeX:++    + Recognize `en` as a `langid` in biblatex bibliographies (#10764).++  * Text.Pandoc.MIME:++    + Add mime type and extension for `avif` (#10704).+    + Handle `apng`, `avif`, `jxl` (#10704).++  * Text.Pandoc.Readers.LaTeX.Math: export `inlineEnvironmentNames`.+    Internal module, not a change to the public API.++  * `reference.docx` (Andrew Dunning):++    + Remove extra spaces around text placeholders.+    + Add footnote block text sample.++  * Text.Pandoc.Class.Sandbox:++    + Add `sandboxWithFileTree` function [API change] (Albert Krewinkel).++  * Lua subsystem (Albert Krewinkel):++    + pandoc-lua-engine: add all test files to the cabal file.+    + Allow `pandoc.read` to be called in "sandbox" mode for added+      security (#10831). Readers running in a sandbox will not be+      able to access the network or file system. The sandbox is+      enabled if the fourth parameter is a list of files or+      filename/content pairs. The files are read and then made+      available in the sandbox via en ersatz file system.++  * Makefile:++    + Add target `release-checkist`.+    + Install @daisy/ace from npm if not present.+    + Use pandoc lua instead of lua.+    + Fix typo in `latex-package-dependencies` target.+    + Use `jq` instead of `json_reformat` in `validate-docx-golden-tests2`.++  * NiX infrastructure: new working `flake.nix` and simpler `shell.nix`.+    Removed old `default.nix`.++  * Require random >= 1.3 and use `splitGen`. `split` has been deprecated.++  * Use citeproc-0.9. Bump citeproc bounds for pandoc, pandoc-lua-engine.++  * Use texmath-0.12.10.1.++  * Use released typst 0.8 (partially supporting typst 0.13).++  * Use citeproc 0.9.0.1.++  * MANUAL.txt:++    + Fix default URL for revealjs.+    + Add note that `alerts` extension only works with commonmark (#9716).+    + Remove "Body Text Char" from list of Word styles that can be customized+      using a reference.docx (#10646). This doesn't seem to be present in+      pandoc-generated docx files, nor is it a Word default.+    + For pandoc lua, add note about the environment.+    + Improve documentation of `--variable` option.++  * `doc/typst-property-output.md`: Mention that `typst:no-figure` is a+    class, not an attribute (#10826, Niklas Eicker).++  * Change RELEASE-CHECKLIST to RELEASE-CHECKLIST-TEMPLATE.org. Use org-babel+    to automate many of the steps of the release.++  * INSTALL.md: update MacPorts information (#10719, Mohamed Akram).++  * COPYRIGHT: fix link to source code.++  * CONTRIBUTING.md: Fix link to discussion forum. (#10834, R. N. West).++## pandoc 3.6.4 (2025-03-16)++  * Disable `citations` extension in writers if `--citeproc` is used (#10662).+    Otherwise we get undesirable results, as the format's native+    citation mechanism is used instead of (or in addition to) the+    citeproc-generated citations.++  * Markdown reader:++    + Allow line break between URL and title of link (#10621).+    + Give better position information when YAML metadata parsing fails+      with a YAML exception (#10231).+    + Fixed `escapedChar'` parser (#10672). It should not accept+      escaped newlines.+    + Remove some misguided list fanciness (#9865, #7778, cf. #5628).+      Previously we tried to handle things like commented out list items:+      ```+      - one+      <!--+      - two+      -->+      - three+      ```+      and also things like:+      ```+      - one `and+      - two` and+      ```+      But the code we added to handle these cases caused problems with+      other, more straightforward things, like:+      ````+      - one+      - ```+        code+        ```+      - three+      ````+      So we are rolling back all the fanciness, so that the markdown+      parser now behaves more like the commonmark parser, in which+      indicators of block-level structure always take priority over+      indicators of inline structure.++  * HTML reader:++    + Skip MathJaX-introduced cruft (#10673).+    + Ignore style tags in the body (#10643).++  * LaTeX reader:++    + Better handle comments/whitespace in option lists and includes (#10659).+    + Support `\newline`, `\linebreak`.++  * Docx reader/writer:++    + Revert commit adding row heads+      (cbe67b9602a736976ef6921aefbbc60d51c6755a) (#10627).+      Word sets `w:firstColumn="1"` by default for tables.  You have to find+      the Table Design tab and explicitly uncheck "First Column" to make this+      go away.  In most cases, I don't think writers intend to designate+      the first column as a row head, so this commit is going to produce+      unexpected results.  In addition, because of the table normalization+      done by pandoc-type's `tableWith`, any table containing a colspanned+      cell in the left-hand column will get broken if the first column is+      designated a row head.  For these reasons it seems best to revert this+      change, which was made in response to #9495.++  * LaTeX writer and template:++    + Remove `selnolig-langs` (#9863). We now specify the language as+      a global option again, so we no longer need to specify it when+      invoking selnolig.+    + Use babel options `shorthands=off` (#6817).+    + Use `*` for multirow width when no colwidth specified (#10685).+      Otherwise the multirow will be excessively wide.+    + Protect `\phantomsection` (#10688, etclub).++  * Markdown writer:++    + Omit extra space after bullets (#7172). Those who want the old+      behavior can obtain it by using `-t markdown+four_space_rule`.+    + Treat `Emph [Emph ils]]` as `ils` (#10642). Otherwise we get+      `**content**` which means strong emphasis.++  * EPUB writer:++    + Use a nonbreaking space after section number in nav.xhtml.+      This seems to be required for iOS books app to display the space.++  * Typst writer:++    + Better heuristics for escaping potential list markers (#10650).+    + Ensure that `citation-style` works as well as `csl` (#10661).++  * Powerpoint writer:++    + Avoid extra blank lines before author when there is no+      subtitle (#10619).++  * JATS template:++    + Fix typo in author prefix in article.jats_publishing template+      (#10622, Tiago-Manzato).++  * Text.Pandoc.Parsing:++    + Smart quote parsing: ignore curly quotes (#10610). Previously we+      tried to match curly quotes as well as straight quotes,+      producing Quoted inlines. But it seems better just to assume+      that those who use curly quotes want them passed through+      verbatim. This also fixes an (unintended) bug whereby curly+      single left quotes would sometimes be changed to single right quotes.++  * Text.Pandoc.Shared:++    + `makeSections`: put some attributes on section element only.+      Certain `role` and `epub:type` attributes should only be on the section+      (and indeed, many `role`s give a validation error if left on the+      heading element).++  * Text.Pandoc.Logging:++    + Change NoTitleElement from WARNING to INFO (#10671). Users+      commonly complain about the warning when producing HTML+      documents without an explicit title. It seems that an info+      message is more appropriate, since pandoc's default here (using+      the input's base name) ensures compliance with the standard and+      many users are happy with that default. Those who want to make+      sure the message is seen can use `--verbose`.++  * Beamer template: only emit `\date` if set (#10687, josch).++  * Fix invalid OOXML in definition_list.docx test (#10394).++  * MANUAL.txt:++    + Correct typo: 'date' for doubled 'title' (#10654, Olivier Dossmann).+    + Add note about `template` variable for typst.+    + Change maxwidth default in MANUAL.txt (#10683).+    + Improve EPUB metadata documentation.+    + In Security section, alert readers to a threat relating to iframe in+      HTML, and add LaTeX, Typst to the list of formats that have an+      `include` (#10682).++  * `doc/lua-filters.md`: Add missing html_math_method 'katex' (R. N. West).++  * Use texmath 0.12.9.++  * Use typst 0.7. Fixes an issue with package loading, a regression+    in pandoc 3.6.3.++## pandoc 3.6.3 (2025-02-09)++  * Track wikilinks with a class instead of a title (Evan Silberman).+    Previously wikilinks were distinguished by giving them the `title`+    `wikilink`.  Now that we have link attributes, it makes more sense+    to give them the `class` `wikilink`. This change affects all readers+    and writers that support wikilinks.++  * DocBook reader:++    + Handle title inside `orderedlist` (#10594). Also some other+      elements that allow title: `blockquote`, `calloutlist`, etc.+    + Better handle `informalequation` (#10592, tombolano). Include `id`+      attribute.+    + Better handle `formalpara`, `example`, and `sidebar` (#8666, tombolano).+      Include identifiers and titles in each case.++  * Markdown reader:++    + Simplify and fix normal citation parsing (#10584).+      This fixes a bug that causes some normal citations to be+      parsed as bracketed regular citations.++  * ODT reader:++    + Create Figure elements for images that are figures (#10567).+    + Avoid producing spurious blockquotes in list items (#9505).+    + Fix unwanted block quotes (#10575). Previously the reader created+      block quotes whenever a paragraph was marked indented (even though+      this just affects the first line). With this change we still+      generate block quotes for content that has an altered left margin,+      but not for indented paragraphs.++  * Docx reader:++    + Do not issue warning for comments with `+styles` (#10571, Stephen Reindl).++  * LaTeX reader:++    + Test \{,re}newcommand arguments (#4470, Evan Silberman).++  * Pod reader:++    + Consume blanks after =encoding in pod reader (#10537, Evan Silberman).++  * JATS writer:++    + Add CRediT roles to JATS (Charles Tapley Hoyt and Jez Cope, #10152).+      Enable annotating author roles using the Contribution Role Taxonomy+      (CRediT) and export this information in conformant JATS.++  * LaTeX writer/templates:++    + Improve babel support (#8283). Previously we used the `.ini`+      files for every language, but for European languages these tend to+      provide inferior results to the `.ldf` files used by classic+      Babel. Currently Babel documentation recommends using the classic+      system for European languages written in Latin and Cyrillic+      scripts and Vietnamese. So the LaTeX writer and template now+      follow this guidance.++      Main languages in the list of languages with good "classic" support+      are added to global documentclass options and will be automatically+      handled by Babel using the `.ldf` files.++      If the main language is not in this list, the `babeloptions` variable+      will be set to `provide=*`, which will cause support to be loaded from+      the `.ini` file rather than an `.ldf`. So, for example, setting+      `-V babeloptions=''` with a polytonic Greek document will cause the+      `.ldf` support to be used instead of the `.ini`.++      The default setting of this variable can be overwritten, but in most+      cases the default should give good results.++    + Allow `csquotesoptions` to be specified.+    + Fix indentation bugs in `font-settings.latex`.++  * Docx writer:++    + Repeat reference doc's `sectPr` for each new section (#10577).+      Previously we were only carrying over the reference doc's `sectPr`+      at the end of the document, so it wouldn't affect the intermediate+      sections that are now added if `--top-level-division` is `chapter`+      or `part`. This could lead to bad results (e.g. page numbering+      starting only on the last chapter).+    + Create section divisions with `--top-level-division=part` (#10576).+    + Improve title style in reference.docx; base Author and Date+      on Title; remove condensed spacing (Andrew Dunning, #10581).++  * Typst writer:++    + Brace tables with `typst:no-figure` and `typst:text` attributes (#10563,+      Gordon Woodhull).++  * Ms writer:++    + Fix escaping of `-` (#10536). `-` should now be escaped in man+      output but not in ms output (where `\-` is a unicode minus sign).++  * HTML styles: fix style of `hr` so it works when printed (#10535, Hendrik Erz).+    Previously `background-color` was used to style the hr, but this gets ignored+    when printing.  This commit uses `border-top` instead.++  * Text.Pandoc.Shared:++    + Handle `<abbr>` as a span-like inline in `htmlSpanLikeElements`+      (#5793, Evan Silberman).++  * Text.Pandoc.MediaBag:++    + Prefer MIME type when determining extensions for MediaBag items (#10557,+      Max Heller).  This should give different results for remote images+      that are served at URLs that do not contain misleading extensions+      (e.g. `shields.io`).++  * Text.Pandoc.Citeproc:++    + Fix moving punctuation before citation notes. This previously worked with+      regular citations, but not author-in-text citations. Now it works with both.++  * `doc/lua-filters.md`:++    + Correct luacheck URL (#10589, R. N. West).+    + Add static analysis paragraph to debugging section (#10568, R. N. West).+    + Add note about extensions handling in `read` and `write` (Albert Krewinkel).++  * `doc/extras.md`:++    + Add entry for pandoc-subfigs (R. N. West).+    + Update diagram Lua filter URL and description (R. N. West).++  * MANUAL.txt:++    + Add note on using typst to produce pdf/a-2b.+    + Document top-level-division functionality with Docx (#10579, Andrew Dunning).++  * Raise xml-conduit upper bound.++  * Depend on latest commonmark-pandoc, commonmark-extensions,+    citeproc, typst.++  * Makefile: make `make binpath` quiet.++## pandoc 3.6.2 (2025-01-12)++  * New input format: `pod` (Evan Silberman). Pod ("Plain old documentation")+    is a markup languaged used principally to document Perl modules and+    programs.++  * New reader module Text.Pandoc.Readers.Pod, exporting `readPod`+    [API change].++  * Docx reader:++    + Support row heads in tables (#9495). Reader: When `w:tblLook` has+      `w:firstColumn` set (or an equivalent bit mask), we set row heads = 1+      in the AST.+    + Read table styles as custom styles when `styles` extension+      is enabled (#9603).++  * HTML reader:++    + Add size information for font awesome SVG icons (#10134).+      If the icon has class `fa-fw` or `fa-w16` or `fa-w14`, we add a width+      attribute to prevent the icon from appearing full-width in PDF or+      docx output.++  * Djot reader:++    + Use a Span with class "mark" rather than "highlighted" for+      highlighted text, for consistency with the other pandoc readers and+      writers.++  * mandoc reader:++    + Add mdoc St for C23 (Evan Silberman).++  * RST reader:++    + Fix handling of underscores (#10497). Fixes a a regression+      introduced in 3.6.++  * Docx writer:++    + Support row heads in tables (#9495). Writer: set `w:firstColumn` in+      `w:tblLook` when there are row heads. (Word only allows one, so this+      is triggered by any number of row heads > 0.)++  * Djot writer:++    + Render a Span with sole class "mark" as highlighted text.++  * Asciidoc writer:++    + Don't emit the class in a span if it's just "mark" (#10511).+      The "mark" class is used for highlighting, and Asciidoc treats+      bare `#...#` with no attributes as highlighted text.+    + Improve escaping (#10385, #2337, #6424).++  * EPUB v2 writer:++    + Fix cover image (#10505).  This is a regression introduced in 3.6.++  * Typst writer:++    + Fix handling of pixel image dimensions (#9945).+      These are now converted to inches as in the LaTeX writer.++  * Improve error message given when users specify `asciidoc` as input+    format (#8416, Santiago Zarate).++  * Allow random 1.3.++  * Use texmath 0.12.8.13 (typst improvements).++  * `lua-filters.md`: document `system.os` return values (#10523).++  * `MANUAL.txt`:++    + Improve manual's coverage of custom styles.+    + Replace LibreOffice PDF documentation link to latest so it links+      to the latest major release rather than a specific major release+      (which there are two of every year) (Stéphane Guillou).+    + Improve links and descriptions for `odt`, `opendocument` (#10518).++## pandoc 3.6.1 (2024-12-23)++  * Allow YAML bibliographies to be arrays of references (#10452).+    Previously, they had to be YAML objects with a `references` key.++  * Change `--template` to allow use of extensionless templates (#5270).+    The intent is to allow bash process substitution: e.g.,+    `--template <(echo "foo")`. Previously pandoc *always* added an+    extension based on the output format, which caused problems+    with the absolute filenames used by bash process substitution+    (e.g. `/dev/fd/11`). Now, if the template has no extension,+    pandoc will first try to find it without the extension, and+    then add the extension if it can't be found. So, in general,+    extensionless templates can now be used. But this has been+    implemented in a way that should not cause problems for+    existing uses, unless you are using a template `NAME.FORMAT`+    but happen to have an extensionless file `NAME` in the template+    search path.++  * Allow `--shift-heading-level-by=-1` to work in djot in the same way+    it works for other formats (with the top-level heading being+    promoted to metadata title) (#10459).  This needed special+    treatment because of the way djot surrounds sections with Divs.++  * RST reader:++    + Handle explicit reference links (#10484, Evan Silberman).+      This case was missed when changing the reference link strategy for+      RST to allow a single pass. (It is a regression in pandoc 3.6.)++  * Markdown reader:++    + Use T.P.URI's `pBase64DataURI` in parsing data URIs (#10075,+      Evan Silberman and John MacFarlane).+    + More efficient base64 data URI parsing (#10075, Evan+      Silberman and John MacFarlane). This should yield dramatic+      performance improvements for markdown documents containing+      large data URIs in images.++  * HTML reader:++    + Don't canonicalize data: URIs (#10075). It can be very expensive+      to call network-uri's URI parser on these.++  * LaTeX reader:++    + Handle `figure*` environment as a figure (#10472).++  * MediaWiki reader:++    + Allow empty quoted attributes (#10490).+    + Allow cells starting with `+` (#10491).++  * Textile reader:++    + Improve parsing of spans (#9878). The span needs to be separated+      from its surroundings by spaces. Also, a span can have attributes,+      which we now attach.+    + Inline constructors shouldn't trigger if closer is preceded by+      whitespace (#10414).++  * Docx writer:++    + Put chapters in separate sections, and restart footnotes+      by section by default (#2773). The main effect of this change is that+      when `--top-level-division=chapter` is used, chapters will start on+      a new page and footnote numbering will restart for each chapter.+      Both of these defaults can be overridden in the reference.docx.+    + Use styleIds not styleNames for Title, Subtitle, etc.+      (#10282). This fixes a regression introduced in pandoc 3.5.+      This change affects the default openxml template as well as the+      OpenXML writer.++  * Markdown writer:++    + Avoid collapsing of initial/final newline in markdown raw blocks.+      This makes it easy to write a filter that adds extra blank lines+      before certain elements (#10477).++  * Mediawiki writer:++    + Escape line-initial characters that would otherwise be interpreted+      as list starts (#9700).++  * LaTeX writer:++    + Properly handle boolean value for `csquotes` variable (#10403).+    + Use displayquote for block quotes with `csquotes` (#10456).++  * HTML writer:++    + Avoid calling parseURIString for data URIs (#10075).+      This was done to determine the "media category," but we can+      get that directly from the mime component of data: URIs.++  * Typst writer:++    + Properly handle data URIs in images (#10460).++  * LaTeX/Beamer templates:++    + Fix default.beamer `nocite` location (Thomas Hodgson).+      It must be inside a frame or it is ignored (#10465).+    + Move nocites from LaTeX preamble to body (#10461, Thomas+      Hodgson). Putting `\nocite` in the preamble works only with biblatex.++  * Text.Pandoc.Parsing:++    + Correct example in comment on `charsInBalanced` (Evan Silberman).++  * Text.Pandoc.Error:++    + Mention typst in rendering `PandocUnknownWriterError` for `pdf`+      (Evan Silberman).++  * Text.Pandoc.MediaBag:++    + `insertMedia`: fast path for data URIs. Avoid the slow URI+      parser from network-uri on large data URIs (#10075).++  * Text.Pandoc.Class:++    + Add shortcut for base64 data URIs in `downloadOrRead` (#10075).+      This avoids calling the slow URI parser from network-uri on+      data URIs, instead calling our own parser.++  * Text.Pandoc.MIME:++    + Fix `extensionFromMimeType`. We had a few special cases encoded,+      but as previously written they wouldn't work properly with+      modifiers like `;charset=utf-8`.++  * Text.Pandoc.URI:++    + Export `pBase64DataURI`.  Modify `isURI` to use this and avoid+      calling network-uri's inefficient `parseURI` for data URIs.++  * Text.Pandoc.PDF:++    + Fix temp file extension in `toPdfViaTempFile` (#10468).+      This fixes a regression in pandoc 3.6, which changed+      the extension from `html` to `source`. Apparently+      `wkhtmltopdf` needs it to be `.html`.  So now we have added+      a parameter to `toPdfViaTempFile` that allows the extension+      to be specified in a way that is appropriate to the PDF engine+      used.++  * Lua (Albert Krewinkel):++    + Support more elements as input to `pandoc.utils.stringify`+      (#10450). Elements of type Caption, Cell, TableHead, and TableFoot+      can now be stringified.+    + Add `Caption` constructor to `pandoc` module.++  * Miscellaneous code quality improvements (Joseph C. Sible).++  * Depend on citeproc 0.8.1.2, skylighting and skylighting-core+    0.14.5.++  * `doc/lua-filters.md: Fix links to constructors (Albert Krewinkel).+++## pandoc 3.6 (2024-12-07)++  * Add `mdoc` as input format (Evan Silberman). This change+    introduces a reader for mdoc, a roff-derived semantic markup+    language for manual pages. This reader has been developed almost+    exclusively against mandoc's documentation and implementation of+    mdoc as a reference, and the real-world manual pages tested+    against are those from the OpenBSD base system. Of ~3500 manuals+    in mdoc format shipped with a fresh OpenBSD install, 17 cause the+    mdoc reader to exit with a parse error. Any further chasing of+    edge cases is deferred to future work.++  * New module: Text.Pandoc.Readers.Mdoc, exporting `readMdoc` [API change].++  * Issue warnings for duplicate YAML metadata keys (#10312).++  * Ensure that `--sandbox` affects `--embed-resources`. Previously it+    did not (contrary to what was implied by the manual), which means+    that an image with URL `/etc/passwd` would leak an encoded version+    of that file to HTML output with `--self-contained` or+    `--embed-resources`, even if `--sandbox` was used. Thanks to+    Samuel Mortenson for pointing out the issue.++  * Text.Pandoc.App.OutputSettings: add `sandbox'` function.+    This computes the sandboxed files from Opt and avoids code repetition.++  * Docx reader:++    + Parse index references as empty spans with attributes (#10171).+      Attributes included are `entry`, and optionally `bold`, `italic`,+      `yomi`, `see`.+    + Don't create multiple paragraphs for title or subtitle (#10359).+      If there are multiple paragraphs with Title or Subtitle style,+      use only the first for metadata.+    + Handle case where Zotero `itemData` has different id from the+      `citationItem` id.  In this case we use the `citationItemId`+      in the bibliography as well, overriding the `referenceId`+      in the itemData (#10366).++  * LaTeX reader:++    + Put parsed minipage in specially marked Div (#10266).++  * HTML reader:++    + Parse footnotes defined by dpub-aria roles (#5294).++  * MediaWiki reader:++    + Fix indented tables with caption (#10390).+    + Fix parsing of col/rowspan (#6992).++  * Typst reader:++    + Avoid generating empty paragraphs.+    + Support `underparen`, `overparen`.+    + Fix `#quote` attribution. If attribution is not present, don't print+      the `--` (#10320).+    + Fix typo in unicode code point for em dash (see #10320).++  * Commonmark reader:++    + `implicit_figures` should check for empty caption+      and not produce an implicit figure in this case (#10429).++  * RST reader:++    + Use a new one-pass parsing strategy. Instead of having an initial pass+      where we collect reference definitions, we create links with target+      `##SUBST##something` or `##REF##something` or `##NOTE##something`,+      and resolve these in a pass over the parsed AST. This allows us to handle+      link references that are not at the top level (#10281).+    + Ignore newlines in URL in explicit link (#10279).+    + Handle block level substitutions.+    + Support `:file:` on raw directive (#8584).+    + Implement option lists (#10318).+    + Avoid putting metadata in Para (#7766). Create MetaInlines when possible,+      just as with markdown input. MetaBlocks is still used when there are+      multiple paragraphs or non-paragraph content.+      This change also affects field lists.+    + Fix linked substitutions (#6588). E.g. `|Python|_`.+    + Support inline anchors (#9196).+    + Explicit links define references (#5081). For example,+      ``Go to `g`_ `g <www.example.com>`_.`` should produce two links to+      www.example.com.++  * EPUB writer:++    + Use standardized filename for cover image instead of the original name+      (#10404). This avoids problems with e.g. filenames containing spaces.++  * Markdown writer:++    + Issue INFO warning when not rendering table, e.g., when `raw_html` is+      disabled and the table can't be fit into a supported markdown table+      format (#10407).+    + Respect empty LineBlock lines in `plain` output (Evan Silberman).+      The plain writer behaved as a markdown variant with `Ext_line_blocks`+      turned off, and so empty lines in a line block would get eliminated.++  * LaTeX writer:++    Ensure that beamer footnotes go on frame, not column (#5769).++  * HTML writer:++    + Unwrap empty incremental divs (#10328, Albert Krewinkel).+      Divs are unwrapped if the only purpose of the div seems to be to control+      whether lists are presented incrementally on slides.++  * Typst writer:++    + Make template sensitive to a `page-numbering` variable (#10370).+      This can be set to an empty string (or, in metadata, to false) for+      no page numbers.+    + Make `smart` extension work (#10271). If `smart` is not enabled, a command+      in the default template will disable smartquote substitutions.+      When `smart` is enabled, render curly apostrophes as straight+      and escape straight apostrophes. When `smart` is disabled,+      render curly apostrophes as curly and don't escape straight+      apostrophes. Similarly for quotes, em and en dashes. This should+      give more idiomatic typst output, with fewer unnecessary+      escapes.++  * ANSI writer:++    + Respect empty LineBlock lines (Evan Silberman).++  * JATS writer:++    + Correct spelling of suppress attribute (#10350, Andreas Deininger).++  * Typst template:++    + Remove `definitions.typst` partial.+    + Remove unnecessary definition of `endnote`.+    + Incorporate the one remaining definition into `default.typst`.+    + Use typst 0.12 code for two column layout (#10294, Luis Rivera).+    + Note: the new templates presuppose typst 0.12; if you try to use an+      earlier version of typst, an error will be raised.++  * LaTeX/Beamer template:++    + Split `fonts.latex` partial into two parts: `fonts.latex` and+      `font-settings.latex`.+    + In beamer template, load beamer theme between `fonts.latex` and+      `font-settings.latex`. This allows a theme (such as metropolis)+      to set its own default font, while still allowing the user to+      override it. This fixes a regression in pandoc 3.5 (#10297).+    + Note: Users who have custom templates based on pandoc 3.5 templates will+      need to add `font-settings.latex()` after `fonts.latex()` in the+      latex template. In a beamer template, the beamer theme-setting+      code needs to be moved between these two partials.++  * ConTeXt template: Ensure that font names don't wrap (#10305).++  * `epub.css`: remove background-color (#10264, Suraj Patil).+    With this greyish background color, epubs look bad on a Kindle (#10263).++  * Text.Pandoc.ImageSize: add WebP support (Evan Silberman, #10397).+    Add `Webp` constructor on ImageType [API change].++  * Text.Pandoc.Readers.Roff and a new unexported module+    Text.Pandoc.Readers.Roff.Escape: parameterize Roff+    escaping (Evan Silberman) [API change]. This allows code to+    be reused between the mdoc and man readers, despite the+    differing Token types.++  * Text.Pandoc.PDF:++    + PDF via LaTeX: always do max runs if `toc` is present (#10308).+      The old method (checking to see if toc hash had changed) is not+      completely reliable.+    + Use `.source` extension, not `.html`, in `toPdfViaTempFile` (#10314).++  * Text.Pandoc.Logging: add `YamlWarning` constructor to `LogMessage`+    [API change] (#10312).++  * Text.Pandoc.Format: remove duplicate typst entry (#10388, Caleb Mclennan).++  * Fix a typo in the `ua.yaml` localization for 'See' (Jens).++  * Lua subsystem (Albert Krewinkel):++    + Remove prefixes from Lua type names (#8574). Lua type names were+      inconsistent with regard to the use of prefixes; all prefixes+      are removed now, and Lua types now have the same name as the+      Haskell types. The use of app-specific prefixes is suggested by+      the Lua manual to avoid collisions. However, this shouldn't be a+      problem with pandoc, as it cannot be used as a Lua package.++  * doc/libraries.md: Add newly developed Haskell packages.+    Sort list alphabetically (Albert Krewinkel).++  * doc/lua-filters.md: document `pandoc.List:iter` method (Albert Krewinkel).+    List objects have a new function `iter` that returns an iterator+    function that returns the next list item on each call.++  * MANUAL.txt:++    + Clarify what the example of YAML EPUB metadata shows (#10405).+    + Fix typo in template syntax (#10265, Pascal Wagler).+    + Update manual with information on openxml template (#10273).+    + Clarify that `--variable` can only assign string values (#10298).++  * Fix comments in TEI writer referring to DocBook (#10430, Evan Silberman).++  * Fix several typos in documentation (#10349, Andreas Deininger).++  * Allow Diff 1.0.++  * Add font-settings.latex partial to pandoc.cabal (#10379).++  * Bump upper bound for data-default.++  * Use latest typst, texmath, pandoc-lua-marshal, commonmark-pandoc,+    commonmark-extensions, skylighting, skylighting-format-blaze-html.+++## pandoc 3.5 (2024-10-04)++  * Add command-line options `--list-of-figures/--lof` and+    `--list-of-tables/--lot` (#10029, Akash Patel).+    Only docx, latex, and context are affected by these options currently.+    Setting the `lof` and `lot` variables will also work for the formats+    that are currently supported.++  * Defaults files:  interpolation of environment variables now+    works for `to` and `from` fields (#8024). This is needed because+    these files can contain paths of custom readers/writers.++  * Docx reader:++    + Reset lists after headers in same list `numId` (#10258).+      To accomplish this, we add a Heading constructor to BodyPart and+      include on it all the information list items have.++  * DocBook reader:++    + Parse id, class, and tabstyle on tables (#10181, Erik Rask).+      Add parsing of id (xml:id), class, and tabstyle XML attributes+      for table and informaltable in the DocBook reader.+      The tabstyle value is put in the 'custom-style' attribute.++  * Dokuwiki reader:++    + Be more forgiving about misaligned lists, like dokuwiki itself (#8863).+    + Improve blockquote parsing in dokuwiki. Allow for quoted code blocks.+    + Enable smart extension.+    + Properly parse `--` and `---` as dashes.+    + Fix block quote behavior (#6461). Blockquotes are not really block+      containers in DokuWiki; the lines are interpreted literally (so,+      e.g., you can't start a list), and line breaks are added at the ends.++  * EPUB reader:++    + Fix links to other files in the EPUB, making them internal links+      to a fragment derived from the filename (#10207).  There was+      already code to handle links like `#foo`, but not to handle links+      like `ch0001.html#foo`.++  * LaTeX reader:++    + Add em, ex, px, mu to list of units for dimension args (#10212).++  * ANSI writer:++    + Fix subscripts (Evan Silberman).++  * DokuWiki writer:++    + Don't emit `<HTML>` tags (#7413). The use of these tags is now+      strongly discouraged for security reasons, and will be removed.+      We previously used them as a fallback for lists that could not+      be represented using DokuWiki syntax, e.g. ordered lists with+      fancy numbers or lists with multiple blocks in their items.+      We also used them for block quotes with multiple blocks as+      their contents. We now use the `<WRAP>` syntax (from the optional+      WRAP plugin) to handle lists with multiple blocks as their contents.+      A new method of handling block quotes with complex contents+      has the side benefit of also handling nested block quotes,+      which weren't supported before.+      `<HTML>` and `<html>` tags are only for raw HTML blocks and+      inlines, and only if the `raw_html` extension is enabled. (It is+      now a valid extension for `dokuwiki`, though off by default.)++  * Docx writer:++    + Support `--list-of-figures` and `--list-of-tables` (or `lof` and+      `lot` variables) (Akash Patel).++  * HTML writer:++    + Don't emit missing title/lang warnings if templates does not+      contain the `pagetitle` or `lang` variables respectively (#9370).++  * LaTeX writer:++    + Better fix for lists in definition lists (#10241).+      In commit a26ec96d89ccf532f7bca7591c96ba30d8544e4a we added an+      empty `\item[]` to the beginning of a list that occurs first+      in a definition list, to avoid having one item on the line with+      the label. This gave bad results in some cases (#10241) and there+      is a more idiomatic solution anyway: using `\hfill`.+    + Avoid error on `refs` div with empty citations (#10185).+      If there are no citations, don't emit an empty CSLReferences environment.++  * RST writer:++    + Change bullet list hang from 3 to 2. This accords with the style in+      the RST reference docs.+    + Handle cases where indented context starts with block quote (#10236).+      In these cases we emit an empty comment to fix the point from+      which indentation is measured; otherwise the block quote is not+      parsed as a block quote. This affects list items and admonitions.+    + Don't enclose the list table in a `.. table::`; this leads to+      doubled captions (#10226).+    + Fix alignment of list table items corresponding to cells (#10227).++  * JATS template:++    + Support `floats-group` (Albert Krewinkel, see #10196).+      The content of the `floats-group` variable is now rendered in a+      `<floats-group>` element when using the *publishing* or *archiving* tag+      sets.++  * LaTeX and Beamer templates:++    + Split old default.latex into two templates, `default.latex` and+      `default.beamer`, factoring common parts into partials:+      `fonts.latex`, `common.latex`, `passoptions.latex`,+      `hypersetup.latex`, `after-header-includes.latex`.+    + Make `default.beamer` the default template for beamer.+    + Add `shorttitle`, `shortsubtitle`, `shortauthor`, `shortinstitute`,+      `shortdate` variables to beamer template (#10248, Thomas Hodgson).+    + Make `--number-sections` work with beamer (#12045, Thomas Hodgson).+    + Support a list of images for `titlegraphic` in beamer template+      (#10246, Thomas Hodgson). Title graphic options will be+      applied to each title graphic. Images will be separated by `\enspace`.+    + Beamer theme options (#10243)+    + Add theme options to beamer template: `colorthemeoptions`,+      `fontthemeoptions`, `innerthemeoptions`, `outerthemeoptions` (#10243,+      Thomas Hodgson).+    + Don't load amsmath, amssym in beamer template. These are loaded by+      beamer automatically.++  * Text.Pandoc.SelfContained:++    + Improve handling of links to remote CSS (#10261).++  * Text.Pandoc.Class:++    + Allow extracting `data:` URIs even in PandocPure (`--sandbox`)+      (#10249).+    + Export `extractURIData` [API change].++  * Text.Pandoc.PDF:++    + Read `.toc` and `.log` files from output directory (#10186).+      When this is different from the input directory, this is+      where `.toc` and `.log` files are written.++  * Text.Pandoc.Shared:++    + Modify `addPandocAttributes` for changes in commonmark-pandoc.+      The new commonmark-pandoc version automatically adds the+      attribute `wrapper="1"` on all Divs and Spans that+      are introduced just as containers for attributes that belong+      properly to their contents.  So we don't need to add the+      attribute here. This gives much better results in some cases.+      Previously the wrapper attribute was being added even for+      explicit Divs and Spans in djot, but it is not needed in these cases.++  * Text.Pandoc.Options:++    + Add `writerListOfFigures` and `writerListOfTables` fields+      to `WriterOptions` (#8245, Akash Patel). [API change]++  * Text.Pandoc.App:++    + Add `optListOfFigures` and `optListOfTables` to `Opt` (#8245)+      [API change].++  * Lua subsystem (Albert Krewinkel):++    + Update List module (#9835). The module now comes with a method+      `:at(index[, def])` that allows to access indices, accepts+      negative indices to count from the end, and will return the+      `def` value as a default if the list has no item at the given position.+      Furthermore, the list constructor `pandoc.List` now accepts iterators.+      E.g., `pandoc.List(text:gmatch '%S+')` returns the list of words+      in `text`.+    + Support character styling via `pandoc.layout`. The `Doc` values+      produced and handled by the `pandoc.layout` module can now+      be styled using `bold`, `italic`, `underlined`, or `strikeout`. The+      style is ignored in normal rendering, but becomes visible when+      rendering to ANSI output. The `pandoc.layout.render` function+      now takes a third parameter that defines the output style,+      either *plain* or *ansi*.+    + It is now possible to return a single filter from a filter file, e.g.+      ``` lua+      -- Switch single- and double quotes+      return {+        Quoted = function (q)+          elem.quotetype = elem.quotetype == 'SingleQuote'+            and 'DoubleQuote' or 'SingleQuote'+          return elem+        end+      }+      ```+      The filter must not contain numerical indexes, or it might be treated+      as a list of filters.+    + Add `list_of_figures` and `list_of_tables` to writer options+      (Akash Patel).++  * Use latest releases of commonmark, commonmark-pandoc, texmath, djot.++  * Stop depending on package SHA (Albert Krewinkel). Use `crypton` instead.++  * `linux/make_artifacts.sh`: add riscv64 support (Olivier Benz).++  * Fix invalid XML in `test/docx/normalize.docx` (#10242).++  * `doc/lua-filters.md`: list functions in `pandoc.utils` alphabetically+    (Albert Krewinkel).++  * MANUAL.txt:++    + Clarify  use of `beamerarticle` variable (#10250).+    + Add clarification to address user issues like #6704 (Yehuda Katz).++## pandoc 3.4 (2024-09-09)++  * New output format: `ansi` (for formatted console output) (Evan Silberman).+    Most Pandoc elements are supported and printed in a reasonable way, if+    not always ideally. This version does no detection of terminal+    capabilities, nor does it fall back to different output styles for+    less-capable terminals.++  * Add command line options `--table-caption-position` and+    `--figure-caption-position`. These allow the user to specify whether+    to put captions above or below tables and figures, respectively.+    The following output formats are supported: HTML (and related such+    as EPUB), LaTeX (and Beamer), Docx, ODT/OpenDocument, Typst.++  * Change default `--pdf-engine` via HTML to WeasyPrint (#10142).+    `wkhtmltopdf` is deprecated.  `weasyprint` is the easiest-to-install,+    maintained alternative.  For better results, one might prefer+    `pagedjs-cli`.++  * Org reader:++    + Fix parsing of src blocks with an `-i` flag (#10071, Albert Krewinkel).+      Tabs are now preserved in the contents of *src* blocks if the the block+      has the `-i` flag.++  * RTF reader:++    + Handle images inside `shp` contexts (#10145).++  * RST reader:++    + Improve simple table support (#10093). Multiline rows occur+      only when the *first* cell is empty; we were previously treating+      lines with *any* empty cell as row continuations. In addition, we+      no longer wrap multiline cells in Para if they can be represented+      as Plain. This is consistent with docutils behavior.++  * LaTeX reader:++    + Math environments don't have bracketed options (#10160).+    + Parse nested tabular environments (#4746).++  * Typst reader:++    + Change how "block" elements are handled. Previously they were+      always parsed as divs.  But actually they can occur in some "inline"+      contexts.  Now we first try to parse them as inlines, and only as+      blocks if that fails.  A surrounding Div or Span element is added+      only if there is an identifier.++  * HTML reader:++    + Only parse main element's contents (if present) (#10140).+      If main has an id or class, we include a div with that id or class;+      otherwise just the contents.+    + Read TeX annotation in MathML content if present (#9971).+    + Better handle KaTeX-generated math (#9971). KaTeX emits the mathml+      followed by a span with an HTML fallback. Previously pandoc was+      converting both.  We now ignore the HTML fallback span, marked+      with class `katex-html`.++  * Docx reader:++    + Add "SuppressAuthor" and "AuthorOnly" to citationMode+      when `+citations` is used (thomjur).++  * New module: Text.Pandoc.Writers.ANSI [API change] (Evan Silberman).++  * Docx writer:++    + Support `custom-style` attribute for docx table (Sebbones).+    + Support `--number-offsets`.+    + Make table/figure rendering sensitive to caption position settings.++  * OpenDocument writer:++    + Make table/figure rendering sensitive to caption position settings.++  * Typst writer/template:++    + Implement figure caption positions by triggering a show rule in+      the default template, which determines caption positions for+      figures and tables globally.+    + Don't include trailing semicolon after `@` style citations with suffixes+      (#10148).+    + Template: move header-includes before show doc (#9996, Gordon Woodhull).++  * LaTeX writer:++    + Make table/figure rendering sensitive to caption position settings (#5116).+    + Preserve locator labels with `--natbib` (#10057).++  * HTML writer/template:++    + Make `<figcaption>` placement sensitive to caption position+      settings. For tables, `<caption>` must be the first element, and+      positioning is determined by CSS, for here we set a variable+      which the default template is sensitive to.+    + Use `makeSectionsWithOffsets` for `writerNumberOffsets`,+      instead of the old, inefficient code.+    + Don't add doc-biblioref role to every link in a citation;+      only to links to the bibliography (#10156).+    + Add `data-` when rendering `label` attribute (#10048).++  * Markdown writer:++    + Avoid emitting markdown caption if table has fallen back to raw HTML,+      which will then contain a `<caption>` tag (#10094).+    + Make math sensitive to `tex_math_gfm` extension (#9121).+      This means that in GFM output, the "new style" math will be used+      by default, e.g.++          $`x=y`$++          ```math+          x = y+          ```++      To defeat this and get the older behavior, namely++          $x=y$++          $$x=y$$++      one could use `-t gfm-tex_math_gfm`.++  * AsciiDoc writer:++    + Add `link:` prefix when needed (#10105). AsciiDoc requires it+      except for `http`, `https`, `irc`, `mailto`, `ftp` schemes (#10105).+    + Preserve original base level (#10062). We used to normalize so+      that the base level is always 1, but asciidoc no longer seems+      to care about that, and the behavior creates difficulties when+      we are converting fragments.+    + Don't emit empty figure caption (#10047).++  * ODT writer:++    + Add TableCaption to styles.xml (#10058, Ian Max Andolina).++  * LaTeX template:++    + Fix wrong beamer color in (sub)section page (Jonathan).++  * Text.Pandoc.Options:++    + Add `CaptionPosition` and new `WriterOptions` fields+      `writerFigureCaptionPosition` and `writerTableCaptionPosition`+      [API change].++  * Text.Pandoc.Opt:++    + Change default for optNumberOffset to `[]`. This behaves the same as+      `[0,0,0,0,0]`.+    + Add `Opt` fields `optFigureCaptionPosition` and+      `optTableCaptionPosition` [API change].++  * Text.Pandoc.Format: change `formatFromFilePaths` so that it is+    smarter about URLs.  URLs are parsed, and we take the format from+    the path component, if present (#10141). This means that+    `https://emacs.org/` will be treated as HTML, while+    `https://emacs.org/sample.org` will be treated as Org.++  * Text.Pandoc.URI:++    + Add unofficial `gemini:` to list of URI schemes (Pau RE).++  * Text.Pandoc.Shared:++    + Add `makeSectionsWithOffsets` [API change].+    + Remove `stripEmptyParagraphs [API change] (Albert Krewinkel).+      This function is no longer used.++  * Text.Pandoc.Highlighting: Expose `formatANSI` [API change]+    (Evan Silberman).++  * Text.Pandoc.Writers.Shared: export `to{Sub,Super}scriptInline`+    [API change] (Evan Silberman).++  * Remove use of partial functions (e.g. `head`) in code.++  * Use latest skylighting-core, skylighting, doclayout, texmath, typst.++  * pandoc-lua-engine: Add accessors for several writer options, including+    some that were added in previous releases.++  * pandoc-server: Initialize some missing fields in WriterOptions:+    `writerEpubTitlePage`, `writerChunkTemplate`, `writerListTables`,+    `writerFigureCaptionPosition`, `writerTableCaptionPosition`.++  * CONTRIBUTING.md: Summarize steps for adding a new cli option.++  * MANUAL.txt:++    + Clarify that the `--number-offset` option should only+      directly affect numbering of the first section heading in+      a document; subsequent headings will increment normally.+    + Fix asciidoc link (#10039).+    + Fix CSL Docs broken link (#10100, Tristano Ajmone).+    + Document the use of `luatexja` when CJKmainfont is used with lualatex+      (#3873, Kolen Cheung).+    + Add a `citations` (typst) section to the manual (#9127).+    + Clarify that `citations` affects both input and output for `org`.+    + Add note on `--citeproc` that you may need to disable `citations`+      extension on the output format (e.g., `-t markdown-citations`) to+      see the rendered citation (#9127, #10012).++  * INSTALL.md — reorganise info on static binaries and add conda-forge+    install options (#10098, #10069, Ian Max Andolina).++## pandoc 3.3 (2024-07-28)++  * New cli option: `--link-images`.  This causes images to be linked+    rather than embedded in ODT.++  * Allow `--number-sections` to take an optional `true|false` argument.++  * RTF reader:++    + Handle `\*\shppict` without dropping image (#10025).++  * TWiki Reader:++    + Recognize WikiWords as internal links (#9941).+    + Avoid partial function.++  * Typst reader:++    + Ignore 'pad' and just parse its body (#9958).+    + Use typst 0.5.0.5. Fixes parsing of equations like `$1.$`.++  * Docx writer:++    + Fix regression with nested lists (#9994). The bug affects e.g.+      ordered lists with bullet sublists; after the sublist the top-level+      list reverts to bullets instead of being properly numbered.+      This is a regression introduced in version 3.2.1.++  * BibTeX writer:++    + Ensure that "literal" names are enclosed in braces (#9987).++  * Man writer:++    + Use default middle header when metadata does not include `header`+      (#9943).  This change causes pandoc to omit the middle+      header parameter when `header` is not set, rather than+      emitting `""`.  The parameter is optional and man will use+      a default based on the section if it is not specified.++  * HTML templates: don't load polyfill (#9918).+    This was added in a period when MathJaX required polyfill.+    MathJaX no longer recommends this and polyfill should no+    longer be necessary on any reasonably modern browser.++  * Translations:++    + Add `ua.yaml` (Jens Oehlschlägel).+    + Add a script (`tools/update-translations.py`) and Makefile+      target (`update-translations`) to update translation data+      automatically from babel and polyglossia upstream+      (Stephen Huan).+    + Use this script to update language data, increasing the number+      of languages we cover (Stephen Huan).  Fix a few small bugs in+      existing translations.++  * Fix some mistakes with Japanese language code (#9938).+    In several places we were mistakenly assuming that the BCP 47 code for+    Japanese language was `jp`.  It is `ja`.++  * Text.Pandoc.Options:++    + New field in WriterOptions: `writerLinkImages` [API change] (#9815).++  * Text.Pandoc.App.Opt:++    + New field in Opt: `optLinkImages` [API change] (#9815).++  * Lua subsystem:++    + Keep `lpeg` and `re` as "loaded" modules (Albert Krewinkel).+      The modules `lpeg` and `re` are now treated as if they had been+      loaded with `require`. Previously the modules were only assigned+      to global values, but could be loaded again via `require`,+      thereby allowing to use a system-wide installation. However, this+      proved to be confusing.++      The old behavior can be restored by adding the following lines to+      the top of Lua scripts, or to the `init.lua` in the data dir.++          debug.registry()['_LOADED'].lpeg = nil+          debug.registry()['_LOADED'].re = nil++  * `pandoc-cli`: Include pandoc copyright in Lua version info (Albert+    Krewinkel).++  * `pandoc-cli`: Refer printing of version info to the Lua interpreter+    (Albert Krewinkel). The Lua interpreter no longer terminates when+    called with `-v` or `--version` arguments, thus improving+    compatibility with the default `lua` interpreter program.++  * Avoid partial functions in JATS reader, DocBook writer, Haddock reader.++  * Allow tls 2.1.x.++  * MANUAL.txt:++    + Make documentation of extensions clearer (#9060).+    + Fix section level for two Extensions entries.++  * lua-filters.md: Partially autogenerate docs for module `pandoc`+    (Albert Krewinkel). The documentation system isn't powerful enough to+    generate the full documentation automatically.++## pandoc 3.2.1 (2024-06-24)++  * Fix `gfm_auto_identifiers` to replace emojis with their aliases,+    as documented (#9876).++  * CSV reader:++    + Turn line breaks into LineBreaks not SoftBreaks (#9797).++  * Docx reader:++    + Support task lists (#8211).+    + Fix a small bug in parsing delimiters in numbered lists,+      which led to the default delimiter being used wrongly in some cases.+    + Improve handling of captions.+      - Turn captioned images into Figure elements. Closes #9391.+      - Improve the logic for associating elements with captions (#9358).+      - Ensure that captions that can't be associated with an+        element aren't just silently dropped (#9610).+    + Support HorizontalRule. We support both pandoc-style and the style+      described on a Microsoft support page, an empty paragraph with+      a bottom border (#6285).+    + React to `"left"` value on `jc` attribute.+    + Handle column and cell alignments (#8551). We take the column alignments+      from the first body row.+    + Fix a bug that caused comments inside insertions or deletions+      to be ignored (#9833).++  * HTML reader:++    + Better handle non-`li` elements in `ul` and `ol` (#9809).+      For example, a `p` after a closed `li` will be incorporated into+      the previous `li`. This mirrors what browsers do with this+      invalid HTML.++  * LaTeX reader:++    + Fix parsing of dimensions beginning with `.`, e.g. `\kern.1pt` (#9902).++  * Markdown reader:++    + Allow author-only textual citations (#7219). E.g. `-@reese2002`+      outside of brackets.++  * RST reader:++    + Tighten up rules for when emphasis can start (#9805).+    + Support `:cite:` role with citeproc (#9904). A subset of the+      functionality of the sphinxcontrib-bibtex extension to Sphinx+      is supported.++  * Textile reader:++    + Don't let spans begin right after a symbol (#9878).++  * Typst reader:++    + Fix an incomplete pattern match (#9807).+    + Handle inline bodies ending in a parbreak. E.g.+      ```+      `#strong[+      test+      ]+      ```++  * ConTeXt template: remove `\setupbackend[export=yes]` (#9820).++  * Docx writer:++    + Allow OpenXML templates to be used with `docx` (#8338, #9069, #7256,+      #2928). The `--reference-doc` option allows customization of styles in+      docx output, but it does not allow one to adjust the content of the output+      (e.g., changing the order in which metadata, the table of contents,+      and the body of the document are displayed), or adding boilerplate+      text before or after the document body.  For these changes, one can+      now use `--template` with an OpenXML template.  (See the default+      `openxml` template for a sample.) `--include-before-body` and+      `--include-after-body` can also now be used with `docx` output.+      The included files must be OpenXML fragments suitable for+      inclusion in the document body.+    + New unexported module Text.Pandoc.Writers.Docx.OpenXML.+    + Omit `jc` attribute on table cells with AlignDefault (#5662).+    + Better formatting for task lists. Task lists are now properly+      formatted, with no bullet (#5198).+    + Replace an expensive generic traverse to remove Space elements,+      for better performance.+    + Wrap figures with `id` in a bookmark (#8662).+    + Add eastAsia font hints to `w:r` (#9817). We do this when the text+      in the run contains any CJK characters. This ensures that ambiguous+      code points (e.g. quotation marks) will be represented as "wide"+      characters when together with CJK characters.+    + Clean up Abstract Title and Subtitle in default reference docx.+      Center Subtitle, remove color.++  * HTML writer:++    + Ensure URI escaping needed for `html4` (#9905).+      Unicode characters need not be escaped for html5, and still won't be.+    + Don't emit unnecessary classes in HTML tables (#9325, Thomas Soeiro).+      Pandoc used to emit a `header` class on the `tr` element that forms+      the table header. This is no longer needed, because `head > tr` will+      do the same thing. Similarly, pandoc used to emit `even` and `odd`+      classes on `tr`s, allowing striped styling.  This is no longer needed,+      because one can use e.g. `tbody tr:nth-child(2n)`.+      Compatibility warning:  users who relied on these classes to style+      tables may need to adjust their CSS.++  * JATS writer:++    + Support `supplementary-material` in metadata for `jats_articlepublishing`+      (#9818).++  * LaTeX writer:++    + New method for ensuring images don't overflow (#9660).+      Previously we relied on graphicx internals and made global+      changes to Gin to force images to be resized if they exceed+      textwidth.  This approach is brittle and caused problems+      with `\includesvg` (see #9660). The new approach uses a new macro+      `\pandocbounded` that is now defined in the LaTeX template.+      (Thanks here to Falk Hanisch in https://github.com/mrpiggi/svg/issues/60.)+      The LaTeX writer has been changed to enclose `\includegraphics`+      and `\includesvg` commands in this macro when they don't explicitly+      specify a width or height. In addition, the writer now adds+      `keepaspectratio` to the `\includegraphics` or `\includesvg`+      options if `height` is specified without width, or vice versa.+      Previously, this was set in the preamble as a global option.+      Users should attend to the following compatibility issues:+      - If custom templates are used with the new LaTeX writer, they will have+        to be updated to include the new `\pandocbounded` macro, or an error+        will be raised because of the undefined macro.+      - Documents that specify explicit dimensions for an image may render+        differently, if the dimensions are greater than the line width or+        page height. Previously pandoc would shrink these images to fit,+        but the new behavior takes the specified dimensions literally.+        In addition, pandoc previously always enforced `keepaspectratio`,+        even when width and height were both specified, so images with+        width and height specified that do not conform to their intrinsic+        aspect ratio will appear differently.+    + Task lists must be unordered (#9185).+    + Specify language option for `selnolig` and only include it if+      `english` or `german` is used (#9863). (This includes changes to the+      LaTeX template.) This should restore proper ligature suppression when+      lualatex is used.+    + Fix `--toc-depth` with beamer output (#9861). Previously only top-level+      sections were ever included in the TOC, regardless of the setting of+      `--toc-depth`.+    + Use `\linewidth` instead of `\columnwidth` or `\textwidth`+      for resizing figures, table cells, etc. in LaTeX (#9775).+      `\linewidth`, unlike the others, is sensitive to indented environments+      like lists.++  * LaTeX template: put `babel-lang` in options to beamer (#9868).+    This is required to make beamer use proper localized terms for+    things like "Section."++  * Markdown writer:++    + Don't print extra caption when using `implicit_figures`.+    + Ensure blank line after HTML blocks in commonmark-based formats (#9792).+    + Fix bug rendering block quotes in lists (#9908).++  * Texinfo writer:++    + Ensure proper escaping in all node/link contexts.+    + Target node rather than anchor when possible in internal links.+    + Remove illegal characters from internal link anchors (#6177).+    + Use two commas not one in `@ref`.+    + Don't add anchors to headings. We don't need them, now that we+      make internal links use the node.+    + Avoid duplicate node names.+    + Improve menus. Properly handle the case where the node name is+      different from the descriptive title.++  * Texinfo template: add variables for filename and version.++  * Typst writer:++    + Support '.typst:no-figure' and 'typst:figure:kind=kind' attributes+      (#9778, Carlos Scheidegger). This extends support for fine-grained+      properties in Typst. If the `typst:no-figure` class is present on a+      Table, the table will not be placed in a figure. If the+      `typst:figure:kind` attribute is present, its value will be used+      for the figure's `kind` (#9777). These features are documented in+      `doc/typst-property-output.md`.++  * Typst template:++    + Add subtitle (#9747, Mickaël Canouil).+    + Use content rather than string for title, author, date, email (#9823).+      This allows formatting in title, author, date, and email fields.+      Since the PDF metadata requires a string, and typst only+      converts the title to a string (not the authors), we use++  * Textile writer:++    + Get rid of header, odd, even classes on `tr` (#9376).++  * Text.Pandoc.Class:++    + `fillMediaBag`: Convert IOErrors to warnings when fetching absolute+       paths (#9859, Albert Krewinkel).  This will allow many conversions that+       would have failed with an error to succeed (albeit without images or+       other needed resources).++  * Text.Pandoc.ImageSize:++    + Don't prefer exif width/height when they conflict with image+      width/height (#9871).  That was a mistaken call in #6936.+      Usually when these values disagree, it is because the image+      has been resized by a tool that leaves the original exif values+      the same, so the width/height metadata are more likely to be+      correct that exif width/height.++  * Text.Pandoc.SelfContained:++    + Strip CRs from XML before base64 encoding for data URI+      (so tests can work on Windows).+    + Only create `<svg>` elements for SVG images when the image has+      the class `inline-svg`. Otherwise just use a `data` URI as we do+      with other images (#9787).++  * Lua subsystem (Albert Krewinkel):++    + Split Init module into more modules. The module has grown unwieldy and+      is therefore split into three internal Haskell modules, `Init`,+      `Module`, and `Run`.+    + Add function `pandoc.utils.run_lua_filter` (#9803).+    + Add function `pandoc.template.get` (#9854, co-authored by Carsten Gips).+      The function allows to specify a template with the same argument value+      that would be used with the `--template` command line parameter.+    + Keep CommonState object in the registry. The state is an internal+      value and should be treated as such. The `PANDOC_STATE` global is+      merely a copy; unsetting the global no longer breaks the Lua engine.+    + Allow passing an environment to `run_lua_filter`.+      The default is now to use a *copy* of the global environment when running+      a filter; this ensures better separation when `run_lua_filter` is used+      multiple times. A custom environment can be specified via the+      optional third parameter.+    + Set `pandoc.List` as default metatable for JSON lists (#9834).+      Lists created by `pandoc.json.decode` now behave like lists generated+      via `pandoc.List`. This also ensures that `pandoc.List` tables are+      encoded as JSON arrays when passed to `pandoc.json.encode`.++  * Text.Pandoc.Writers.Shared: export `toTaskListItem` [API change].++  * Add unexported module Text.Pandoc.Char. This exports `isCJK`.+    Use this instead of locally defined `isCJK` in T.P.Readers.MediaWiki.++  * MANUAL.txt:++    + Remove false claim that Lua mode does not support `-i` (#9757,+      Ian Max Andolina).+    + Use level-3 headings for extensions (to avoid gaps).+    + Add anchor for tagging extension.+    + Remove explicit referencess to generate anchors.+      These will be linkified automatically.+    + Fixed links to `option--reference-doc`.+    + Add a note that column widths aren't supported in pptx for Divs+      with class `columns` (#9890).+    + Fix alerts example (#9826, Ian Max Andolina).+    + Fix markup of `babelfonts` example code (Albert Krewinkel).++  * `doc/custom-writers.md`:++    + Fix usage of Template in example (Albert Krewinkel).+    + Document the separator arg of `Writer.Blocks` (Albert Krewinkel).++  * `doc/lua-filters.md` (Albert Krewinkel):++    + Fix outdated documentation for math and quoting functions and fields.+    + Autogenerate docs for module `pandoc.template` and `pandoc.layout`.+    + Document operators of the "Doc" type.++  * pandoc-lua-engine: depend on pandoc >= 3.2 (see #9755).++  * Allow crypton-connection 0.4, time 1.14.++  * Allow tasty-quickcheck 0.11.++  * Use latest emojis, skylighting, skylighting-core, citeproc, djot,+    commonmark-extensions, typst-hs++## pandoc 3.2 (2024-05-11)++  * Change to `--file-scope` behavior (#8741): previously a Div with an+    identifier derived from the filename would be added around the contents+    of each file. This caused problems for "chunking" files into chapters,+    e.g. in EPUB. We no longer add the surrounding Div. This cooperates+    better with chunking. Note, however, that if you have relied on the old+    behavior to link to the beginning of the contents of a file using+    its filename as identifier, that will no longer work.++  * Markdown reader:++    + Allow repeated labels in numbered example lists.+      Previously if you tried to use the same label as an earlier+      example list item, you'd get a new number, not the old one,+      and references to the label would go to the second occurrence.+      Now an existing label will be reused, and no new number will+      be generated.  Caveat:  this only works reliably when the+      re-used example list item occurs by itself in a list, or+      occurs in a list of previously used example list items that+      occur in exactly the same order as previously.+    + Fix `normalCite` so it doesn't consume past a closing `]` boundary+      (#9710).  This was causing an exponential performance bug on long+      lists of links containing potential emphasis characters.+    + Generalize `inlinesInBalancedBrackets` to `inBalancedBrackets`,+      with a parameter for the inner parser.+    + Auto-close unclosed divs (#9635). This applies to both fenced and+      HTML-ish varieties. Otherwise we face an exponential performance+      problem with backtracking. A warning is issued when a div is+      implicitly closed.++  * RST reader:++    + Fix `figclass` and `align` annotations for figures (#7473, Gokul+      Rajiv).++  * LaTeX writer:++    + Use `polytonicgreek` instead of `polutonikogreek` with babel (#9698).+      `polutonikogreek` is outdated. Also recognize both in the LaTeX+      reader.+    + Improve treatment of math inside soul commands (#1294, #5529).+      soul commands (`ul`, `hl`, `st`) are very fragile and the math+      must be handled specially.++  * LaTeX reader:++    + Fix over-eager macro expansion in conditionals (#9676).+    + Parse `flalign`, `flalign*` math environments (#9679). We parse+      these as Math elements with an `aligned` environment. Semantically+      it's not exactly the same, but better than falling back to raw LaTeX.++  * LaTeX template: add `titlegraphicoptions` variable (#9207, Guilhem+    Saurel).++  * Docx reader:++    + Issue warning rather than error when we can't parse EndNote citations+      (see #8433).+    + Fix anchor in header after anchor (#9626, mbracke).++  * RTF reader:++    + Don't try to handle non-default code pages (#9683). Emit a warning+      instead.++  * OpenDocument writer:++    + Implement custom-style for spans (#9657).++  * Typst writer:++    + Add blank line in definition lists with multiple definitions (see+      #9704).+    + Property output (#9648, Gordon Woodhull). The Typst writer will pass+      on specially marked attributes as raw Typst parameters on selected+      elements. This allows extensive customization using filters.+      A separate document (`doc/typst-property-output.md`) has been added+      that provides extensive documentation and examples of the use of+      this feature.++  * Markdown writer:++    + Don't try to align columns in pipe tables with lines greater than+      COLUMNS. The alignment just reduces readibility when the lines+      soft wrap.+    + Don't use `raw_attribute` syntax for raw blocks, unless there is no+      other option (see #9677).  Macros in a `raw_attribute` block don't+      get interpreted when it is read again by pandoc's markdown reader.++  * ConTeXt writer:++    + Replace depreciated `\sc` with `\setsmallcaps` (#9518, James P.+      Ascher).++  * Docx writer:++    + Use conventional styles/indents for Word bullet lists (#7280).++  * `reference.docx`:++    + Use current standard Word theme (#7280). This includes using the+      sans-serif font Aptos instead of the serif font Cambria, and+      default colors for headings.+    + Remove duplicate `DefaultParagraphFont` in `styles.xml`.++  * New module Text.Pandoc.Transforms [API change] (Albert Krewinkel).+    This module exports the following functions which were formerly+    exported from Text.Pandoc.Shared: `headerShift`,+    `filterIpynbOutput`, `eastAsianLineBreakFilter`, as well as some+    functions that were previously not exported.++  * Text.Pandoc.Shared:++    + `headerShift`, `filterIpynbOutput`, and `eastAsianLineBreakFilter`+      are no longer exported from this module; they are now exported+      from Text.Pandoc.Transforms (Albert Krewinkel).++  * Text.Pandoc.Error:++    + Improve reporting of unsupported extensions errors (#9247, Albert+      Krewinkel).++  * Text.Pandoc.App:++    + Move "transforms" after filters (#9664). This will mean that+      `--shift-heading-level-by` affects a heading added by+      `reference-section-title`.++  * Text.Pandoc.App.CommandLineOptions:++    + Simplify output for `OptVersion`. Omit the information about versions+      of dependencies. We no longer emit version info at this level anyway;+      `pandoc-cli` intercepts and handles `--version`. This code would+      only be called if someone used the pandoc library function+      `handleWithOptInfo` in their own program.++  * Text.Pandoc.ImageSize:++    + Export `ImageSize` datatype.++  * Text.Pandoc.SelfContained:++    + Merge class attribute when both img and svg specify it (#9652,+      Carlos Scheidegger).++  * Text.Pandoc.Logging:++    + Add `ScriptingInfo` constructor for `LogMessage` [API change]+      (Albert Krewinkel).+    + Make `DocxParserWarning` a WARNING, not INFO. [API change].+    + Add `UnsupportedCodePage` constructor to `LogMessage` [API change].+    + Add `UnclosedDiv` constructor for `LogMessage` [API change].++  * Lua subsystem (Albert Krewinkel:++    + Add a `pandoc.log` module.+    + Uupdate to pandoc-lua-marshal version 0.2.7 (#8916).+      This fixes counterintuitive behavior of the `content` property on+      BulletList and OrderedList items. Unmarshalling of that field now+      matches the behavior of the constructor.+    + Use newest zip module. This adds a `symlink` function to Entry objects,+      allowing to check if an entry represents a symbolic link.+    + Improve `pandoc.json.decode` docs.+    + Update and fix docs for `pandoc.types.Version` and `pandoc.utils.type`.+    + Add new module `pandoc.image` The module provides basic querying+      functions for image properties.+    + Bump pandoc-lua-engine to 0.2.1.4.++  * Use latest KaTeX CDN asset (#9707, Salim B).++  * `pandoc-cli`: ensure UTF8 when emitting version info.++  * tools/update-lua-module-docs.lua: improve script-internal docs, cleanup+    (Albert Krewinkel).++  * Allow network 3.2.++  * Use latest versions of texmath, djot, skylighting-core, skylighting.++  * Fix command test for #9652.++  * Fix some typos in code comments (#9638, guqicun).++  * Command tests: include regular PATH after directory with the test+    executable (ensures that DLLs will be found on Windows).++  * MANUAL.txt:++    + Document `handout` variable for beamer (#9742).+    + Document formats affected by `--slide-level` (#9745).+    + Update the list of required LaTeX packages (#9728, Albert Krewinkel).+    + Use more descriptive link text for ODT (#9673).+    + Add clarification about `toc-title` in `docx`, `pptx` (#9645).+    + Better document truthiness for conditionals (#9661).+    + Mention that `custom-style` works with ODT (Ian Max Andolina).+    + Harmonize typographic dashes (#9688, Salim B). Standardize on `---`+      with no space.++  * INSTALL.md: Minor tweaks (#9705, Leo Heitmann Ruiz).++## pandoc 3.1.13 (2024-04-07)++  * Org reader:++    + Fix treatment of `id` property under heading (#9639).++  * DocBook reader:++    + Add empty title to admonition div if not present (#9569).+      This allows admonition elements (e.g. `<note>`) to work with+      `gfm` admonitions even if the `<title>` is not present.++  * DokuWiki reader:++    + Link text cannot contain formatting (e.g., `//` is not italics) (#9630).+    + An explicitly empty link text (`[[url|]]`) works the same as an omitted+      link text (#9632).++  * Typst reader:++    + Support Typst 0.11 table features: col/rowspans, table head+      and foot (#9588).+    + Parse cell col/rowspans.++  * CSLJson writer:++    + Put `$` or `$$` around math in `csljson` output (#9616).++  * ConTeXt writer:++    + Fix options order with `\externalfigure`. The dimensions should+      come after the class if both are present.++  * Typst writer:++    + Put label after Span, not before. Labels get applied to preceding markup+      item.+    + Support Typst 0.11 table features (#9588): colspans, rowspans,+      cell alignment overrides, relative column widths,+      header and footer, multiple table bodies with intermediate headers.+      Row heads are not yet supported.+    + The default typst template has been modified so that tables+      don't have lines by default. As is standard with pandoc, we only+      add a line under a header or over a footer. However, a different+      default stroke pattern can easily be added in a template.+    + More reliable escaping in inline `[..]` contexts (#9586). For example,+      we need to escape `[\1. April]` or it will be treated as an ordered list.+    + Handle `unnumbered` on headings (#9585).++  * LaTeX writer:++    + Fix math inside strikeout (#9597).++  * Text.Pandoc.Writers.Shared:++    + Export `isOrderedListMarker` [API change].++  * Change lhs tests so they don't use `--standalone`.+    This will avoid test failures due to minor changes in+    skylighting versions, e.g. #9589.++  * Use latest texmath, typst.++  * Require pandoc-lua-marshal 0.2.6 (#9613, Albert Krewinkel).+    Fixes an issue arising when the value of `content` properties+    on *BlockQuote*, *Figure*, and *Div* elements was an empty list.++  * Update lua-filters.md (#9611, Carlos Scheidegger).+++## pandoc 3.1.12.3 (2024-03-17)++  * Markdown reader: Fix bug with footnotes at end of fenced div (#9576).++  * LaTeX reader:++    + Improve tokenization of `@` (#9555). Make tokenization sensitive to+      `\makeatletter`/`\makeatother`. Previously we just always treated+      `@` as a letter.  This led to bad results, e.g. with the sequence `\@`.+      E.g., `a\@ b` would parse as "ab" and `a\@b` as "a".+    + Make `withRaw` work inside `parseFromToks` (#9517).+      This is needed for raw environments to work inside table cells.+    + Better handling of table colwidths (#9579). Previously the parser just+      failed if the column width specified in `p{}` wasn't a multiple of+      `\linewidth`. This led to cases where content was skipped.++  * Typst writer:++    + Add 'kind' parameter to figures with tables (#9574).+    + Avoid unnecessary box around image in figure (#9236).+    + Omit width/height in images unless explicitly specified (#9236).+      Previously we computed width/heigth for images that didn't have+      size information, because otherwise typst would expand the image+      to fit page width. This typst behavior has changed in 0.11.+      This change fixes a bug in which images would sometimes overflow+      page margins, depending on their intrinsic size.+    + Don't add hard-coded `inset` to tables (#9580). Instead, set this+      globally in the default template, allowing it to be customized.++  * LaTeX template: Fix block headings support for unnumbered paragraphs+    (#9542, #6018, Oliver Fabel).++  * HTML templates: Replace polyfill provider (#9537, @SukkaW).+    Replace polyfill.io with cdnjs.cloudflare.com/polyfill.+    polyfill.io has been acquired by Funnull, and the service has+    become unstable.++  * Korean translations: delete colon in translation for 'to'.+    This was invalid YAML, and not desired anyway, since a colon+    is added.++  * Use latest commonmark, commonmark-extensions.+    This fixes a 3.12 regression in parsing of commonmark/gfm autolinks+    (jgm/commonmark-hs#151).++  * Depend on djot 0.1.1.3, which fixes a serious parsing bug affecting+    regular paragraphs after lists.++  * Depend on latest skylighting, skylighting-core, typst-hs, texmath.++  * MANUAL.txt: Change broken link to IDML cookbook (#9563).++## pandoc 3.1.12.2 (2024-02-29)++  * Docx reader:++    + Ensure that table captions are counted (#9518).+    + Detect caption by style name not id (#9518).+      The styleId can change depending on the localization.+    + Avoid emitting empty paragraph where caption was.++  * Markdown reader: fix regression in link parsing with wikilinks extensions+    (#9481).  This fixes a regression introduced in 3.1.12.++  * Org reader/writer: support admonitions (#9475).++  * Org writer: omit extra blank line at end of quote block.++  * Typst writer: ensure that `-`, `+`, etc. are escaped at beginning of block+    (#9478). Our recent relaxing of escaping (#9386) caused problems for+    things like emphasized `-` characters that were rendered using+    `#strong[-]#`.  This now gets rendered as `#strong[\-]`.++  * LaTeX writer: fix bug when a language is specified in two different ways+    (#9472). If you used `lang: de-DE` but then had a span or div with+    `lang=de`, the preamble would try to load `ngerman` twice, leading+    to an error. This fix ensures that a language is only loaded once.++  * Docx writer: Don't copy over `footnotePr` in `settings.xml`+    from reference.docx (#9522).++  * EPUB writer: omit EPUB2-specific meta tag on EPUB3 (#9493).+    This caused a validation failure in epubs with cover images.++  * Lua: avoid crashing when an error message is not valid UTF-8 (Albert+    Krewinkel).++  * Text.Pandoc.SelfContained:++    + Add `role="img"` to svgs.+    + Add `aria-label` to svg elements with `alt` text if present.+      Screen readers ignore `alt` attributes on svg elements but do+      pay attention to `aria-label` (#9525).++  * Text.Pandoc.Shared: Fix regression in section numbering in+    `makeSections` (#9516). Starting with pandoc 3.1.12, unnumbered+    sections incremented the section number.++  * Text.Pandoc.Class: fix `openUrl` TLS negotiation (#9483).+    With the release of TLS 2.0.0, the TLS library started requiring+    Extended Main Secret for the TLS handshake. This caused problems+    connecting to zotero's server and others that do not support TLS 1.3.+    This commit relaxes this requirement.++  * Depend on djot 0.1.1.0 (fixes rendering on multiline block attributes).++  * Use new releases of skylighting-format-blaze-html (#9520).+    Fixes auto-wrapping of long source lines in HTML print media.++  * Use new commonmark-extensions (fixes issue with the+    `rebase_relative_paths` extension when used with commonmark/gfm.++  * Makefile: improve epub-validation target (#9493).+    Use `--epub-cover-image` to catch issues that only arise with that.++## pandoc 3.1.12.1 (2024-02-17)++  * EPUB writer: omit EPUBv3-specific accessibility features on epub2+    (#9469). Fixes a regression in 3.1.12.++  * More fixes for SVG ids with `--self-contained` (#9467).+    This generalizes the fix to #9420 so it applies to things like+    `style="fill(url(#..."` and should fix problems with SVGs including+    gradients.++  * Powerpoint writer: properly handle math in headings and tables (#9465).+    This ensures that paragraphs containing math are wrapped in+    a `mc:AlternateContent` node as required.++  * Makefile: make validate-epub check v2 output too.++## pandoc 3.1.12 (2024-02-14)++  * Add `djot` as input and output format. Djot is a light markup syntax+    (https://djot.net).++    + New module Text.Pandoc.Readers.Djot [API change]. The function+      `readDjot` is also exported by Text.Pandoc.Readers.+    + New module Text.Pandoc.Writers.Djot [API change]. The function+      `writeDjot` is also exported by Text.Pandoc.Writers.++  * `--number-sections` now uses the first digit for the number of+    the top-level section, no matter what its level. So if the top-level+    section is level-2, numbers will be `1`, `2`, etc. rather than+    `0.1`, `0.2`, as in the past (#5071). For some backwards compatibility,+    we revert to the old behavior when the `--number-offset` option is used.++  * DocBook reader:++    + Better handling of `<procedure>` and `<substeps>` (#9341):+      `<procedure>` now gets parsed as an ordered list, and+      `<substeps>` as a sublist.++  * Man reader:++    + Move spaces outside of emph/strong (#9445).++  * MediaWiki reader:++    + Don't make leading blanks underscores in image links (#9425).+    + Allow lowercase `image:` (#9424).++  * BibTeX reader:++    + Support `pagetotal` in converting BibLaTeX.++  * Markdown reader:++    + Fix wikilinks extensions to allow newlines in titles (#9454).++  * EPUB reader:++    + Don't put `#` characters in identifiers.++  * LaTeX reader:++    + Improve treatment of `\cref`, `\Cref` (#7463). Use the+      reference-type `ref+label` and `ref+Label`. Also, associate with+      `\vref` `ref` instead of `ref+page`.+    + Limited support for `\Cref` (#7463).+    + Generate relative widths for `\linewidth`, `\textheight` (#9388).++  * Typst reader:++    + Fix handling of `\overline` (#9294). Due to a typo, it was being+      incorrectly rendered as an `\underset`.+    + Improve handling of inline `#quote` (#9413).+    + Fix handling of `dot()`, `tilde()`, `ddot()` (jgm/typst-hs#38).+    + Fix character used for `norm` (jgm/typst-hs#38).++  * Typst writer:++    + Use reference form (e.g. `@jones2000[p. 30]`) for citations when+      possible.+    + Use `#ref` or `@` for links with `reference-type="ref"` (#7463).+      This attribute is added to LaTeX `\cref`, for example.+    + Improve citation support (#9452). Emit `form: "prose"` or `form: "year"`+      qualifiers if the citation is author-in-text or suppress-author.+      Strip initial comma from suffix, since typst will add an extra one.+    + Unescape URI escapes in image paths (#9389).+    + Handle labels and citaiton ids with spaces and other special+      characters (#9387). In these cases, we produce an explicit `label()`+      rather than using `<>` or `@`.+    + Avoid producing illegal labels (#9387).+    + Avoid unnecessary escapes (#9386).++  * LaTeX writer:++    + Make writer sensitive to `empty_paragraphs` extension (#9443).+    + Fix beamer highlighting (mh4ckt3mh4ckt1c4s).+    + Create valid table even when table is empty (#9350).+    + Set font fallback for babel main font (Max Heller).+    + Add some kerns where needed between quotes (#9371).++  * HTML writer:++    + Add suffix to multiple footnote section ids, so they are+      unique (Sam May). This is necessary when `--reference-location`+      is `block` or `section`.++  * EPUB writer:++    + Add ARA roles for accessibility (#9378, Iacobus1983).+      Footnote references are given role "doc-noteref", footnote text+      gets "doc-footnote", and nav gets "doc-toc".+    + Ensure that an alt attribute is always added (#9354). This seems to+      be required by iBooks; even an empty alt attribute will satisfy it.+    + Add `xml:lang` to package element (#9372).+    + Add accessibility metadata to EPUB metadata (#9372, #9400,+      Iacobus1983 and John MacFarlane). Reasonable default values are+      used to ensure that pandoc's EPUBs conform to the EU Accessibilty Act+      requirements, but values can be overridden using metadata.++  * Docx writer:++    + Restore ability to center-justify table (#9393). The fix to+      #5947 caused all tables to be left indented. This was necessary+      to avoid extra indentation in table cells when a table appeared+      in a list item. This change makes the changes conditional, so+      that they only affect tables in list items.++  * Man writer:++    + Fix bug with long URLs (#9458). URLs with more than 68 characters didn't+      display properly because of wrapping.+    + Support (limited) syntax highlighting in code blocks (#9446).+      Currently only boldface and italics are supported. The `monochrome`+      style might be of use for those generating man pages.++  * Org writer:++    + Escape special lines in code blocks (#9218, Albert Krewinkel).++  * Markdown writer:++    + Use different width fences for nested divs (#9450). Outer divs+      have longer fences. This aids clarity for the reader, making it+      easier to see where the div ends. It also makes the output+      compatible with some other implementations, e.g. micromark,+      which require different-width fences for nesting.+    + Fix output for pipe tables with a huge number+      of columns (#9346). Previously we got invalid pipe tables when the+      number of table columns exceeded the setting of `--columns`.++  * Powerpoint writer:++    + Fix regression in layout for slides with figures (#9442).+    + Use internal column widths in pptx writer tables (#5706,+      Tomas Dahlqvist). The table writer used to only divide all+      available width evenly for all columns. In this update the code+      uses the incoming widths if they are available. If they are not+      set the earlier even distribution is used. Some of the golden+      templates are adjusted slightly because of different rounding when+      using the new calculation model.++  * Custom writers:++    + Fix handling of common state (#9229, Albert Krewinkel).+      The CommonState (`PANDOC_STATE` in Lua) may change between the time that+      a custom writer script is first loaded and when the writer is run.+      However, the writer was always using the initial state, which led to+      problems, e.g. when the mediabag was updated in a filter, as those+      updates where not visible to the writer. The state is now updated+      right before the writer function runs.++  * Text.Pandoc.SelfContained:++    + Fix id replacements in SVGs with clipping paths (#9420).+      This fixes `--embed-resources` when SVGs have `clip-path` attributes.+    + Fix size of duplicated SVGs with `--embed-resources` (#9439).++  * ConTeXt template: support font fallback (#9361, Lawrence Chonavel).++  * Text.Pandoc.Shared:++    + `addPandocAttributes`: use `wrapper` attribute, not `wrap`, for+      Divs and Spans added as wrappers to hold attributes on elements+      that do not accept them.+    + `makeSections` behavior changes:+      - When the optional base level parameter is provided, we no+        longer ensure that the sequence of heading levels is gapless+        (#9398). Instead, we set the lowest heading level to+        the specified base level, and adjust the others accordingly. If+        an author wants to skip a level, e.g. from level 1 to level 3,+        they can do that. In general, the heading levels specified+        in the source document are preserved; `makeSections` only+        puts them into a hierarchical structure.+      - Section numbers are now assigned differently, as described above+        under `--number-sections` changes (#5071).+    + Improve `makeSections` code for section number calculation.++  * Text.Pandoc.Chunks:++    + Autogenerate unique ids for sections missing them (#9383).+      This is needed for TOC generation to work properly. We can't+      create TOC links if there are no ids. This fixes some EPUB validation+      issues we've been getting since switching over to Chunks for chunking.+    + Improve `fixTOCTreePaths`. We weren't adding ids for section headings+      that don't head a chunk, but these headings are needed for a TOC.++  * Lua: catch encoding error in `pandoc.read` (#9385, Albert Krewinkel).+    Fixed a bug that could lead to an un-catchable error and program+    termination when `pandoc.read` was called with invalid UTF-8 input.++  * LaTeX template: support font fallback (lawcho).  This support is+    LuaLaTeX-specific.  See MANUAL.txt for documentation.++  * Text.Pandoc.Readers: Add `readMan` to exports [API change] (George Stagg).++  * Text.Pandoc.PDF:++    + Reliably detect when TOC has changed (#9295). Sometimes the TOC+      changes but there are no warnings: this happens when no labels+      are present. In this case we must rerun LaTeX. So we now take the+      SHA1 hash of the TOC file and rerun LaTeX if it changes between runs.+    + Increase maximum number of LaTeX runs to 4 (#9299). On some documents,+      4 runs are needed (e.g. when a LastPage reference is used).+    + Avoid `readFileLazy`, which caused improperly cleaned-up+      temp directories on Windows (#9460).++  * MANUAL.txt:++    + Harmonize spelling of Markdown and MultiMarkdown (#9402, Salim B).+    + Add `<pre>` to list of exceptions for `markdown_in_html_blocks`+      extension (#9305).+    + Add clarification to docs for `--resource-path` (#9417).++  * Makefile: Validate generated EPUB as part of prerelease checks.++  * Add validation for docx golden files to CI (Edwin Török).++## pandoc 3.1.11.1 (2024-01-05)++  * Docx reader:++    + Fix HYPERLINK with only switch and no argument (#9246).++  * Org reader:++    + Parse caption and label for grid tables (#9279).++  * MediaWiki reader:++    + Handle multiline math in list items (#9293).++  * OPML writer:++    + Respect `--wrap` options & `--columns` in contents of notes (#9297).++  * ODT/OpenDocument writers:++    + Properly handle highlighting styles (#9287). These styles were+      going into an `office:styles` element in `content.xml`, but this+      is invalid. Instead they must go in `styles.xml`. The variable+      `highlighting-styles` no longer has any effect on the default+      opendocument template, and highlighting styles are not included+      in `opendocument` output.++  * Markdown writer:++    + Add table identifier at end of caption if present (#9279).++  * Text.Pandoc.PDF:++    + Expand list of environment variables to display in verbose output+      (#9303).+    + Ensure that we find all the LaTeX warnings requiring a rerun (#9284).+      This should fix a regression from 3.1.9 that led to incorrect+      alignments in tables (and possibly other issues).++  * Docx writer:++    + Ensure that pandoc's output validates (Edwin Török, #9273, #9269,+      John MacFarlane, #9265, #9266, #9264).+    + Don't emit empty table rows, which seem to cause problems for+      Word (#9224).++  * LaTeX writer:++    + Omit superfluous page locator label when used with `--natbib` or+      `--biblatex` (#9275). These will treat a bare number as a+      page locator, and they will be able to localize it. Note that the+      recognition of the locator label is locale-sensitive; if `lang` is+      `de`, then `S. 33` is a page reference, and `p. 33` is not!++  * Text.Pandoc.Chunks: Fine tune `makeChunks` (#9281).++    + Ensure that chunks not based on sections (those with the+      "preamble" class) get unique identifiers, by appending chunk number.+    + This will also ensure that they get unique path names when+      the path is generated from the identifier.++  * Default HTML5 template: remove html5shiv (and support for IE < 9).++  * Makefile:++    + Fix `make quick-stack`: `j` was expecting a number (Edwin Török).+    + Run built pandoc (instead of pandoc in path).+    + Add `validate-epub` target, using `epubcheck` to test the golden files.+    + Add `validate-docx-golden-tests` target.++## pandoc 3.1.11 (2023-12-15)++  * Typst writer:++    + Emit `;` after typst code, unless followed by space (#9252).+      Otherwise there's the potential that the typst code will swallow+      up a following character.++  * Text.Pandoc.Logging:++    + Add `MakePDFWarning` constructor to LogMessage [API change].+    + Add `MakePDFInfo` constructor to LogMessage [API change].++  * Text.Pandoc.PDF:++    + LaTeX warnings are passed on to the user as warnings.+    + Use `report` with `MakePDFWarning` and `MakePDFInfo` to relay+      verbose information and warnings, instead of writing directly+      to stderr.+    + Parse logs to determine whether additional runs needed, instead of+      running a fixed number of times (#9255). (The number of times+      that was appropriate given pandoc's default templates didn't+      always work for custom templates, and thus pandoc 3.1.10's+      change in the number of runs led to some regressions in PDF+      production.)++  * Makefile: in `make prelease`, add checks that pandoc-cli and+    pandoc have the same version, that pandoc-cli depends on this+    exact version of pandoc, that there is an entry for this version+    in the changelog, and that the version numbers in the+    generated man pages are correct.++  * Regenerate man pages with pandoc 3.1.10. This properly escapes hyphens+    and fixes version numbers in man pages for `pandoc-server` and+    `pandoc-lua`.++  * Depend on texmath 0.12.8.6. This omits unneeded `lr`s in typst+    math output.++  * Depend on typst 0.5. This allows the typst reader to support+    multiline strings, the version type, and the `as`+    keyword with `import`.++## pandoc 3.1.10 (2023-12-12)++  * Link pandoc-cli version to pandoc version. Henceforth pandoc-cli's+    version will be synchronized with pandoc's, and pandoc-cli will+    depend on an exact pandoc version. This will avoid confusion by+    ensuring that `cabal install pandoc-cli-X.Y.Z` installs pandoc+    version X.Y.Z. It will make things more straightforward for+    upstream packagers (see #9232). This scheme does not follow the+    Haskell PVP, but that should cause no harm, because this package+    does not expose a library.++  * Add `alerts` markdown extension. This enables GitHub style markdown+    alerts as a commonmark extension. This extension is now default for+    `gfm`. It can't be used with `markdown`, only with `commonmark` and+    variants.++  * Markdown reader:++    + Preserve newlines in math instead of changing to spaces.+      Otherwise we can get unwanted results if there's+      a `%` comment (#9193).+    + Make attributes work with reference links (#9171).++  * HTML reader:++    + Improve handling of invalidly nested sublists (#9187, cf. #8150).++  * MediaWiki reader:++    + Allow attribute keys with hyphens (#9178).++  * ODT reader:++    + Support attr `text:continue-numbering` (#8979, Stephan Meijer).++  * Typst reader:++    + Allow references (e.g. `@foo`) to become citations+      if there is no corresponding label in the document.+    + Collapse adjacent `cite` elements.+    + Handle supplements in `cite`.+    + Change `cite` (only one key allowed, a label) (typst 0.9 breaking change).+    + Support `quote` element (typst 0.9).++  * LaTeX reader:++    + Handle otherlanguage environment and language-name environments like+    `\begin{french}...\end{french}` (#9202).+    + Fix theorem label parsing (#8872, Hikaru Ibayashi).++  * Docx reader:++    + Unwrap content of shaped textboxes (Stephan Meijer, #9214).+    + Improve handling of `w:sym` (#9220). We now look up symbols in symbol+      fonts using the table defined at Text.Pandoc.Readers.Docx.Symbols.+    + Add unexported module Text.Pandoc.Readers.Docx.Symbols. This gives us a+      table to use to resolve characters included in docx via `w:sym` element.++  * Man reader:++    + Properly handle `.sp` macro inside lists and block quotes (#9201).++  * LaTeX writer:++    + Fix bug with big footnotes inside emphasis (#8982, Hikaru Ibayashi).+    + Handle identifiers inside heading contents. `\phantomsection` can't+      be used in this case, so we need `\hypertarget` (#9209).++  * LaTeX template:++    + Include `bookmark` package unconditionally. This package+      produces better PDF bookmarks than `hyperref` and does it on the+      first pass.++  * Typst writer:++    + Use `quote` for block quotes.+    + Support `--toc-depth` as in other writers (#9242).+    + Put inline image dimensions on enclosing box, not image (#9104).+    + Better handling of tables with captions (#9194).+      We now put these in a figure with a caption argument.+    + Update typst writer to typst 0.9 citation format (#9188).++  * Typst template:++    + Remove custom definition of `blockquote` in default template.+      (We now use built-in `quote`.)+    + Support table of contents.+    + Support csl (#9186, Ian Max Andolina). Typst now supports CSL for its+      native citation engine, so pandoc should use a specified `csl`+      style in the template, falling back to `bibliographystyle` if+      `csl` is not specified.++  * Docx writer:++    + Use different style for block quotes in notes (#9243).+      Using "Footnote Block Text" for the style name, so it can be+      given a different font size if footnotes are.+    + Allow embedded fonts to be used in reference.docx (#6728).++  * HTML5 writer:++    + To conform to validator's expectations, `doc-footnote` role is used+      with `aside` and `doc-endnotes` with `section`.+    + `aside` is used only for notes at ends of sections or blocks;+      if all the notes come at the end of the document, `section` is+      used so we can have the `doc-endnotes` role.++  * JATS writer:++    + Handle case where there is material after refs div (#9166). Previously in+      such cases the references were not being moved to back matter.++  * Ms writer:++    + Don't do normal escapes in filename arguments for PSPIC etc.++  * T.P.RoffChar: escape `-` as `\-`. The `groff_man (7)` man page indicates+    that `-` characters will be treated as typographic hyphens and are not+    appropriate for cases where the output should be copy-pasteable as an+    ASCII hyphen-minus character.  (E.g. in command line options.)+    However, until a recent update groff man did not actually do this;+    it treated `-` and `\-` the same.  With the new update (1.23.0)+    the two are distinguished (see https://lwn.net/Articles/947941/+    for background), so now it is important that pandoc escape `-`.++  * Text.Pandoc.Extension: add `Ext_alerts` constructor [API change].++  * Text.Pandoc.PDF: We now default to running LaTeX only+    once in producing a PDF (instead of twice). This is made possible by the+    shift to the `bookmark` package, which does not require a second pass for+    PDF bookmarks. If a table of contents is present, we still have to run+    three times to get the page numbers, and if beamer is used we still do a+    minimum of two runs.++  * Text.Pandoc.Shared:++    + `renderTags'`: use minimized tag for `rect`.+    + Allow svg `path` element to be minimized.+    + Export `combineAttr` [API change].+    + Improve `isTightList` so that it recognizes an item containing only a list+      which is itself tight as potentially an item in a tight list (#9161).++  * Text.Pandoc.MIME: Ensure we use `.svg` not `.svgz` as extension+    for `image/svg+xml` mime type. This fixes issues with embedded+    SVG images in docx output, among other things (#9195).++  * Text.Pandoc.Class: `openURL` improvements for data uris.+    Only treat data URI as `base64` if ';base64' is specified.+    Otherwise treat as UTF-8 (not 100% reliable but should cover most+    other cases). Strip off `;base64` (or `;charset=...` or whatever)+    from mime type (#9195).++  * Text.Pandoc.SelfContained: Improve treatment of embedded SVGs+    (#9206, #8948).++    + Ensure unique ids for elements by prefixing SVG id.+    + Ensure SVG `id` attribute except when `use` element is used.+    + Remove `width`, `height` attributes from svg element when `use`+      element is used. Instead, add `width` and `height` 100% to the+      `use` element. This seems to get the sizing right.++  * Text.Pandoc.Citeproc: Don't link citations if+    `suppress-bibliography` specified, for there will be nothing to+    link to (#9163).++  * epub.css: add styling for sup and sub (#9160).++  * Switch from `base64` to `base64-bytestring` (#9233).++  * Use newest versions of commonmark, commonmark-extensions,+    commonmark-pandoc, texmath, typst, skylighting, skylighting-core.++  * Benchmark: use standalone documents for reader tests.+    Otherwise typst reader benchmark fails. Note: this means that we are now+    parsing longer documents, so bench results on readers won't be comparable+    to before.++  * MANUAL.txt: update defaults file docs for bibliography fields (#9173).+    Recommend using top-level `bibliography` `csl`, etc. instead+    of a nested `metadata` field. Reason: `${USERDATA}` and `${HOME}`+    are only expanded in these contexts, not in `metadata`.++  * Move man pages to pandoc-cli package (#9245).++## pandoc 3.1.9 (2023-10-27)++  * Make `reference-section-title` work with `jats+element_citations`+    (#9021).++  * Add `bits` as synonym of `jats` as input format.++  * JATS reader:++    + Modify JATS reader to handle BITS too (#9138, Julia Diaz).+      Add provision for title-group, book, book-part-wrapper, book-meta,+      book-part-meta, book-title, book-title-group, index, toc, legend,+      title, collection-meta+    + Fix handling of alt-text (#9130, Julia Diaz). Previously we were+      looking for an attribute that doesn't exist in JATS; alt-text is+      provided by a child element.++  * CommonMark reader:++    + Handle `Ext_tex_math_gfm` (#9121). Parse GFM-specific math+      constructions when `tex_math_gfm` enabled.++  * DokuWiki reader:++    + Allow autolinks to be avoided using e.g. `https:%%//%%...` (#9153).+    + Parse `<code>` and `<file>` as block-level code (#9154).+      Previously we treated them as inline code in some contexts,+      but that is not how DokuWiki works.++  * LaTeX reader:++    + Better handle spacing commands `\hfill`, `\vfill`, `\hskip`,+      `\vskip`, etc. (#9150).+    + Fix incorrect abbreviation for astronomical unit (#9125,+      Michael McClurg).++  * Markdown reader:++    + Fix blindspot with superscript in links (#8981).+      Previously `[^super^](#ref)` wasn't parsed as a link, due to+      code that was meant to prevent footnote markers from being+      recognized as reference links.  This commit tightens up that+      code to avoid this bad effect. We have also added a new+      restriction on footnote labels: they cannot contain the characters+      `^`, `[`, or `]`. Though this is technically a breaking change, we+      suspect that the impact will be minimal, as it's very unlikely+      people would be using these characters in their note labels.+    + Don't apply `--default-image-extension` to data URIs (#9118).+    + More accurate check that a normalCite is not a link,+      bracketed span, or reference (#9080).++  * HTML reader:++    + Allow th to close td and vice versa (#9090).+    + Parse task lists using input elements (#9047, Seth Speaks).++  * Creole reader:++    + Handle empty cells correctly (#9141, Sascha Wilde).++  * Org writer:++    + Escape literal `*`, `|`, `#` at beginning of line with ZWS (#9159).++  * ICML writer:++    + Prevent doubled attributes (#9158).++  * Powerpoint writer:++    + Fix a corruption error caused when the document used both a+      regular png and a png in a data URI (#9113). (Similarly for any+      other image format.) The problem was that duplicate entries in+      `[Content Types].xml` were being created, one for the mime type+      `image/png`, one for `image/png;base64`.++  * LaTeX writer:++    + Fix rowspans in tables so they use the width of+      the column (`=` as the width parameter) (#9140).+    + Don't treat table as "simple" if they have col widths.+      This should help fix a problem wherein some grid tables with+      colspans were overly wide (#9140).+    + Fix uneven indents in line block output (#9088).++  * JATS writer: fix 3.1.4 regression in handling block-level metadata+    (#9092).++  * Ms writer: improvements in image handling (#4475).++    + PDFPIC is now used for PDF images in figures.+    + Inline images that are postscript or PDF are rendered using+      PSPIC or PDFPIC. This isn't ideal, because they will still be+      rendered as if in a separate paragraph, but it's probably+      better than just printing the image name.+    + Units are included in height.++  * HTML writer:++    + If raw format is an HTML side deck format, emit it (James J Balamuta).++  * Typst writer:++    + Add `#box` around image to make it inline. (#9104)+      An `#image` by itself in typst is a block-level element.+      To force images to be inline (as they are in pandoc), we need+      to add a box with an explicit width. When a width is not given+      in image attributes, we compute one from the image itself, when+      possible.+    + Don't allow long heading to wrap (#9132).+    + Escape `(` (#9137). If unescaped `(` occurs in+      certain contexts, it can be parsed as function application.++  * Man writer:++    + Fix some spacing issues around links (#9120).+      We need to use `\c` before a `.UR` or `.MT`, to avoid+      an extra space, and also after.  To ensure that a space+      at the beginning of the following line doesn't get swallowed+      up, we escape it with `\`.+    + Use UR, MT macros for URLs, emails (#9120).++  * Text.Pandoc.Extensions:++    + Add `Ext_tex_math_gfm` constructor to Extension (#9121).+      [API change]. This handles two GitHub-specific syntaxes for math.+      This is now default for `gfm`, in addition to `tex_math_dollars`.+    + Remove duplicates for `Ext_raw_html` and `Ext_pipe_tables`+      in some of the lists (Tim Stewart).++  * Text.Pandoc.Metadata: Add helpful message on some metadata+    YAML errors (#9155).++  * Text.Pandoc.Shared:++    + `splitSentences`: don't split after initials.+      This improves the man and ms writer output, preventing+      sentence breaks after initials.+    + Add `addPandocAttributes` function [API change].+      This is meant to simplify addition of attributes to Pandoc+      elements: for elements that don't have a slot for attributes, an+      enclosing Div or Span is added to hold the attributes.++  * MANUAL.txt:++    + Clarify that formatting can't cross line boundaries+      in line blocks (#9119).+    + Fix legacy option for citation (#8737, 3w36zj6)++  * Update `et` translations (priiduonu).++  * Updated `no` translations (Stephan Daus).+    Renamed no.yaml (macrolanguage Norwegian) to nb.yaml (Norwegian Bokmål).+    Created soft symbolic link from no.yaml pointing to nb.yaml.++  * Lua subsystem: Use the newest LPeg version (lpeg-1.1.*) (#9107,+    Albert Krewinkel).++  * Default `epub.css`: Apply style to h6, format styles, and+    combine identical styles under shared selectors (samuel-weinhardt).++  * Update nix flake with dependencies (piq9117).++  * LaTeX template: fix `\CSLBlock` vertical space (John Purnell).++  * Allow tasty 1.5 and Diff 0.5.++  * Require commonmark-extensions 0.2.4, commonmark 0.2.4.++  * Require texmath 0.12.8.4. This should improve math in+    powerpoint, fixing empty boxes around roots in some cases.++  * Require typst 0.3.2.1++## pandoc 3.1.8 (2023-09-08)++  * JATS reader:++    + Ignore `<processing-meta>` element (#9057, Julia Diaz).+    + Fix conversion of date to ISO 8601 format (#8865).++  * LaTeX template:++    + Add code allow `\cite` to break across lines (#9050).+    + Fix regression with CSL `display="block"` (#7363).+      This restores the line break before the block.+    + Rewrite `CSLReferences` environment to avoid depending on+      `enumitem`, which plays badly with beamer.  Instead we use+      a regular list environment. Thanks to @jpcirrus for the+      concept (#9053).+    + Restore the pre-3.1.7 format of the `CSLReferences`+      environment, which again has two parameters. The first+      determines whether a hanging indent is used (1 = yes, 0 = no),+      and the second is the entry line spacing (0 = none).+    + Add a strut to avoid inconsistencies in spacing (#9058).+    - Remove a break at the end of `CSLRightInline` to avoid+      inconsistencies in spacing. It shouldn't be necessary+      because the paragraph should extend to the right margin (#9058).++  * LaTeX writer:++    + Fix regression with figure labels (#9045). In 3.1.7, pandoc+      added two labels to LaTeX figure environments, one with a+      phantomsection.+    + Fix default citeproc entry-spacing. According to the CSL manual,+      the default entry spacing is 1. We were treating it as 0 (#9058).++  * HTML writer:++    + Use the ID prefix in the ID for the footnotes section (#9044,+      Benjamin Esham).+    + Fix CSL entry-spacing default (#9058).++  * Text.Pandoc.Citeproc:  always include an `entry-spacing` attribute+    in the Div if the bibliography element contains an entry-spacing+    attribute (previously we omitted it when it was 0) (#9058).++  * Clean up pandoc's own man pages by regenerating with pandoc 3.1.7.++  * pandoc-lua-engine: bump lower bound for pandoc (#9046).++  * Depend on texmath 0.12.8.2, fixing binom in typst writer (#9063).++## pandoc 3.1.7 (2023-08-31)++  * Org reader:++    + Don't parse alphabetical lists unless the `fancy_lists` extension is+      enabled (#9042).+    + Allow escaping commas in macro arguments (Amneesh Singh).++  * JATS reader:++    + Support for `<permissions>` metadata (#9037, Julia Diaz).+      metadata objects with multiple fields are created, matching the+      structure in JATS.+    + Correct name of JATS element `attrib`.++  * Markdown reader:++    + Support images with wikilink syntax, e.g. `![[foo|bar]]`, when+      one of the `wikilinks` extension is enabled (#8853).+    + Allow a citation or reference link to be parsed after a `!` (#8254).+    + Fix dropped `!` before nonexistent reference (#9038).++  * LaTeX writer:++    + Fix regression in escaping URLs (#9043).+    + Use `\cite` and `\bibitem` to link up citations, even with citeproc.+      (#9031). This will give us better accessibility; when tagging is+      enabled, the citation can be linked to the bibliography entry.+      This changes some of the details of the layout and the default+      template. We now make `CSLReferences` a special enumitem list+      that will contain `\bibitem`s. Internal links inside citations to+      ids beginning in `ref-` are creating using `\cite` instead of+      `\hyperref`.+    + Use `\phantomsection` and `\label` instead of `\hypertarget` (#9022).+    + Use `\hyperref` for LaTeX internal links, `\hyperlink` for+      beamer (since `\hyperref` doesn't seem to work) (#9022).+    + Backslash-escape `%` and `#` in URLs (#9014).++  * JATS writer:++    + Fix placement of ref-list when no title is specified for the+      reference section (#9017). (In this case we place it in `back`+      with an empty title.)++  * Man writer:++    + Avoid a `.PP` right after a section heading (#9020).+      This is at best a no-op (in groff man and mandoc) and at worst+      (in some formatters) may create extra whitespace.+    + We revert the fanciness introduced in #7506, which employs a+      custom font name `V` and a macro that makes this act like boldface+      in a terminal and monospace in other formats.  Unfortunately,+      this code uses a mechanism that is not portable (and does not+      work in mandoc) (#9020).+    + Instead of using `V` for inline code, we simply use `CR`.+      Note that `\f[CR]` is emitted instead of plain `\f[C]`,+      because there is no `C` font in man.  (This produces warnings+      in recent versions of groff, #9020.)+    + For code blocks, we now use the `.EX` and `.EE` macros,+      together with `.IP` for spacing and indentation.  This gives+      more standard code that can be better interpreted e.g. by mandoc+      (#9020).++  * Man template: don't emit `.hy`, regardless of setting of+    `hyphenate` variable (#9020).++  * LaTeX template: special redefinition of `\st` for CJK (#9019).+    soul's version raises on error on CJK text.++  * Use latest skylighting-format-blaze-html (#7248).+    This works around a longstanding iOS Safari bug that caused long+    lines to be displayed in a different font size in highlighted code.++  * Allow skylighting 0.14 (and require it in pandoc core).++  * Allow text 2.1.++## pandoc 3.1.6.2 (2023-08-22)++  * Org reader: allow example lines to end immediately after the colon+    (Brian Leung).++  * Docx reader:++    + Omit "Table NN" from caption (#9002).+    + Avoid spurious block quotes in list items (#8836).++  * JATS reader: Fix display of block elements (#8889, Julia Diaz).+    A number of block elements, like disp-quote, list, and disp-formula, were+    always treated as inlines if appearing inside paragraphs, even if their+    usage granted a separate block.++  * HTML reader: avoid duplicate id on header and div (#8991).++  * Typst writer:++    + Use `~` for nonbreaking space, and escape literal `~` (#9010).+    + Put the label in right place for Div, use `#block` (#8991).+      Previously we were putting the label at the beginning of+      the Div's contents, but according to the documentation such a+      label gets attached to the *preceding* element.  We now use an+      explicit `#block` and add the label at the end.++  * LaTeX writer:++    + Improve escaping of URIs in href, url (#8992).+    + Improve internal links and targets (#8744). We no longer+      wrap section headings in a `\hypertarget`. This is unnecessary+      (hyperref creates an anchor based on the label) and it interferes with+      tagging. In addition, we now use `\hyperref` rather than `\hyperlink`+      for internal links. Currently `\hypertarget` is still being used for+      link anchors not on headings. Thanks to @u-fischer.++  * HTML format templates (style.html): Fix typo in clause for svg+    (Jackson Schuster).++  * Use lastest texmath, typst-symbols, typst. Targets typst 0.7.+++## pandoc 3.1.6.1 (2023-08-11)++ * HTML reader: properly calculate RowHeadColumns (#8984). This fixes a+   bug in the calculation of the number of header columns in table row.+   It also changes the algorithm for determining the table body's+   RowHeadColumns based on the numbers of head columns in each row.+   Previously we used the max, and #8634 switched to the min, which+   led to bad results. Now we only set RowHeadColumns to a non-zero value+   if *all* rows have the same number of head columns.++  * OpenDocument writer:++    + Implement syntax highlighting for inline and block code (#6710).+    + Support highlighted text in ODT/OpenDocument writers for Span+      with class `mark` (#8960). The color can be adjusted by+      modifying the Highlighted style.++  * Typst writer: escape `//` so it doesn't get interpreted as a comment+    (#8966).++  * ChunkedHTML writer: Fix regression including MathJax script (#8967).+    The fix for #8620 caused the script to be included when the table of+    contents but not the body text of a page contains math.  But it broke the+    case where the table of contents doesn't contain math but the page does.+    This patch fixes the issue.++  * Text.Pandoc.SelfContained:++    + Retain attributes in SVG tag when referring to another+      SVG's content using `<use>` (#8969).+    + Allow units in width and height for SVG. Units are optional but allowed.+    + Don't coerce calculated SVG dimensions to Int.+    + fix calculation of SVG width and height. We were computing width and+      height from viewBox incorrectly (#8969).+    + Add clause for SVG to default CSS for HTML (#8969).+    + Ensure that width and height attributes don't get specified+      twice is both the img tag and the svg include them (#8965).+    + Omit unnecessary attributes xmlns, xmlns:xlink, and version on+      SVG element (#8965).+    + Use 20 character rather than 40 character hashes for generated IDs+      (#8965).++  * Use pandoc-types 1.23.1. This fixes a regression with toJSONFilter (#8976),+    which in 1.23.0.1 no longer worked on pure values of type `a -> [a]`.++  * Use ghc 9.6 for release builds (#8947).++  * Fix some links in FAQs (Diogo Almiro).+++## pandoc 3.1.6 (2023-07-20)++  * Fix CVE-2023-38745, a 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 emitting 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+    (#8788, Sam S. Almahri). The default is true if no value is specified,+    so this is fully backwards-compatible.++  * Support `--id-prefix` for markdown output (#8878)++  * Markdown reader:++    + Add strictness annotations to fix a memory leak (#8762).++  * Typst reader:++    + Use typst-hs 0.3.0.0, which is more robust, fixes many bugs, and+      targets typst 0.6.+    + Package loading is now supported, as long as the package has been+      cached or is local.+    + Rewrite Typst reader in a way that makes it easier to extend.+    + Filter out CR in raw.+    + Handle block content for link element.+    + Handle block-level content in text element.+    + Handle style, align, place in inline contexts too.+    + Improve info message for skipped elements.++  * Add typst reader tests (#8942).++  * MediaWiki reader:++    + Revise treatment of "link trail." Previously we only included ASCII+      letters. That is correct for English but not for, e.g., Spanish (see+      comment in #8525). A safer approach is to include all letters except+      those in the CJK unified ideograph ranges.++  * AsciiDoc writer:++    + Make modern AsciiDoc the target for `asciidoc` (#8936).+      The AsciiDoc community now regards the dialect parsed by `asciidoctor`+      as the official AsciiDoc syntax, so it should be the target of our+      `asciidoc` format. The `asciidoc` output format now behaves like+      `asciidoctor` used to. `asciidoctor` is a deprecated synonym. For+      the old `asciidoc` behavior (targeting the Python script),+      use `asciidoc_legacy`. The templates have been consolidated. Instead of+      separate `default.asciidoctor` and `default.asciidoc` templates, there+      is just `default.asciidoc`.+    + Text.Pandoc.Writers.AsciiDoc API changes:+      - `writeAsciiDoc` now behaves like `writeAsciiDoctor` used to.+      - `writeAsciiDoctor` is now a deprecated synonym for `writeAsciiDoc`.+      - New exported function `writeAsciiDocLegacy` behaves like+        `writeAsciDoc` used to.+    + Update line-through for asciidoc writer to custom inline style (#8933,+      Kevin Broch).++  * Typst writer:++    + Support `unlisted` class in headings (#8941).+    + Consolidate bibliography files into one `#bibliography` command (#8937).+    + Improve handling of autolinks (#8931).++  * Docx writer:++    + Make relative widths work in tables. This didn't work before because we+      were missing an attribute that tells Word to used fixed widths rather+      than computing optimal ones.++  * DokuWiki writer: fix lists with Div elements (#8920).+    The DokuWiki writer doesn't render Divs specially, so their presence in+    a list (e.g. because of custom-styles) need not prevent a regular+    DokuWiki list from being used. (Falling back to raw HTML in this case is+    pointless because no new information is given.)++  * LaTeX writer:++    + Fix babel name for `fa` (should be `persian`).+    + Prevent babel language from being imported twice (#8925).++  * Text.Pandoc.Class:++    + Add `toTextM` [API change]. This is like `Text.Pandoc.UTF8.toText`,+      except:++      - it takes a file path as first argument, in addition to+        bytestring contents+      - it raises an informative error with source position if+        the contents are not UTF8-encoded++    This replaces `utf8ToText` whenever we have the filename and are+    in a PandocMonad instance. This will lead to more informative error+    messages for UTF8-encoding, indicating the file path and byte offset+    where the error occurs (#8884).++  * Remove invalid term "Subject" from Turkish translations (#8921).++  * stack.yaml: add pkg-config to nix packages (#8927, pacien).++  * Allow aeson 2.2.++  * MANUAL: Add clarification on --section-divs. Closes #8882.+++## pandoc 3.1.4 (2023-06-24)++  * Fix a security vulnerability in MediaBag and T.P.Class.IO.writeMedia.+    This vulnerability, discovered by Entroy C, allows users to write+    arbitrary files to any location by feeding pandoc a specially crafted+    URL in an image element.  The vulnerability is serious for anyone+    using pandoc to process untrusted input.  The vulnerability does+    not affect pandoc when run with the `--sandbox` flag. [CVE-2023-35936]++  * Allow `epub-title-page` to be used in defaults files (#8908).++  * Issue `Extracting` info message (in `--verbose` mode) when using+    `--extract-media` or extracting media temporarily in PDF production.++  * HTML reader: Update TableBody RowHeadColumns caculation (#8634,+    Ruqi). This change sets RowHeadColumns to the minimum value of each row,+    which gives better results in cases where rows have different numbers+    of leading th tags.++  * Dokuwiki reader: retain image query parameters as attributes (#8887, echo0).++  * Textile reader: Add support for link references (#8706, Stephen Altamirano).+    Textile supports what it calls "link alias", which are analogous to+    Markdown's reference-style links.++  * LaTeX reader: support alt text on images (#8743, Albert Krewinkel).++  * Commonmark reader: Make `implicit_figures` work again.+    Support for this (introduced in #6350) disappeared when we made an+    architectural change.++  * JATS reader:++    + Add footer and multiple body parsing to table reader (#8765, Noah Malmed).+    + Parse references title from ref-list (#8365).++  * JATS writer:++     + Make `--number-sections` work.+     + Include title in ref-list (#8364). Previously the reference title ended+       up in a separate section at the back of the body instead of in the ref-list+       in the back matter.++  * Mediawiki writer: allow highlighting to work for F# language+    (Adelar da Silva Queiróz).++  * LaTeX writer: Fix escaping of `&` in `\href` and `\url` (#8903).++  * Docx writer:++    + Fix localization of "Abstract" title (#8702).+    + Allow `abstract-title` to be specified in docx metadata (#8794).++  * ChunkedHTML writer: Make math work in top-level page (#8915).++  * Text.Pandoc.Logging: add new log message type `ScriptingWarning`+    [API change] (Albert Krewinkel).++  * Lua: report warnings from Lua scripts (Albert Krewinkel).+    Lua's warning system is plugged into pandoc's reporting architecture.+    Warnings that are raised with the Lua `warn` function are now reported+    together with other messages.++  * Use crypton-connection instead of connection (#8896, Felix Yan).+    Follows the change introduced in tls 1.7.0.++  * Bump versions for skylighting-core, skylighting.++  * Include lua/module/sample.svg in cabal extra-source-files (Felix Yan).++  * Add Nynorsk (New Norwegian) translations (Per Christian Gaustad).++  * Add tests for `fillMediaBag`/`extractMedia`.++  * INSTALL.md:++    + Mention alternatives to LaTeX to generate PDF (Norwid Behrnd).+    + Update Linux install links (harabat).++  * pandoc-extras.md: add to "Academic publishing workflows" (#8696,+    Vladimir Alexiev).++## pandoc 3.1.3 (2023-06-07)++  * New output format: `typst`.++  * New module: Text.Pandoc.Readers.Typst [API change].++  * DocBook reader:++    + Support more emphasis roles (Albert Krewinkel).+      The role "bf" is taken to indicate "bold face", i.e.,+      "strongly emphasized" text, while "underline" leads to+      underlined text.++  * JATS reader:++    + Improve title and label parsing in the JATS reader (#8718,+      Noah Malmed.)+    + Add rowspan, colspan and alignment to cells in jats table+      reader (#8408, Noah Malmed)++  * Org reader (Albert Krewinkel):++    + Require abstract environment to use lowercase.+    + Treat `#+NAME` as synonym for `#+LABEL` (#8578).++  * ODT reader:++    + Allow lists in table cells (#8892).+    + Allow frames inside spans (#8886).++  * RST reader:++    + Fix sorting on anonymous keys (#8877). This fixes a link+      resolution bug bug affecting RST documents with anonymous links.++  * HTML reader:++    + Fix iframe with data URI of an image (#8856).+      In this case we don't want to try to parse the data at the URL.+      Instead, create an image inside a div.++  * RTF reader:++    + Fix bug in table parsing (#8767). In certain cases, text before a+      table was being incorporated into the table itself.++  * Docx reader:++    + Introduce support for Intense Quote (Stephan Meijer).++  * Markdown reader:++    + Disallow escaping of `~` and `"` in `markdown_strict` (#8777,+      Albert Krewinkel). This matches the behavior of the legacy+      `Markdown.pl` as well as what is described in the manual.++  * LaTeX reader: ignore args to column type in `\multicolumn` (#8789).++  * HTML writer:++    + Use first paragraph in task item as checkbox label (#8729, Albert+      Krewinkel).++  * Ms writer:++    + Coerce titles to inlines (#8835). Block-level formatting is not+      allowed inside `.TL`.++  * LaTeX writer:++    + Fix width for multicolumn simple table (#8831).++  * Jira writer:++    + Use first code block class as highlighting language (#8814, Albert+      Krewinkel). The writer no longer searches the list of+      classes for a known programming language but always uses+      the first class in that list as the language identifier.++  * OpenDocument writer:++    + Handle row header column cells as header cells (#8764, Michael Stahl).+    + Fix invalid `text:p` inside `text:p` from meta (#8256).++  * ODT writer:++    + Don't add settings.xml (Michael Stahl). This will cause defaults+      to be used, which is what we want.+    + Don't add unnecessary Configurations2 directory (Michael Stahl).+    + Don't add thumbnail (Michael Stahl).+    + Put `manifest.version` on directory file-entry (Michael Stahl).+      See ODF 1.3 part 2, 4.16.14.1.+    + Stop validator complaints by producing ODF 1.3 (Michael Stahl).++  * MediaWiki writer:++    + Remove links from inside links in mediawiki writer (#8739,+      Wout Gevaert).++  * Typst writer:++     + Omit bibliography if `citations` not enabled (#8763).+      With this change, the typst writer will omit the `#bibliography`+      command when `citations` is not enabled.  (If you want to use+      pandoc's own `--citeproc`, you should combine it with+      `-t typst-citations` to disable native typst citations.+    + Use `<..>` for labels, create internal links.+    + Use `#footnote` for notes (#8893).+    + Fix alignment issue in lists.  It's an aesthetic issue+      only; the first line had an extra space indent after the+      list marker.++  * Commonmark writer:++    + Use shortcut reference links: commonmark supports these.++  * EPUB template: add `lang` attribute to `<html>` (Gabriel Lewertoski).++  * Template styles.html: fix task-list styling in reveal.js+    (#8731, Albert Krewinkel).++  * LaTeX template: Fix `\babelfont` (#8728).++  * Text.Pandoc.Parsing:++    + Remove unnecessary 'spaces' in `parseFromString`.++  * Text.Pandoc.ImageSize: Drop BOM at start of SVG if present.+    Otherwise our code can fail to determine image size.++  * Lua subsystem:++    + Fix value of PANDOC_SCRIPT_FILE for custom readers & writers+      (#8781, Albert Krewinkel). The value did not hold the actual+      file path for scripts in the *custom* folder of the datadir.++  * Fix YAML in translation files for `cs` and `pl` (#8787).++  * Fix pdf output via typst (#8754).  One must now use `typst+    compile` rather than `typst`.++  * MANUAL.txt:++    + Added note that the user will need to create the user data+      dir (#8727).+    + Add `wikilinks` to non-default extensions (Ilona).+    + Update link to custom djot writer (Albert Krewinkel).+    + Better link to citation syntax.+    + Fix typo (sdhoward).+    + Note that `#` fancy list markers don't work with commonmark (#8772,+      William Lupton).+    + Add commonmark `fenced_div` note (#8773, William Lupton).+    + Move highlighting documentation, with minor adjustments+      (William Lupton).+    + Fix inaccurate statement about spaces and tabs in template+      syntax+      (Frank Seifferth).++  * Update documentation for org-mode (Christian Christiansen, #8716).++  * doc/lua-filter.md:++    + Fix typos (#8734, perro tuerto).+    + Fix anchor (Toni Dietze).+    + Use full field name in example (#8857, Matt Dodson).+    + Fix copy-paste error (#8798, thron7).++  * CONTRIBUTING.md: update info on ghc versions.++  * INSTALL.md:++    + Fix cabal install instructions (Albert Krewinkel).+    + Use more relevant link to NetBSD/pkgsrc entry (Charlotte Koch).+    + Fix Windows install instructions for winget (#8799).++  * Tests: Rename test/docx/block_quotes_parse_indent.native for+    consistency (Stephan Meijer).++  * Add `tls` constraint on cabal.project. This is needed to+    avoid problems caused by the transition to `crypton`.++  * Require texmath 0.12.8.+++## pandoc 3.1.2 (2023-03-26)++  * Add a Lua REPL (Albert Krewinkel). This can be started+    with `pandoc lua -i`.  It is also possible to instruct a filter to+    open the REPL at a certain point, for debugging (see `pandoc.cli.repl`).++  * Support `typst` as a `--pdf-engine`.++  * Add typst writer (#8713).  New module Text.Pandoc.Writers.Typst,+    exporting `writeTypst` [API change].++  * Org reader:++    + Allow zero width space as an escape character (#8716,+      Christian Christiansen). Allow the character U+200B to be used as+      an escape character as described in the Org-mode documentation+      (<https://orgmode.org/manual/Escape-Character.html>).++  * DocBook reader:++    + Handle "book" for xref references (#8712, Andres Freund)+      This also adds a test xref to book and part.+    + Handle `<part>` (#8712).++  * HTML reader:++    + Fix behavior with `-native_spans-raw_html` (#8711). Previously with+      this configuration, `<span>`s were not treated as inline elements at all.++  * HTML writer:++    + Avoid duplicate classes (#8705).+    + Use img element instead of embed for `.svg.gz` and `.png.gz` etc. (#8699).+    + HTML writer footnotes changes (#8695): when `--reference-location=section`+      or `=block`, use an `aside` element for the notes rather than a `section`.+      When `--reference-location=section`, include the `aside` element inside+      the section element, rather than outside. (In slide shows, this option+      causes footnotes on a slide to be displayed at the bottom of the slide.)++  * EPUB writer:++    + Use different structure for epub footnotes (#8676, see #8672, #5583).+      Many EPUB readers are thrown off by pandoc's current footnote+      output.  Both the ol and the fact that the footnote backlink is+      at the end of the note seem to pose problems.+      With this commit, we now create a list of aside (or div) elements,+      instead of an ordered list. Each element begins with a note number+      that is linked back to the note reference.  (So, the backlink occurs+      at the beginning rather than the end.) Thanks to @Porges and @lewer.++  * Docx writer:++    + Include abstract title (#8702). Uses localized term for abstract.++  * Markdown writer:++    + Use implicit figures if there's a caption but no alt (#8689,+      Albert Krewinkel).++  * Jira reader (Albert Krewinkel):++    + Add panel title as nested div (#8681).+    + Require jira-wiki-markup 1.5.1 (#8680). This fixes a bug in the parser+      that caused text between two exclamation marks to be parsed as an+      image. The first `!` of image markup must now be followed by a+      non-space character; otherwise, the enclosed text is parsed as+      normal content.++  * Ms writer:++    + Fix handling of Figure (#8660).++  * ICML writer:++    + Fix images with data (#8675). The Contents element+      should be inside Properties.++  * LaTeX writer:++    + Add Chinese to Babel languages.+    + Fix background image in Beamer when there are figure environments (#8671,+      Martín Pozo).++  * LaTeX template:++    + Add `babelfonts` variable to default LaTeX template.+      This allows specifying certain fonts to be used with+      certain babel languages. Thanks to Frederik Elwert.+    + Fix highlight/underline with lualatex (#8707). We need the lua-ul package+      instead of soul, which doesn't work with lualatex.++  * Lua (Albert Krewinkel):++    + Add `pandoc.cli.repl` function+    + Fix `json.encode` for nested AST elements. Ensures that objects with+      nested AST elements can be encoded as JSON.+    + Auto-generate docs for pandoc modules.+    + Load text module as `pandoc.text`. This only affects the name in the+      Lua-internal documentation. It is still possible to load the modules+      via `require 'text'`, although this is deprecated.+    + Move docs from module `text` to `pandoc.text`+      The latter is easier to use and more consistent with the other modules.+    + Keep the Lua stack clean A metatable used during initialization was+      not properly removed from the stack. Likewise, accessing the+      CommonState from Lua previously led to the pollution of the+      Lua stack with a left-over value.+    * Add function `pandoc.format.from_path`.+    + Allow to get the JSON encoding of log messages.++  * Text.Pandoc.Format: Add new function `formatFromFilePaths` [API change]+    (#8710, Albert Krewinkel).++  * The old Text.Pandoc.App.FormatHeuristics module has been removed.++  * In `--version`, use Windows `%APPDATA%` variable to describe+    user data dir (#8686, Pablo Rodríguez).++  * Text.Pandoc.App.CommandLineOptions: don't lowercase arg to `--from`/`--read`+    (Albert Krewinkel). This prevented users to use custom writers with+    uppercase characters in their filenames. Format-normalization,+    including lower-casing of format identifiers, happens during+    format parsing.++  * Documentation:++    + Add `doc/nix.md`.+    + Add `doc/extras.md`. This was formally in the website repo.+    + `doc/lua-filters.md`: improve docs for `pandoc.zip`.++  * Factor out `make_macos_release.sh` from the release candidate workflow.+    Use cabal instead of stack to build the macos binary.++  * Modify linux/make_artifacts.sh so it will work on cirrus.++  * Switch to hslua-2.3++  * Depend on latest releases of texmath, doclayout.++## pandoc 3.1.1 (2023-03-05)++  * EPUB reader: Give additional information in error if the epub+    zip container can't be unpacked.++  * TSV reader: don't gobble tabs as whitespace (#8661).++  * Org reader: accept empty tables (#8659).++  * LaTeX reader: fix multiplication syntax for tabular (#8658).+    We recognized `*{6}{...}` but not `*6{...}` or `*6c`.++  * Docx reader: parse image alt texts in LibreOffice generated files.+    LibreOffice tags images slightly differently than Word; this change lets+    the parses take that difference into account when looking for an image+    description (alt text).++  * DocBook reader:++    + Fix `<xref>` references to tables in DocBook files+      (#8626, Pavol Otto).+    + Parse `figure` as a Figure element in the AST (#8668).++  * JATS reader: avoid generating duplicate figure captions (#8669).++  * RST reader: align with spec in syntax for role names (#8653).+    In particular, we now allow colons in row names.++  * Add note on converting from .doc format to FAQs (#8654).++  * Trap error in getAppUserDataDirectory (#8648).+    This can raise an error if pandoc is run in a non-user environment.++  * LaTeX writer: do not use longtable foot with Beamer (#8638, Albert+    Krewinkel). The table foot is made part of the table body, as+    otherwise it won't show up in the output. The root cause for+    this is that longtable cannot detect page breaks in Beamer.++  * LaTeX template: Add CJKsansfont and CJKmonofont for XeLaTeX+    (#8656, Yudong Jin). `CJKsansfont` and `CJKmonofont` will be+    set for xelatex only if `CJKmainfont` is also provided.++  * URL style in ConTeXt (#8612, Thomas Hodgson). Previously, a+    URL like this would be in monospace text:+    `\useURL[url1][https://example.com]`.  Now, it will match the+    main text unless the `linkstyle` variable is set, which+    controls the styling of all links.  Closes #8602.++  * Asciidoc writer: Properly escape `|` in table cells (#8665).++  * asciidoc{,tor} template: fix revision date when author is unset+    (#8637, arcnmx). Revision line syntax is only valid in+    combination with an author line, so the date attribute must be+    set explicitly when the author is missing++  * HTML writer: allow "track" element to be treated as block-level HTML+    (#8629).++  * Include needed polyfill when MathJaX is used (#8625).++  * JATS writer: include alt-text in `<graphic>`,+    `<inline-graphic>` elements (#8631, Albert Krewinkel).++  * Chunked HTML writer:  Retain metadata in processing sections+    for chunked HTML (#8620).  Previously we suppressed metadata+    in all but the top page, in order to prevent the title block+    from being printed on every page. This prevented use of+    custom variables set by metadata fields.  This commit moves+    to a better solution: a conditional in the default template+    restricts the title block to the top page.++  * Lua API:++    + Add new function `pandoc.system.cputime` (Albert+      Krewinkel).  The function returns the CPU time consumed by+      pandoc and can be used to benchmark Lua computations.+    + Add module `pandoc.json` to handle JSON encoding (#8605,+      Albert Krewinkel).++  * Use pandoc-lua-marshal 0.2.1 (Albert Krewinkel).+    All major AST elements now have `__tojson` metamethods that return the+    JSON representation of an element. This allows to JSON-encode these+    elements with libraries that respect the `__tojson` metamethod,+    including dkjson.++  * Use latest zip-archive.  This allows pandoc to open certain+    epubs that it could not open before.++  * Use commonmark-extensions 0.2.3.4. This fixes some bugs involving+    definition lists and inline formatting.++  * Use latest skylighting-format-context++  * MANUAL.txt:++    + Document chunk-template in defaults file.+    + Remove obsolete "raw content in a style" section.+    + Revise documentation for `--mathml` to reflect support in all major+      browsers (#8667).++  * docs/custom-readers.md: Update JSON parsing example. The example now+    uses the built-in `pandoc.json` library to parse the API output.++  * doc/press.md: Add article on CiTO in J Cheminform by @egonw.++  * doc/lua-filters.md: fix typo in `run_json_filter` (Morgan Willcock).+++## pandoc 3.1 (2023-02-09)++  * Fix regression with `--print-highlight-style` option (#8586).++  * Add new `--chunk-template` option (#8581), allowing more control+    over the filenames in chunked HTML output.++  * Text.Pandoc.App: Add `optChunkTemplate` constructor to Opt [API change].++  * Text.Pandoc.Options: add `writerChunkTemplate` constructor to+    `WriterOptions` [API change].++  * Text.Pandoc.Chunks: add Data, Typeable, Generic, ToJSON, FromJSON+    instances for `PathTemplate` [API change].++  * Text.Pandoc.Citeproc: Fix bug in `metaValueToReference` (#8611).+    This bug caused us to get some repeated content when converting+    MetaBlock to Inlines.++  * Textile reader:++    + Support footnote backlinks (#8585, Stephen Altamirano).+    + Don't allow brackets in URLs (#8582).++  * ODT reader: fix blockquote indent detection (#3437, Daniel Kessler).++  * LaTeX writer: include short figure/table caption if one is given+    (Albert Krewinkel). Short captions are used by LaTeX when generating+    the list of figures or list of tables. Adding a short caption will+    now overwrite the full caption in these lists.++  * Powerpoint writer: fix handling of simple figures (#8565,+    Albert Krewinkel). This ensures that simple figures are displayed+    in the same way as before the introduction of a dedicated `Figure`+    constructor in the AST.++  * Improve handling of `%` in bib(la)tex parsing (#8597, #8595).++  * Use released skylighting 0.13.2.1++  * INSTALL.md: direct people to cabal install pandoc-cli.++  * doc/lua-filters.md: document 'Figure' type and constructor (Albert+    Krewinkel). Fix typos (Martin Joerg).++  * Fix link in manual (#8583, Salim B).++## pandoc 3.0.1 (2023-01-25)++  * Fix use of extensions with custom readers (#8571).++  * Text.Pandoc.Writers.Shared: export `setupTranslations` [API change].+    Use this in HTML and OpenDocument writers, to ensure that+    translations are set up properly even when we don't go through+    `convertWithOpts`.++  * LaTeX reader: fix regression in macro resolution for environments (#8573).++  * Chunked HTML writer: Fix handling of images with absolute URLs (#8567).++  * HTML writer:++    + Don't omit newlines in task lists.+    + Don't disable checkboxes in task lists (#8562).++  * Ensure that automatically set variables `pandoc-version`, `outputfile`,+    `title-prefix`, `epub-cover-image`, `curdir`, `dzslides-core` can be+    overridden by `--variable` on the command line. Previously they would+    create lists in the template Context, which is not desirable.++  * Fix man page copying in `linux/make_artifacts.sh` (#8566).+    Previously we were copying the pandoc-server.1 pandoc page to pandoc-lua.1.++  * pandoc.cabal: remove pandoc.cabal, stack.cabal from extra-source-files+    (#8560). The problem is that if these are in extra-source-files, then they+    get put in the tarball, and then anyone trying to build the source+    from an unpacked tarball will run into the problem that cabal.project+    and stack.yaml refer to pandoc-server, pandoc-lua-engine, and+    pandoc-cli, which aren't in the tarball.++  * Require texmath 0.12.6 for better MathML output.++  * Fix typo in Lua filter documentation (Carlos Scheidegger).++  * Fix formatting of link in pandoc-server.md (James Scott-Brown).++  * Minor changelog fixups.++## pandoc 3.0 (2023-01-18)++  * Split pandoc-server, pandoc-cli, and pandoc-lua-engine+    into separate packages (#8309). Note that installing+    the `pandoc` package from Hackage will no longer give you the+    `pandoc` executable; for that you need to install `pandoc-cli`.++  * Pandoc now behaves like a Lua interpreter when called as+    `pandoc-lua` or when `pandoc lua` is used (#8311, Albert Krewinkel).+    The Lua API that is available in filters is automatically+    available to the interpreter. (See the `pandoc-lua` man page.)++  * Pandoc behaves like a server when called as `pandoc-server`+    or when `pandoc server` is used. (See the `pandoc-server` man page.)++  * A new command-line option `--list-tables`, causes tables to be+    formatted as list tables in RST (#4564, with Francesco Occhipinti).++  * New command line option: `--epub-title-page=true|false` allows+    the EPUB title page to be omitted (#6097).++  * `--reference-doc` can now accept a URL argument (#8535) and+    load a remote reference doc.++  * `--version` output no longer contains version info for dependent+    packages. Instead, it contains a "Features" line that indicates+    whether the binary was compiled with support for acting as a server,+    and for using Lua filters and Custom writers.++  * A new option `--split-level` replaces `--epub-chapter-level`+    and affects both EPUB and chunked HTML output.  `--epub-chapter-level`+    will still work but is deprecated.++  * Multiple input files with `--file-scope`: fix case where the links+    are URL-encoded, e.g. with `%20` (#8467).++  * Produce error if `--csl` is used more than once (#8195, Prat).++  * Remove deprecated `--atx-headers` option.++  * Remove deprecated option `--strip-empty-paragraphs`.++  * In `--verbose` mode add message when running citeproc (as with+    other filters).++  * Add new `mark` extension for highlighted text in Markdown,+    using `==` delimiters (#7743).++  * Add new extensions `wikilinks_title_after_pipe` and+    `wikilinks_title_before_pipe` for `commonmark` and `markdown`.+    (#2923, Albert Krewinkel). The former enables links of style+    `[[Name of page|Title]]` and the latter `[[Title|Name of+    page]]`. Titles are optional in both variants, so this works+    for both: `[[https://example.org]]`, `[[Name of page]]`. The+    writer is modified to render links with title `wikilink` as+    a wikilink if a respective extension is enabled. Pandoc will+    use `wikilinks_title_after_pipe` if both extensions are+    enabled.++  * Add prefixes to identifiers with `--file-scope` (#6384).+    This change only affects the case where `--file-scope` is used+    and more than one file is specified on the command line.+    In this case, identifiers will be prefixed with a string+    derived from the file path, to disambiguate them. For example,+    an identifier `foo` in `contents/file1.txt` will become+    `contents__file1.txt__foo`.  Links will be adjusted accordingly:+    if `file2.txt` links to `file1.txt#foo`, then the link will+    be changed to point to `#file1.txt__foo`.  Similarly, a link+    to `file1.txt` will point to `#file1.txt`.  A Div with an+    identifier derived from the file path will be added around+    each file's content, so that links to files will still work.++  * New output format: `chunkedhtml`. This creates a zip file+    containing multiple HTML files, one for each section,+    linked with "next," "previous," "up," and "top" links.+    (If `-o` is used with an argument without an extension,+    it is treated as a directory and the zip file is automatically+    extracted there, unless it already exists.) The top page will+    contain a table of contents if `--toc` is used.  A+    `sitemap.json` file is also included. The option+    `--split-level` determines the level at which sections are+    to be split.++  * Support complex figures (Albert Krewinkel, Aner Lucero).+    There is now a dedicate Figure block constructor for+    figures.  The old hack of representing a figure as+    `Para [Image attr [..alt..] (source, "fig:title")]`+    has been dropped.  Here is a summary of figure support+    in different formats:++    + Markdown reader: paragraphs containing just an image are treated as+      figures if the `implicit_figures` extension is enabled. The identifier+      is used as the figure's identifier and the image description is also+      used as figure caption; all other attributes are treated as belonging+      to the image.+    + Markdown writer: figures are output as implicit figures if possible,+      via HTML if the `raw_html` extension is enabled, and as Div elements+      otherwise.+    + HTML reader: `<figure>` elements are parsed as figures, with the+      caption taken from the respective `<figcaption>` elements.+    + HTML writer: the alt text is no longer constructed from the caption,+      as was the case with implicit figures. This reduces duplication, but+      comes at the risk of images that are missing alt texts. Authors should+      take care to provide alt texts for all images. Some readers, most+      notably the Markdown reader with the `implicit_figures` extension,+      add a caption that's identical to the image description. The writer+      checks for this and adds an `aria-hidden` attribute to the+      `<figcaption>` element in that case.+    + JATS reader: The `<fig>` and `<caption>` elements are parsed into+      figure elements, even if the contents is more complex.+    + JATS writer: The `<fig>` and `<caption>` elements are used write+      figures.+    + LaTeX reader: support for figures with non-image contents and for+      subfigures.+    + LaTeX writer: complex figures, e.g. with non-image contents and+      subfigures, are supported. The `subfigure` template variable is set if+      the document contains subfigures, triggering the conditional loading+      of the *subcaption* package. Contants of figures that contain tables+      are become unwrapped, as longtable environments are not allowed within+      figures.+    + DokuWiki, Haddock, Jira, Man, MediaWiki, Ms, Muse, PPTX, RTF, TEI,+      ZimWiki writers: Figures are rendered like Div elements.+    + Asciidoc writer: The figure contents is unwrapped; each image in the+      the figure becomes a separate figure.+    + Classic custom writers: Figures are passed to the global function+      `Figure(caption, contents, attr)`, where `caption` and `contents` are+      strings and `attr` is a table of key-value pairs.+    + ConTeXt writer: Figures are wrapped in a "placefigure" environment+      with `\startplacefigure`/`\endplacefigure`, adding the features+      caption and listing title as properties. Subfigures are place in a+      single row with the `\startfloatcombination` environment.+    + DocBook writer: Uses `mediaobject` elements, unless the figure contains+      subfigures or tables, in which case the figure content is unwrapped.+    - Docx writer: figures with multiple content blocks are rendered as+      tables with style `FigureTable`; like before, single-image figures are+      still output as paragraphs with style `Figure` or `Captioned Figure`,+      depending on whether a caption is attached.+    + DokuWiki writer: Caption and "alt-text" are no longer combined. The+      alt text of a figure will now be lost in the conversion.+    + FB2 writer: The figure caption is added as alt text to the images in+      the figure; pre-existing alt texts are kept.+    + ICML writer: Only single-image figures are supported. The contents of+      figures with additional elements gets unwrapped.+    + OpenDocument writer: A separate paragraph is generated for each block+      element in a figure, each with style `FigureWithCaption`. Behavior for+      single-image figures therefore remains unchanged.+    + Org writer: Only the first element in a figure is given a caption;+      additional block elements in the figure are appended without any+      caption being added.+    + RST writer: Single-image figures are supported as before; the contents+      of more complex images become nested in a container of type `float`.+    + Texinfo writer: Figures are rendered as float with type `figure`.+    + Textile writer: Figures are rendered with the help of HTML elements.+    + XWiki: Figures are placed in a group.++  * Changes in custom readers/writers:++    + It is now possible to have a custom reader and a custom writer for+      a format together in the same file.  The file may also define+      a custom template for the writer.+    + Pandoc now checks the folder `custom` in the user's data directory+      for a matching script if it can't find one in the local directory.+      Previously, the `readers` and `writers` data directories were+      searched for custom readers and writers, respectively. Scripts in+      those directories must be moved to the `custom` folder.+    + Custom readers used to implement a fallback behavior that allowed to+      consume just a string value as input to the `Reader` function. This+      has been removed, the first argument is now always a list of+      sources. Use `tostring` on that argument to get a string.++  * New module Text.Pandoc.Writers.ChunkedHTML,+    exporting `writeChunkedHtml` [API change].++  * We now set the `pandoc-version` variable centrally rather+    than in the writers.  One effect is the man writer now emits+    a comment with the pandoc version.++  * pandoc-server:++    + Add simple CORS support to pandoc-server (#8427).+    + Print message to stderr when starting the server.++  * Docx reader:++    + Mark unnumbered headings with class `unnumbered` (#8148,+      Albert Krewinkel). This change ensures good conversion+      results when converting with `--number-sections`.+    + Support parsing of highlighted text.+    + Fix handling of `oMathPara` in `w:p` with other content (#8483).++  * ODT reader:++    + Fix relative links. ODT adds a `../` to relative links+      (see #3524); this needs to be removed when converting from ODT.+    + Handle "section" elements (#8409).+    + Rename Text.Pandoc.Readers.Odt -> Text.Pandoc.Readers.ODT,+      for consistency with Writers.ODT. Rename `readOdt` -> `readODT`.+      [API change]++  * DocBook reader:++    + Support href on link even in a fragment (#8437).+      (We now just look for an `href` attribute without+      worrying about the namespace.)+    + Parse title from imageobject/objectinfo (#8437).++  * JATS reader:++    + Handle uri element in references (#8270).++  * Ipynb reader:++    + Add cell id to attachment filename when storing in MediaBag (#8415).+      Otherwise attachments with the same name can overwrite each other.++  * LaTeX reader:++    + Skip parenthenized args of toprule, midrule, etc (#8242).+    + Handle `##` macro arguments properly (#8243).+    + Remove unused function `toksToString` in Parsing module.+    + Support more `soul` commands, including `\hl`.+    + Add `unnumbered` class for `\part*` (#8447)+    + Fix `TEXINPUTS` handling (#8392). If `TEXINPUTS` ends with `:`,+      then the system default `TEXINPUTS` is added.  We handle this by+      just adding the working directory in this case.+    + Parse short table caption (see jgm/pandoc-types#103).+      This is not too useful yet, because writers don't do anything with+      the short caption.++  * MediaWiki reader:++    + Parse table cell with attributess, to support rowspan, colspan (#8231,+      Ruqi).+    + Refine "blending" rules for MediaWiki links (#8525, Ruqi).+      The rules for "blending" characters outside a link into the link are+      described here: https://en.wikipedia.org/wiki/Help:Wikitext#Blend_link+      These pose a problem for CJK languages, which generally don't have+      spaces after links. However, it turns out that the blending behavior, as+      implemented on Wikipedia, is (contrary to the documentation) only for+      ASCII letters. This commit implements that restriction, which fixes+      the problem for CJK.++  * HTML reader:++    + Fix regression for `<tt>` (#8330). It was no longer being parsed as+      Code (Justin Wood).++  * RST reader:++    + Support `mark` role for round-trip.++  * Textile reader:++    + Support linked images (#8541).+    + Fix strong emph ending with link (#8540).+    + Adding a Parser to look for ordered list start attribute numbers+      if any (#2465, vkraven).+    + Handle empty paragraphs (#8487). Also, if attributes are added+      explicitly to a paragraph, put it in a Div with the attributes.++  * Markdown reader:++    + Allow fenced code block "bare" language to be combined+      with attributes (#8174, Siphalor), e.g.+      ````+      ```haskell {.class #id}+      ```+      ````+    + Allow table caption labels to start with lowercase `t` (#8259).+    + Grid tables: allow specifying a table foot by enclosing it with+      part separator lines, i.e., row separator lines consisting only+      of `+` and `=` characters (#8257, Albert Krewinkel). E.g.:+      ```+      +------+-------++      | Item | Price |+      +======+=======++      | Eggs | 5£    |+      +------+-------++      | Spam | 3£    |+      +======+=======++      | Sum  | 8£    |+      +======+=======++      ```+    + Fix `implicit_header_references` with duplicate headings (#8300).+      Documentation says that when more than one heading has the same text,+      an implicit reference `[Heading text][]` refers to the first one.+      Previously pandoc linked to the last one instead. This patch+      makes pandoc conform to the documented behavior.+    + Parse highlighted text inside `==..==` if `mark` extension enabled.++  * Org reader:++    + Allow org-ref v2 citations with `&` prefix (#8302).+    + Make `#+pandoc-emphasis-pre` work as expected (#8360, Amir Dekel).++  * BibTeX reader:++    + Fix handling of `%` in `url` field (#7678).+      `%` does not function as a comment character inside `url`+      (where URL-encoding is common).+    + Allow `url` field in `bibtex` as well as `biblatex` (#8287).+      This field is not officially supported for BibTeX, but many styles+      can handle it (<https://www.bibtex.com/f/url-field/>),+      and others will ignore it.+    + Support `software` type in biblatex <-> CSL conversions (#8504).+    + Make sure `version` field comes through in biblatex (#8504).++  * BibTeX writer:++    + Pass through `url` even for `bibtex` (#8287).++  * Org writer:++    + Pass through unknown languages in code blocks (#8278), instead+      of producing `begin_example`.+    + Use span attributes `tag-name` in headers as tags (#8513, Albert+      Krewinkel). This enables round-tripping of tags in Org headings.++  * EndNote reader:++    + Better error when parsing EndNote references fails.++  * DocBook writer:++    + Rename Text.Pandoc.Writers.Docbook -> Text.Pandoc.Writers.DocBook.+      Rename `writeDocbook` -> `writeDocBook`, for consistency with+      the DocBook reader's naming. [API change]+    + Fix position of textobject (#8437). It is a child of+      `inlinemediaobject`, not `imageobject`.+    + Add regression tests for #8437.+    + Render image alt text using textobject element (#8437).+    + Don't indent contents of title element.+    + Store "unnumbered" class in DocBook role attribute (#1402, lifeunleaded).++  * ConTeXt writer (Albert Krewinkel):++    + Support syntax highlighting for code.+    + Always use `\type` for inline code.+      Inline codes that contained curly braces where previously rendered+      with `\mono`; this led to unexpected results when the presentation+      of `\type` was customized, as those changes would not have+      been applied to code rendered with `\mono`.+    + Add support for unlisted, unnumbered headings (#8486).+    + Support `tagging` extension (Albert Krewinkel). Paragraphs+      are enclosed by `\bpar` and `\epar` commands, and `highlight` commands+      are used for emphasis. This results in much better tagging in PDF output.++  * LaTeX writer:++    + Do not repeat caption on headless tables (Albert Krewinkel).+      The caption of headless tables was repeated on each page that+      contained part of the table. It is now made part of the+      "first head", i.e. the table head that is printed only once.+    + Add separator line between table's body and its foot+      (Albert Krewinkel).+    + Ignore languages with no babel equivalent, instead of generating an+      invalid command in the preamble (#8325).+    + Use `\includesvg` for SVGs and include the `svg` package (#8334).+    + Use `soul` instead of `ulem` for strikeout, underline (#8411).+      This handles things like hyphenation, line breaks, and nonbreaking+      spaces better.+    + Use `\toprule\noalign{}` instead of `\toprule()` in tables,+      and similarly for `\midrule` and `\bottomrule` (#8223).+      This facilitates redefining `\toprule`, `\midrule`, and `\bottomrule`+      without needing to gobble the ()s. (Those who redefine these macros+      on the assumption that they will be followed by `()` may need to+      change their definitions.)+    + Support highlighted text for Span with class `mark`.++  * JATS writer:++    + Use `<break/>` for LineBreak in the limited contexts that accept it+      (#8344).+    + Officially deprecate `writeJATS` in favor of `writeJatsArchiving`.++  * RTF writer:++    + Add space after unicode escape commands (#8264).  This fixes+      a bug that caused characters to disappear after unicode escapes.++  * RST writer:++    + Render tables as list tables when the `--list-tables` option is+      specified (`writerListTables`) (#4564, Francesco Occhipinti).+    + Improve inline escaping rules (#8380).+    + Use special `mark` role for Span with class `mark`.++  * Commonmark writer:++    + Ensure that we don't have blank lines in raw HTML (#8307).++  * HTML writer:++    + Only add role attribute in HTML5 (#8241). It is not valid in HTML4.+    + Avoid aria-hidden in code blocks for HTML4 (#8241).+    + Only treat `. . .` as a slide pause in slides, and not in regular+      HTML output (#8281).+    + Properly merge classes for headings of level > 6 (#8363).+    + Prevent `<a>` inside `<a>` (#7585). If a link text contains a link,+      we replace it with a span.+    + Replace deprecated aria roles for bibliography entries (#8354).+      `doc-biblioentry` -> `listitem`, `doc-bibliography` -> `list`.+    + Remove obsolete stuff about mathml-script.+      This was a shim we used to include for mathml support.+      We don't do anything with this any more, so this is dead code.+    + Include math links if there are raw commands or environments that+      can be interpreted as math e.g. by MathJax (#8469).+    + Add prooftree to list of math environments (#8462). This will cause+      raw LaTeX prooftree environments to be rendered appropriately when+      `--mathjax` is used.++  * HTML, Markdown writers: filter out empty class attributes (#8251).+    These should not be generated by any pandoc readers, but they+    might be produced programmatically.    * Markdown writer: 
data/bash_completion.tpl view
@@ -34,7 +34,7 @@              return 0              ;;          --pdf-engine)-             COMPREPLY=( $(compgen -W "pdflatex lualatex xelatex latexmk tectonic wkhtmltopdf weasyprint prince context pdfroff" -- ${cur}) )+             COMPREPLY=( $(compgen -W "pdflatex lualatex xelatex latexmk tectonic wkhtmltopdf weasyprint prince context pdfroff groff" -- ${cur}) )              return 0              ;;          --print-default-data-file)
data/default.csl view
@@ -1,679 +1,3933 @@ <?xml version="1.0" encoding="utf-8"?>-<style xmlns="http://purl.org/net/xbiblio/csl" class="in-text" version="1.0" demote-non-dropping-particle="display-and-sort" page-range-format="chicago">-  <info>-    <title>Chicago Manual of Style 17th edition (author-date)</title>-    <id>http://www.zotero.org/styles/chicago-author-date</id>-    <link href="http://www.zotero.org/styles/chicago-author-date" rel="self"/>-    <link href="http://www.chicagomanualofstyle.org/tools_citationguide.html" rel="documentation"/>-    <author>-      <name>Julian Onions</name>-      <email>julian.onions@gmail.com</email>-    </author>-    <contributor>-      <name>Sebastian Karcher</name>-    </contributor>-    <contributor>-      <name>Richard Karnesky</name>-      <email>karnesky+zotero@gmail.com</email>-      <uri>http://arc.nucapt.northwestern.edu/Richard_Karnesky</uri>-    </contributor>-    <contributor>-      <name>Andrew Dunning</name>-      <email>andrew.dunning@utoronto.ca</email>-      <uri>https://orcid.org/0000-0003-0464-5036</uri>-    </contributor>-    <contributor>-      <name>Matthew Roth</name>-      <email>matthew.g.roth@yale.edu</email>-      <uri> https://orcid.org/0000-0001-7902-6331</uri>-    </contributor>-    <contributor>-      <name>Brenton M. Wiernik</name>-    </contributor>-    <category citation-format="author-date"/>-    <category field="generic-base"/>-    <summary>The author-date variant of the Chicago style</summary>-    <updated>2018-01-24T12:00:00+00:00</updated>-    <rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>-  </info>-  <locale xml:lang="en">-    <terms>-      <term name="editor" form="verb-short">ed.</term>-      <term name="container-author" form="verb">by</term>-      <term name="translator" form="verb-short">trans.</term>-      <term name="editortranslator" form="verb">edited and translated by</term>-      <term name="translator" form="short">trans.</term>-    </terms>-  </locale>-  <locale xml:lang="pt-PT">-    <terms>-      <term name="accessed">acedido a</term>-    </terms>-  </locale>-  <locale xml:lang="pt">-    <terms>-      <term name="editor" form="verb">editado por</term>-      <term name="editor" form="verb-short">ed.</term>-      <term name="container-author" form="verb">por</term>-      <term name="translator" form="verb-short">traduzido por</term>-      <term name="translator" form="short">trad.</term>-      <term name="editortranslator" form="verb">editado e traduzido por</term>-      <term name="and">e</term>-      <term name="no date" form="long">s.d</term>-      <term name="no date" form="short">s.d.</term>-      <term name="in">em</term>-      <term name="at">em</term>-      <term name="by">por</term>-    </terms>-  </locale>-  <macro name="secondary-contributors">-    <choose>-      <if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="none">-        <group delimiter=". ">-          <names variable="editor translator" delimiter=". ">-            <label form="verb" text-case="capitalize-first" suffix=" "/>-            <name and="text" delimiter=", "/>-          </names>-          <names variable="director" delimiter=". ">-            <label form="verb" text-case="capitalize-first" suffix=" "/>-            <name and="text" delimiter=", "/>-          </names>-        </group>-      </if>-    </choose>-  </macro>-  <macro name="container-contributors">-    <choose>-      <if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="any">-        <group prefix=", " delimiter=", ">-          <names variable="container-author" delimiter=", ">-            <label form="verb" suffix=" "/>-            <name and="text" delimiter=", "/>-          </names>-          <names variable="editor translator" delimiter=", ">-            <label form="verb" suffix=" "/>-            <name and="text" delimiter=", "/>-          </names>-        </group>-      </if>-    </choose>-  </macro>-  <macro name="editor">-    <names variable="editor">-      <name name-as-sort-order="first" and="text" sort-separator=", " delimiter=", " delimiter-precedes-last="always"/>-      <label form="short" prefix=", "/>-    </names>-  </macro>-  <macro name="translator">-    <names variable="translator">-      <name name-as-sort-order="first" and="text" sort-separator=", " delimiter=", " delimiter-precedes-last="always"/>-      <label form="short" prefix=", "/>-    </names>-  </macro>-  <macro name="recipient">-    <choose>-      <if type="personal_communication">-        <choose>-          <if variable="genre">-            <text variable="genre" text-case="capitalize-first"/>-          </if>-          <else>-            <text term="letter" text-case="capitalize-first"/>-          </else>-        </choose>-      </if>-    </choose>-    <names variable="recipient" delimiter=", ">-      <label form="verb" prefix=" " text-case="lowercase" suffix=" "/>-      <name and="text" delimiter=", "/>-    </names>-  </macro>-  <macro name="substitute-title">-    <choose>-      <if type="article-magazine article-newspaper review review-book" match="any">-        <text macro="container-title"/>-      </if>-    </choose>-  </macro>-  <macro name="contributors">-    <group delimiter=". ">-      <names variable="author">-        <name and="text" name-as-sort-order="first" sort-separator=", " delimiter=", " delimiter-precedes-last="always"/>-        <label form="short" prefix=", "/>-        <substitute>-          <names variable="editor"/>-          <names variable="translator"/>-          <names variable="director"/>-          <text macro="substitute-title"/>-          <text macro="title"/>-        </substitute>-      </names>-      <text macro="recipient"/>-    </group>-  </macro>-  <macro name="contributors-short">-    <names variable="author">-      <name form="short" and="text" delimiter=", " initialize-with=". "/>-      <substitute>-        <names variable="editor"/>-        <names variable="translator"/>-        <names variable="director"/>-        <text macro="substitute-title"/>-        <text macro="title"/>-      </substitute>-    </names>-  </macro>-  <macro name="interviewer">-    <names variable="interviewer" delimiter=", ">-      <label form="verb" prefix=" " text-case="capitalize-first" suffix=" "/>-      <name and="text" delimiter=", "/>-    </names>-  </macro>-  <macro name="archive">-    <group delimiter=". ">-      <text variable="archive_location" text-case="capitalize-first"/>-      <text variable="archive"/>-      <text variable="archive-place"/>-    </group>-  </macro>-  <macro name="access">-    <group delimiter=". ">-      <choose>-        <if type="graphic report" match="any">-          <text macro="archive"/>-        </if>-        <else-if type="article-journal bill book chapter legal_case legislation motion_picture paper-conference" match="none">-          <text macro="archive"/>-        </else-if>-      </choose>-      <choose>-        <if type="webpage post-weblog" match="any">-          <date variable="issued" form="text"/>-        </if>-      </choose>-      <choose>-        <if variable="issued" match="none">-          <group delimiter=" ">-            <text term="accessed" text-case="capitalize-first"/>-            <date variable="accessed" form="text"/>-          </group>-        </if>-      </choose>-      <choose>-        <if type="legal_case" match="none">-          <choose>-            <if variable="DOI">-              <text variable="DOI" prefix="https://doi.org/"/>-            </if>-            <else>-              <text variable="URL"/>-            </else>-          </choose>-        </if>-      </choose>-    </group>-  </macro>-  <macro name="title">-    <choose>-      <if variable="title" match="none">-        <choose>-          <if type="personal_communication speech thesis" match="none">-            <text variable="genre" text-case="capitalize-first"/>-          </if>-        </choose>-      </if>-      <else-if type="bill book graphic legislation motion_picture song" match="any">-        <text variable="title" text-case="title" font-style="italic"/>-        <group prefix=" (" suffix=")" delimiter=" ">-          <text term="version"/>-          <text variable="version"/>-        </group>-      </else-if>-      <else-if variable="reviewed-author">-        <choose>-          <if variable="reviewed-title">-            <group delimiter=". ">-              <text variable="title" text-case="title" quotes="true"/>-              <group delimiter=", ">-                <text variable="reviewed-title" text-case="title" font-style="italic" prefix="Review of "/>-                <names variable="reviewed-author">-                  <label form="verb-short" text-case="lowercase" suffix=" "/>-                  <name and="text" delimiter=", "/>-                </names>-              </group>-            </group>-          </if>-          <else>-            <group delimiter=", ">-              <text variable="title" text-case="title" font-style="italic" prefix="Review of "/>-              <names variable="reviewed-author">-                <label form="verb-short" text-case="lowercase" suffix=" "/>-                <name and="text" delimiter=", "/>-              </names>-            </group>-          </else>-        </choose>-      </else-if>-      <else-if type="legal_case interview patent" match="any">-        <text variable="title"/>-      </else-if>-      <else>-        <text variable="title" text-case="title" quotes="true"/>-      </else>-    </choose>-  </macro>-  <macro name="edition">-    <choose>-      <if type="bill book graphic legal_case legislation motion_picture report song" match="any">-        <choose>-          <if is-numeric="edition">-            <group delimiter=" " prefix=". ">-              <number variable="edition" form="ordinal"/>-              <text term="edition" form="short" strip-periods="true"/>-            </group>-          </if>-          <else>-            <text variable="edition" text-case="capitalize-first" prefix=". "/>-          </else>-        </choose>-      </if>-      <else-if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="any">-        <choose>-          <if is-numeric="edition">-            <group delimiter=" " prefix=", ">-              <number variable="edition" form="ordinal"/>-              <text term="edition" form="short"/>-            </group>-          </if>-          <else>-            <text variable="edition" prefix=", "/>-          </else>-        </choose>-      </else-if>-    </choose>-  </macro>-  <macro name="locators">-    <choose>-      <if type="article-journal">-        <choose>-          <if variable="volume">-            <text variable="volume" prefix=" "/>-            <group prefix=" (" suffix=")">-              <choose>-                <if variable="issue">-                  <text variable="issue"/>-                </if>-                <else>-                  <date variable="issued">-                    <date-part name="month"/>-                  </date>-                </else>-              </choose>-            </group>-          </if>-          <else-if variable="issue">-            <group delimiter=" " prefix=", ">-              <text term="issue" form="short"/>-              <text variable="issue"/>-              <date variable="issued" prefix="(" suffix=")">-                <date-part name="month"/>-              </date>-            </group>-          </else-if>-          <else>-            <date variable="issued" prefix=", ">-              <date-part name="month"/>-            </date>-          </else>-        </choose>-      </if>-      <else-if type="legal_case">-        <text variable="volume" prefix=", "/>-        <text variable="container-title" prefix=" "/>-        <text variable="page" prefix=" "/>-      </else-if>-      <else-if type="bill book graphic legal_case legislation motion_picture report song" match="any">-        <group prefix=". " delimiter=". ">-          <group>-            <text term="volume" form="short" text-case="capitalize-first" suffix=" "/>-            <number variable="volume" form="numeric"/>-          </group>-          <group>-            <number variable="number-of-volumes" form="numeric"/>-            <text term="volume" form="short" prefix=" " plural="true"/>-          </group>-        </group>-      </else-if>-      <else-if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="any">-        <choose>-          <if variable="page" match="none">-            <group prefix=". ">-              <text term="volume" form="short" text-case="capitalize-first" suffix=" "/>-              <number variable="volume" form="numeric"/>-            </group>-          </if>-        </choose>-      </else-if>-    </choose>-  </macro>-  <macro name="locators-chapter">-    <choose>-      <if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="any">-        <choose>-          <if variable="page">-            <group prefix=", ">-              <text variable="volume" suffix=":"/>-              <text variable="page"/>-            </group>-          </if>-        </choose>-      </if>-    </choose>-  </macro>-  <macro name="locators-article">-    <choose>-      <if type="article-newspaper">-        <group prefix=", " delimiter=", ">-          <group delimiter=" ">-            <text variable="edition"/>-            <text term="edition"/>-          </group>-          <group>-            <text term="section" form="short" suffix=" "/>-            <text variable="section"/>-          </group>-        </group>-      </if>-      <else-if type="article-journal">-        <choose>-          <if variable="volume issue" match="any">-            <text variable="page" prefix=": "/>-          </if>-          <else>-            <text variable="page" prefix=", "/>-          </else>-        </choose>-      </else-if>-    </choose>-  </macro>-  <macro name="point-locators">-    <choose>-      <if variable="locator">-        <choose>-          <if locator="page" match="none">-            <choose>-              <if type="bill book graphic legal_case legislation motion_picture report song" match="any">-                <choose>-                  <if variable="volume">-                    <group>-                      <text term="volume" form="short" suffix=" "/>-                      <number variable="volume" form="numeric"/>-                      <label variable="locator" form="short" prefix=", " suffix=" "/>-                    </group>-                  </if>-                  <else>-                    <label variable="locator" form="short" suffix=" "/>-                  </else>-                </choose>-              </if>-              <else>-                <label variable="locator" form="short" suffix=" "/>-              </else>-            </choose>-          </if>-          <else-if type="bill book graphic legal_case legislation motion_picture report song" match="any">-            <number variable="volume" form="numeric" suffix=":"/>-          </else-if>-        </choose>-        <text variable="locator"/>-      </if>-    </choose>-  </macro>-  <macro name="container-prefix">-    <text term="in" text-case="capitalize-first"/>-  </macro>-  <macro name="container-title">-    <choose>-      <if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="any">-        <text macro="container-prefix" suffix=" "/>-      </if>-    </choose>-    <choose>-      <if type="webpage">-        <text variable="container-title" text-case="title"/>-      </if>-      <else-if type="legal_case" match="none">-        <group delimiter=" ">-          <text variable="container-title" text-case="title" font-style="italic"/>-          <choose>-            <if type="post-weblog">-              <text value="(blog)"/>-            </if>-          </choose>-        </group>-      </else-if>-    </choose>-  </macro>-  <macro name="publisher">-    <group delimiter=": ">-      <text variable="publisher-place"/>-      <text variable="publisher"/>-    </group>-  </macro>-  <macro name="date">-    <choose>-      <if variable="issued">-        <group delimiter=" ">-          <date variable="original-date" form="text" date-parts="year" prefix="(" suffix=")"/>-          <date variable="issued">-            <date-part name="year"/>-          </date>-        </group>-      </if>-      <else-if variable="status">-        <text variable="status" text-case="capitalize-first"/>-      </else-if>-      <else>-        <text term="no date" form="short"/>-      </else>-    </choose>-  </macro>-  <macro name="date-in-text">-    <choose>-      <if variable="issued">-        <group delimiter=" ">-          <date variable="original-date" form="text" date-parts="year" prefix="[" suffix="]"/>-          <date variable="issued">-            <date-part name="year"/>-          </date>-        </group>-      </if>-      <else-if variable="status">-        <text variable="status"/>-      </else-if>-      <else>-        <text term="no date" form="short"/>-      </else>-    </choose>-  </macro>-  <macro name="day-month">-    <date variable="issued">-      <date-part name="month"/>-      <date-part name="day" prefix=" "/>-    </date>-  </macro>-  <macro name="collection-title">-    <choose>-      <if match="none" type="article-journal">-        <choose>-          <if match="none" is-numeric="collection-number">-            <group delimiter=", ">-              <text variable="collection-title" text-case="title"/>-              <text variable="collection-number"/>-            </group>-          </if>-          <else>-            <group delimiter=" ">-              <text variable="collection-title" text-case="title"/>-              <text variable="collection-number"/>-            </group>-          </else>-        </choose>-      </if>-    </choose>-  </macro>-  <macro name="collection-title-journal">-    <choose>-      <if type="article-journal">-        <group delimiter=" ">-          <text variable="collection-title"/>-          <text variable="collection-number"/>-        </group>-      </if>-    </choose>-  </macro>-  <macro name="event">-    <group delimiter=" ">-      <choose>-        <if variable="genre">-          <text term="presented at"/>-        </if>-        <else>-          <text term="presented at" text-case="capitalize-first"/>-        </else>-      </choose>-      <text variable="event"/>-    </group>-  </macro>-  <macro name="description">-    <choose>-      <if variable="interviewer" type="interview" match="any">-        <group delimiter=". ">-          <text macro="interviewer"/>-          <text variable="medium" text-case="capitalize-first"/>-        </group>-      </if>-      <else-if type="patent">-        <group delimiter=" " prefix=". ">-          <text variable="authority"/>-          <text variable="number"/>-        </group>-      </else-if>-      <else>-        <text variable="medium" text-case="capitalize-first" prefix=". "/>-      </else>-    </choose>-    <choose>-      <if variable="title" match="none"/>-      <else-if type="thesis personal_communication speech" match="any"/>-      <else>-        <group delimiter=" " prefix=". ">-          <text variable="genre" text-case="capitalize-first"/>-          <choose>-            <if type="report">-              <text variable="number"/>-            </if>-          </choose>-        </group>-      </else>-    </choose>-  </macro>-  <macro name="issue">-    <choose>-      <if type="legal_case">-        <text variable="authority" prefix=". "/>-      </if>-      <else-if type="speech">-        <group prefix=". " delimiter=", ">-          <group delimiter=" ">-            <text variable="genre" text-case="capitalize-first"/>-            <text macro="event"/>-          </group>-          <text variable="event-place"/>-          <text macro="day-month"/>-        </group>-      </else-if>-      <else-if type="article-newspaper article-magazine personal_communication" match="any">-        <date variable="issued" form="text" prefix=", "/>-      </else-if>-      <else-if type="patent">-        <group delimiter=", " prefix=", ">-          <group delimiter=" ">-            <!--Needs Localization-->-            <text value="filed"/>-            <date variable="submitted" form="text"/>-          </group>-          <group delimiter=" ">-            <choose>-              <if variable="issued submitted" match="all">-                <text term="and"/>-              </if>-            </choose>-            <!--Needs Localization-->-            <text value="issued"/>-            <date variable="issued" form="text"/>-          </group>-        </group>-      </else-if>-      <else-if type="article-journal" match="any"/>-      <else>-        <group prefix=". " delimiter=", ">-          <choose>-            <if type="thesis">-              <text variable="genre" text-case="capitalize-first"/>-            </if>-          </choose>-          <text macro="publisher"/>-        </group>-      </else>-    </choose>-  </macro>-  <citation et-al-min="4" et-al-use-first="1" disambiguate-add-year-suffix="true" disambiguate-add-names="true" disambiguate-add-givenname="true" givenname-disambiguation-rule="primary-name" collapse="year" after-collapse-delimiter="; ">-    <layout prefix="(" suffix=")" delimiter="; ">-      <group delimiter=", ">-        <choose>-          <if variable="issued accessed" match="any">-            <group delimiter=" ">-              <text macro="contributors-short"/>-              <text macro="date-in-text"/>-            </group>-          </if>-          <!---comma before forthcoming and n.d.-->-          <else>-            <group delimiter=", ">-              <text macro="contributors-short"/>-              <text macro="date-in-text"/>-            </group>-          </else>-        </choose>-        <text macro="point-locators"/>-      </group>-    </layout>-  </citation>-  <bibliography hanging-indent="true" et-al-min="11" et-al-use-first="7" subsequent-author-substitute="&#8212;&#8212;&#8212;" entry-spacing="0">-    <sort>-      <key macro="contributors"/>-      <key variable="issued"/>-      <key variable="title"/>-    </sort>-    <layout suffix=".">-      <group delimiter=". ">-        <text macro="contributors"/>-        <text macro="date"/>-        <text macro="title"/>-      </group>-      <text macro="description"/>-      <text macro="secondary-contributors" prefix=". "/>-      <text macro="container-title" prefix=". "/>-      <text macro="container-contributors"/>-      <text macro="edition"/>-      <text macro="locators-chapter"/>-      <text macro="collection-title-journal" prefix=", " suffix=", "/>-      <text macro="locators"/>-      <text macro="collection-title" prefix=". "/>-      <text macro="issue"/>-      <text macro="locators-article"/>-      <text macro="access" prefix=". "/>+<style xmlns="http://purl.org/net/xbiblio/csl" class="in-text" demote-non-dropping-particle="display-and-sort" page-range-format="chicago-16" version="1.0">+  <!-- This file was generated by the Style Variant Builder <https://github.com/citation-style-language/style-variant-builder>. To contribute changes, modify the template and regenerate variants. -->+  <info>+    <title>Chicago Manual of Style 18th edition (author-date)</title>+    <title-short>CMOS with Bluebook (author-date [13.102])</title-short>+    <id>http://www.zotero.org/styles/chicago-author-date</id>+    <link href="http://www.zotero.org/styles/chicago-author-date" rel="self"/>+    <link href="http://www.zotero.org/styles/chicago-notes-bibliography" rel="template"/>+    <link href="https://www.chicagomanualofstyle.org/" rel="documentation"/>+    <author>+      <name>Andrew Dunning</name>+      <uri>https://orcid.org/0000-0003-0464-5036</uri>+    </author>+    <category citation-format="author-date"/>+    <category field="anthropology"/>+    <category field="communications"/>+    <category field="generic-base"/>+    <category field="geography"/>+    <category field="history"/>+    <category field="humanities"/>+    <category field="law"/>+    <category field="linguistics"/>+    <category field="literature"/>+    <category field="philosophy"/>+    <category field="political_science"/>+    <category field="science"/>+    <category field="social_science"/>+    <category field="sociology"/>+    <category field="theology"/>+    <summary>Chicago-style source citations (with Bluebook for legal citations), author-date system</summary>+    <updated>2025-08-07T00:00:00+00:00</updated>+    <rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>+  </info>+  <locale xml:lang="en">+    <terms>+      <!-- Chicago omits 'by' from `verb-short` forms; it abbreviates only the most common roles -->+      <term name="advance-online-publication">ahead of print</term>+      <term name="anonymous">unsigned</term>+      <term form="verb-short" name="collection-editor">ed.</term>+      <term form="short" name="collection-number">+        <single>vol.</single>+        <multiple>vols.</multiple>+      </term>+      <term form="verb-short" name="compiler">comp.</term>+      <term form="verb-short" name="editor">ed.</term>+      <term form="short" name="editor-translator">+        <single>ed. and trans.</single>+        <multiple>eds. and trans.</multiple>+      </term>+      <term form="short" name="editortranslator">+        <single>ed. and trans.</single>+        <multiple>eds. and trans.</multiple>+      </term>+      <term form="verb" name="editor-translator">edited and translated by</term>+      <term form="verb" name="editortranslator">edited and translated by</term>+      <term form="verb-short" name="editor-translator">ed. and trans.</term>+      <term form="verb-short" name="editortranslator">ed. and trans.</term>+      <term form="verb-short" name="illustrator">ill.</term>+      <term form="short" name="legislation">Pub. L.</term>+      <term name="manuscript">unpublished manuscript</term>+      <term name="original-work-published">originally published as</term>+      <term form="short" name="paper-conference">paper</term>+      <!-- 'under' replaces 's.v.' from CMOS17 and earlier (CMOS18 14.130) -->+      <term name="sub-verbo">under</term>+      <term form="short" name="sub-verbo">under</term>+      <term name="timestamp">at</term>+      <term form="verb-short" name="translator">trans.</term>+    </terms>+  </locale>+  <locale xml:lang="en-GB">+    <terms>+      <!-- ensure consistency with other `en-GB` contractions -->+      <term form="short" name="collection-number">+        <single>vol.</single>+        <multiple>vols</multiple>+      </term>+      <term form="short" name="editor-translator">+        <single>ed. and trans.</single>+        <multiple>eds and trans.</multiple>+      </term>+      <term form="short" name="editortranslator">+        <single>ed. and trans.</single>+        <multiple>eds and trans.</multiple>+      </term>+    </terms>+  </locale>+  <!-- Contents:+    +       This file interprets Chicago using APA's four basic reference elements+       (cf. CMOS18 14.2, 14.64, 14.161):++        1. Author (CMOS18 13.74-86)+        2. Date (author-date system only, CMOS18 13.102)+        3. Title and descriptions (CMOS18 13.87-101)+            3.1. Title+            3.2. Description+            3.3. Identifiers (edition, contributors, volume)+        4. Source+            4.1. Serial sources+            4.2. Monographic sources+            4.3. Series+            4.4. Event+            4.5. Publisher+            4.6. Date+            4.7. Locator (including page references)+            4.8. Medium+            4.9. Archival location+            4.10. URL or persistent identifier+      +       Freeform annotations to bibliography entries: +        +        5. Notes+       +       Chicago also provides parallel rules for legal references following+       The Bluebook: A Uniform System of Citation (code shared with APA):++        6. Legal references+  -->+  <!-- In this file, macros suffixed `-bib` and `-note` are parallel versions+       of the same features for the bibliography and notes, and all changes+       must be applied to both. They should only contain differences of+       punctuation (periods in bibliography, commas in notes) and capitalization,+       except where the comments indicate structural changes. -->+  <!-- Categories of CSL item types:++       Serial+       : article-journal article-magazine article-newspaper periodical post-weblog review review-book++       Serial or Monographic+       : interview paper-conference++         Monographic with any of `collection-editor compiler editor editorial-director`.+         A serial `paper-conference` is unpublished if it lacks any of `issue page supplement-number volume`.++       Monographic+       : article book broadcast chapter classic collection dataset document+         entry entry-dictionary entry-encyclopedia event figure+         graphic manuscript map motion_picture musical_score+         pamphlet patent performance personal_communication post report+         software song speech standard thesis webpage++       Legal+       : bill hearing legal_case legislation regulation treaty+  -->+  <!-- Variable labels -->+  <macro name="label-chapter-number">+    <group delimiter=" ">+      <choose>+        <if is-numeric="chapter-number" type="song">+          <text value="track"/>+        </if>+        <else-if is-numeric="chapter-number">+          <label form="short" variable="chapter-number"/>+        </else-if>+      </choose>+      <text variable="chapter-number"/>+    </group>+  </macro>+  <macro name="label-chapter-number-capitalized">+    <group delimiter=" ">+      <choose>+        <if is-numeric="chapter-number" type="song">+          <text text-case="capitalize-first" value="track"/>+        </if>+        <else-if is-numeric="chapter-number">+          <label form="short" text-case="capitalize-first" variable="chapter-number"/>+        </else-if>+      </choose>+      <text text-case="capitalize-first" variable="chapter-number"/>+    </group>+  </macro>+  <macro name="label-collection-number">+    <group delimiter=" ">+      <choose>+        <if is-numeric="collection-number">+          <label form="short" variable="collection-number"/>+        </if>+      </choose>+      <text variable="collection-number"/>+    </group>+  </macro>+  <macro name="label-edition">+    <group delimiter=" ">+      <choose>+        <if is-numeric="edition">+          <number form="ordinal" variable="edition"/>+          <label form="short" variable="edition"/>+        </if>+        <else-if match="any" type="article-journal article-magazine article-newspaper periodical post-weblog review review-book">+          <!-- full label for serial edition (CMOS18 14.89) -->+          <text variable="edition"/>+          <label variable="edition"/>+        </else-if>+        <else-if match="any" type="interview paper-conference">+          <choose>+            <if match="any" variable="collection-editor compiler editor editorial-director">+              <!-- monographic usage -->+              <text variable="edition"/>+            </if>+            <else>+              <!-- serial usage -->+              <text variable="edition"/>+              <label variable="edition"/>+            </else>+          </choose>+        </else-if>+        <else>+          <text variable="edition"/>+        </else>+      </choose>+    </group>+  </macro>+  <macro name="label-edition-capitalized">+    <group delimiter=" ">+      <choose>+        <if is-numeric="edition">+          <number form="ordinal" variable="edition"/>+          <label form="short" variable="edition"/>+        </if>+        <else-if match="any" type="article-journal article-magazine article-newspaper periodical post-weblog review review-book">+          <!-- full label for serial edition (CMOS18 14.89) -->+          <text text-case="title" variable="edition"/>+          <label text-case="capitalize-first" variable="edition"/>+        </else-if>+        <else-if match="any" type="interview paper-conference">+          <choose>+            <if match="any" variable="collection-editor compiler editor editorial-director">+              <!-- monographic usage -->+              <text text-case="capitalize-first" variable="edition"/>+            </if>+            <else>+              <!-- serial usage -->+              <text text-case="title" variable="edition"/>+              <label text-case="capitalize-first" variable="edition"/>+            </else>+          </choose>+        </else-if>+        <else>+          <text text-case="capitalize-first" variable="edition"/>+        </else>+      </choose>+    </group>+  </macro>+  <macro name="label-issue">+    <group delimiter=" ">+      <label form="short" variable="issue"/>+      <text variable="issue"/>+    </group>+  </macro>+  <macro name="label-locator">+    <group delimiter=" ">+      <choose>+        <if locator="page"/>+        <else-if match="any" type="bill hearing legal_case legislation regulation treaty">+          <!-- Bluebook-style labels for legal types (CMOS18 14.174) -->+          <choose>+            <if locator="chapter paragraph section" match="any">+              <label form="symbol" variable="locator"/>+            </if>+            <else>+              <label form="short" variable="locator"/>+            </else>+          </choose>+        </else-if>+        <else-if is-numeric="locator">+          <choose>+            <if locator="line">+              <label variable="locator"/>+            </if>+            <else>+              <label form="short" variable="locator"/>+            </else>+          </choose>+        </else-if>+        <else-if locator="chapter line verse" match="any"/>+        <!-- a non-numeric canonical reference is identified by its formatting and does not need a label (CMOS18 14.143-54) -->+        <else>+          <label form="short" variable="locator"/>+        </else>+      </choose>+      <text variable="locator"/>+    </group>+  </macro>+  <macro name="label-number-capitalized">+    <group delimiter=" ">+      <choose>+        <if type="standard"/>+        <else-if is-numeric="number" match="any" type="legislation regulation">+          <label form="short" text-case="capitalize-first" variable="number"/>+        </else-if>+      </choose>+      <text text-case="capitalize-first" variable="number"/>+    </group>+  </macro>+  <macro name="label-number-of-volumes">+    <group delimiter=" ">+      <text variable="number-of-volumes"/>+      <choose>+        <if is-numeric="number-of-volumes">+          <label form="short" variable="number-of-volumes"/>+        </if>+      </choose>+    </group>+  </macro>+  <macro name="label-part-number">+    <group delimiter=" ">+      <choose>+        <if is-numeric="part-number">+          <!-- TODO: Replace with `part-number` label when CSL provides one -->+          <text form="short" term="part"/>+        </if>+      </choose>+      <text variable="part-number"/>+    </group>+  </macro>+  <macro name="label-part-number-capitalized">+    <group delimiter=" ">+      <choose>+        <if is-numeric="part-number">+          <!-- TODO: Replace with `part-number` label when CSL provides one -->+          <text form="short" term="part" text-case="capitalize-first"/>+        </if>+      </choose>+      <text text-case="capitalize-first" variable="part-number"/>+    </group>+  </macro>+  <macro name="label-section-capitalized">+    <group delimiter=" ">+      <choose>+        <if is-numeric="section">+          <label form="short" text-case="capitalize-first" variable="section"/>+        </if>+      </choose>+      <text text-case="title" variable="section"/>+    </group>+  </macro>+  <macro name="label-section-symbol">+    <group delimiter=" ">+      <label form="symbol" variable="section"/>+      <text variable="section"/>+    </group>+  </macro>+  <macro name="label-supplement-number">+    <group delimiter=" ">+      <choose>+        <!-- TODO: Replace with `supplement-number` label when CSL provides one -->+        <if is-numeric="supplement-number" variable="volume-title">+          <!-- if there is a volume title, it is already described as a supplement -->+          <text form="short" term="issue"/>+        </if>+        <else-if is-numeric="supplement-number" type="periodical" variable="title">+          <text form="short" term="issue"/>+        </else-if>+        <else-if is-numeric="supplement-number">+          <text form="short" term="supplement"/>+        </else-if>+      </choose>+      <text variable="supplement-number"/>+    </group>+  </macro>+  <macro name="label-version">+    <group delimiter=" ">+      <choose>+        <if type="software">+          <!-- short version label for software (CMOS18 14.169) -->+          <label form="short" variable="version"/>+        </if>+        <else>+          <label variable="version"/>+        </else>+      </choose>+      <text variable="version"/>+    </group>+  </macro>+  <macro name="label-version-capitalized">+    <group delimiter=" ">+      <choose>+        <if type="software">+          <!-- short version label for software (CMOS18 14.169) -->+          <label form="short" text-case="capitalize-first" variable="version"/>+        </if>+        <else>+          <label text-case="capitalize-first" variable="version"/>+        </else>+      </choose>+      <text variable="version"/>+    </group>+  </macro>+  <macro name="label-volume">+    <group delimiter=" ">+      <choose>+        <if is-numeric="volume">+          <label form="short" variable="volume"/>+        </if>+      </choose>+      <text variable="volume"/>+    </group>+  </macro>+  <macro name="label-volume-capitalized">+    <group delimiter=" ">+      <choose>+        <if is-numeric="volume">+          <label form="short" text-case="capitalize-first" variable="volume"/>+        </if>+      </choose>+      <text text-case="capitalize-first" variable="volume"/>+    </group>+  </macro>+  <!-- 1. Author (CMOS18 13.74-86) -->+  <macro name="author-bib">+    <names variable="composer">+      <name and="text" delimiter-precedes-last="always" name-as-sort-order="first"/>+      <label form="short" prefix=", "/>+      <substitute>+        <names variable="author"/>+        <!-- cf. `interview` model (CMOS18 14.110); if it is desired to prioritize `host` over `guest`, the latter could be encoded as a `contributor` -->+        <names variable="guest"/>+        <names variable="host"/>+        <choose>+          <if type="song">+            <names variable="performer"/>+          </if>+        </choose>+        <choose>+          <if type="classic">+            <!-- contributors fall after the title of `classic` (CMOS18 14.147) -->+            <text macro="author-title-substitute-bib"/>+          </if>+          <else-if type="entry-dictionary" variable="container-title">+            <!-- contributors fall after the title of unsigned reference entries (CMOS18 14.130) -->+            <text macro="author-title-substitute-container"/>+          </else-if>+          <else-if type="entry-encyclopedia" variable="container-title">+            <text macro="author-title-substitute-container"/>+          </else-if>+        </choose>+        <names variable="illustrator"/>+        <choose>+          <if match="none" type="standard">+            <names variable="editor-translator"/>+            <names variable="editor"/>+            <names variable="translator"/>+            <names variable="collection-editor"/>+          </if>+        </choose>+        <names variable="director"/>+        <choose>+          <!-- serial `broadcast` prioritizes title (CMOS18 14.165, 14.168) -->+          <if type="broadcast" variable="container-title number title"/>+          <else>+            <names variable="producer"/>+            <names variable="executive-producer"/>+            <names variable="series-creator"/>+            <choose>+              <if type="broadcast">+                <names variable="contributor"/>+              </if>+            </choose>+          </else>+        </choose>+        <names variable="editorial-director"/>+        <names variable="compiler"/>+        <choose>+          <if match="any" type="event performance speech">+            <names variable="chair"/>+            <names variable="organizer"/>+          </if>+        </choose>+        <names variable="curator"/>+        <choose>+          <if type="software">+            <!-- `software` listed under the name of the publisher or developer (CMOS18 14.169) -->+            <text variable="publisher"/>+          </if>+          <else-if type="standard">+            <!-- `standard` listed in bibliography under organization, but note omits this (CMOS18 14.159) -->+            <text variable="authority"/>+          </else-if>+        </choose>+        <text macro="author-title-substitute-container"/>+        <text macro="author-title-substitute-bib"/>+        <choose>+          <if type="manuscript">+            <choose>+              <if match="none" variable="container-title event-date event-place event-title genre title publisher publisher-place">+                <text macro="source-archive-bib"/>+              </if>+            </choose>+          </if>+        </choose>+      </substitute>+    </names>+  </macro>+  <macro name="author-inline">+    <choose>+      <if match="any" type="bill hearing legal_case legislation regulation treaty">+        <text macro="title-and-descriptions-short"/>+      </if>+      <else-if match="any" type="interview personal_communication">+        <text macro="author-inline-and-recipient"/>+      </else-if>+      <else>+        <names variable="composer">+          <name and="text" form="short" initialize-with=". "/>+          <substitute>+            <names variable="author"/>+            <names variable="guest"/>+            <names variable="host"/>+            <choose>+              <if type="song">+                <names variable="performer"/>+              </if>+            </choose>+            <choose>+              <if match="any" type="classic performance">+                <!-- contributors fall after the title of `classic` (CMOS18 14.147), `performance` (CMOS18 14.166) -->+                <text macro="author-title-substitute-short"/>+              </if>+              <else-if match="any" type="entry entry-dictionary entry-encyclopedia">+                <!-- contributors fall after the title of unsigned reference entries (CMOS18 14.130) -->+                <choose>+                  <if variable="container-title">+                    <text macro="author-title-substitute-container"/>+                  </if>+                </choose>+              </else-if>+            </choose>+            <names variable="illustrator"/>+            <choose>+              <if match="none" type="standard">+                <names variable="editor-translator"/>+                <names variable="editor"/>+                <names variable="translator"/>+                <names variable="collection-editor"/>+              </if>+            </choose>+            <choose>+              <if type="broadcast" variable="container-title number title"/>+              <else>+                <names variable="director"/>+                <names variable="producer"/>+                <names variable="executive-producer"/>+                <names variable="series-creator"/>+                <choose>+                  <if type="broadcast">+                    <names variable="contributor"/>+                  </if>+                </choose>+              </else>+            </choose>+            <names variable="editorial-director"/>+            <names variable="compiler"/>+            <choose>+              <if match="any" type="event performance speech">+                <names variable="chair"/>+                <names variable="organizer"/>+              </if>+            </choose>+            <names variable="curator"/>+            <choose>+              <if type="software">+                <!-- `software` listed under the name of the publisher or developer (CMOS18 14.169) -->+                <text variable="publisher"/>+              </if>+              <else-if type="standard">+                <!-- `standard` listed in bibliography under organization, but note omits this (CMOS18 14.159) -->+                <text variable="authority"/>+              </else-if>+            </choose>+            <text macro="author-title-substitute-container-short"/>+            <text macro="author-title-substitute-short"/>+            <choose>+              <if type="manuscript">+                <choose>+                  <if match="none" variable="container-title event-date event-place event-title genre title publisher publisher-place">+                    <text macro="source-archive-note"/>+                  </if>+                </choose>+              </if>+            </choose>+          </substitute>+        </names>+      </else>+    </choose>+  </macro>+  <macro name="author-sort">+    <choose>+      <if match="any" type="bill hearing legal_case legislation regulation treaty">+        <text macro="legal-title"/>+      </if>+      <else>+        <text macro="author-bib"/>+      </else>+    </choose>+  </macro>+  <!-- Author elements -->+  <macro name="author-inline-and-recipient">+    <!-- identical to `author-short-and-recipient` but with initialization -->+    <group delimiter=" ">+      <choose>+        <!-- Inaccessible personal commmunication is cited in-text (CMOS18 14.111) -->+        <if match="none" variable="archive archive-place container-title DOI number publisher references URL">+          <!-- These variables indicate whether the letter is retrievable by the reader -->+          <group delimiter=", ">+            <names variable="author">+              <name and="text" initialize-with=". "/>+              <substitute>+                <text macro="title-and-descriptions-short"/>+              </substitute>+            </names>+          </group>+          <choose>+            <if match="none" variable="genre">+              <names variable="recipient">+                <label form="verb" suffix=" "/>+                <name and="text" initialize-with=". "/>+              </names>+            </if>+          </choose>+        </if>+        <else-if variable="author recipient">+          <names variable="author">+            <label/>+            <name and="text" form="short" initialize-with=". "/>+          </names>+          <choose>+            <if match="none" variable="genre">+              <names variable="recipient">+                <label form="verb" suffix=" "/>+                <name and="text" form="short" initialize-with=". "/>+              </names>+            </if>+          </choose>+        </else-if>+        <else>+          <names variable="author">+            <name and="text" form="short" initialize-with=". "/>+            <substitute>+              <text macro="title-and-descriptions-short"/>+            </substitute>+          </names>+        </else>+      </choose>+    </group>+  </macro>+  <macro name="author-title-substitute-bib">+    <choose>+      <if match="any" type="review review-book" variable="reviewed-author reviewed-genre reviewed-title">+        <!-- If a review has no `reviewed-genre` or `reviewed-title`, assume that `title` contains the title of the reviewed work; the description provides it. -->+        <choose>+          <if variable="reviewed-genre title">+            <text macro="title-bib"/>+          </if>+          <else-if variable="reviewed-genre reviewed-title title">+            <text macro="title-bib"/>+          </else-if>+          <else>+            <text macro="title-and-descriptions-bib"/>+          </else>+        </choose>+      </if>+      <else-if variable="title">+        <text macro="title-bib"/>+      </else-if>+      <else>+        <!-- If an item has no `title`, substitute with descriptions. -->+        <text macro="title-and-descriptions-bib"/>+      </else>+    </choose>+  </macro>+  <macro name="author-title-substitute-short">+    <choose>+      <if match="any" type="review review-book" variable="reviewed-author reviewed-genre reviewed-title">+        <!-- If a review has no `reviewed-genre` or `reviewed-title`, assume that `title` contains the title of the reviewed work; the description provides it. -->+        <choose>+          <if variable="reviewed-genre title">+            <text macro="title-short"/>+          </if>+          <else-if variable="reviewed-genre reviewed-title title">+            <text macro="title-short"/>+          </else-if>+          <else>+            <text macro="title-and-descriptions-short"/>+          </else>+        </choose>+      </if>+      <else-if variable="title">+        <text macro="title-short"/>+      </else-if>+      <else>+        <!-- If an item has no `title`, substitute with descriptions and capitalize -->+        <text macro="title-and-descriptions-bib"/>+      </else>+    </choose>+  </macro>+  <macro name="author-title-substitute-container">+    <choose>+      <if match="none" variable="container-title"/>+      <else-if match="any" type="article-magazine article-newspaper">+        <!-- Anonymous magazine and newspaper articles substitute name of publication (CMOS18 14.87, 14.97) -->+        <text macro="source-serial-name"/>+      </else-if>+      <else-if match="any" type="review review-book" variable="reviewed-author reviewed-genre reviewed-title">+        <!-- Publication name also substituted for unsigned reviews (CMOS18 14.102) -->+        <text macro="source-serial-name"/>+      </else-if>+      <else-if match="any" type="interview paper-conference">+        <choose>+          <if match="none" variable="collection-editor compiler editor editorial-director">+            <!-- serial usage -->+            <text macro="source-serial-name"/>+          </if>+        </choose>+      </else-if>+      <else-if match="any" type="entry entry-dictionary entry-encyclopedia">+        <!-- Anonymous entries in reference works (CMOS18 14.130) -->+        <text font-style="italic" text-case="title" variable="container-title"/>+      </else-if>+      <else-if type="broadcast">+        <!-- TV broadcasts and podcasts (CMOS18 14.165, 14.168) -->+        <text font-style="italic" text-case="title" variable="container-title"/>+      </else-if>+      <else-if type="webpage">+        <!-- Website title substituted in bibliography only (CMOS18 14.104) -->+        <text text-case="title" variable="container-title"/>+      </else-if>+    </choose>+  </macro>+  <macro name="author-title-substitute-container-short">+    <choose>+      <if match="none" variable="container-title"/>+      <else-if match="any" type="article-magazine article-newspaper">+        <!-- Anonymous magazine/newspaper articles substitute name of publication (CMOS18 14.87, 14.97) -->+        <text font-style="italic" text-case="title" variable="container-title"/>+      </else-if>+      <else-if match="any" type="review review-book" variable="reviewed-author reviewed-genre reviewed-title">+        <!-- Publication name also substituted for unsigned reviews (CMOS18 14.102) -->+        <text font-style="italic" text-case="title" variable="container-title"/>+      </else-if>+      <else-if match="any" type="interview paper-conference">+        <choose>+          <if match="none" variable="collection-editor compiler editor editorial-director">+            <!-- serial usage -->+            <text font-style="italic" text-case="title" variable="container-title"/>+          </if>+        </choose>+      </else-if>+      <else-if match="any" type="entry entry-dictionary entry-encyclopedia">+        <!-- Anonymous entries in reference works (CMOS18 14.130) -->+        <text font-style="italic" text-case="title" variable="container-title"/>+      </else-if>+      <else-if type="broadcast">+        <!-- TV broadcasts and podcasts (CMOS18 14.165, 14.168) -->+        <text font-style="italic" text-case="title" variable="container-title"/>+      </else-if>+      <else-if type="webpage">+        <!-- Website title substituted in bibliography only (CMOS18 14.104) -->+        <text text-case="title" variable="container-title"/>+      </else-if>+    </choose>+  </macro>+  <!-- 2. Date (CMOS18 13.102) -->+  <macro name="date">+    <choose>+      <if variable="issued">+        <group delimiter=" ">+          <!-- reprints and earlier editions may give original year in brackets (CMOS18 14.16) -->+          <text macro="date-original-year" prefix="(" suffix=")"/>+          <group>+            <text macro="date-issued-year"/>+            <text variable="year-suffix"/>+          </group>+        </group>+      </if>+      <else-if variable="available-date">+        <date date-parts="year" form="text" variable="available-date"/>+      </else-if>+      <else-if variable="event-date">+        <text macro="date-event-year"/>+      </else-if>+      <else-if variable="status">+        <group>+          <!-- Print the status variable rather than use generic CSL terms (`in press`, etc.) -->+          <text text-case="capitalize-first" variable="status"/>+          <text prefix="-" variable="year-suffix"/>+        </group>+      </else-if>+      <else-if type="collection">+        <!-- do not give n.d. for archival collections (CMOS18 14.128) -->+        <text prefix="-" variable="year-suffix"/>+      </else-if>+      <else-if type="manuscript">+        <!-- do not give n.d. with a bare shelfmark -->+        <choose>+          <if match="any" variable="container-title event-date event-place event-title genre title publisher publisher-place">+            <text form="short" term="no date"/>+            <text prefix="-" variable="year-suffix"/>+          </if>+        </choose>+      </else-if>+      <else>+        <text form="short" term="no date"/>+        <text prefix="-" variable="year-suffix"/>+      </else>+    </choose>+  </macro>+  <macro name="date-short">+    <choose>+      <if variable="issued">+        <group delimiter=" ">+          <choose>+            <if is-uncertain-date="original-date">+              <!-- Uncertain date already has square brackets -->+              <text macro="date-original-year"/>+            </if>+            <else>+              <text macro="date-original-year" prefix="[" suffix="]"/>+            </else>+          </choose>+          <group>+            <choose>+              <if match="any" type="interview personal_communication">+                <choose>+                  <if match="any" variable="archive archive-place container-title DOI number publisher references URL">+                    <!-- These variables indicate that the communication is retrievable by the reader. If not, then use the in-text-only personal communication format -->+                    <text macro="date-issued-year"/>+                  </if>+                  <else>+                    <text macro="date-issued-full"/>+                  </else>+                </choose>+              </if>+              <else>+                <text macro="date-issued-year"/>+              </else>+            </choose>+            <text variable="year-suffix"/>+          </group>+        </group>+      </if>+      <else-if variable="available-date">+        <date date-parts="year" form="text" variable="available-date"/>+      </else-if>+      <else-if variable="event-date">+        <text macro="date-event-year"/>+      </else-if>+      <else-if variable="status">+        <!-- Print the status variable rather than use generic CSL terms (`in press`, etc.) -->+        <text text-case="lowercase" variable="status"/>+        <text prefix="-" variable="year-suffix"/>+      </else-if>+      <else-if match="any" type="interview personal_communication">+        <choose>+          <if match="any" variable="archive archive-place container-title DOI number publisher references URL">+            <!-- only give n.d. for accessible personal communication (CMOS18 14.111)-->+            <text form="short" term="no date"/>+          </if>+        </choose>+        <text prefix="-" variable="year-suffix"/>+      </else-if>+      <else-if match="any" type="classic collection entry entry-dictionary entry-encyclopedia">+        <!-- do not give n.d. for archival collections (CMOS18 14.128), `classic` (CMOS18 14.143), or reference entries (CMOS18 14.131) -->+        <text prefix="-" variable="year-suffix"/>+      </else-if>+      <else-if type="manuscript">+        <!-- do not give n.d. with a bare shelfmark -->+        <choose>+          <if match="any" variable="container-title event-date event-place event-title genre title publisher publisher-place">+            <text form="short" term="no date"/>+            <text prefix="-" variable="year-suffix"/>+          </if>+        </choose>+      </else-if>+      <else>+        <text form="short" term="no date"/>+        <text prefix="-" variable="year-suffix"/>+      </else>+    </choose>+  </macro>+  <macro name="date-sort-group">+    <!-- Sort items with and without dates (CMOS18 14.44):++          1. items with dates (= 0)+          2. `no date` items (= 1)+          3. items with `status` (forthcoming, in press, etc.) (= 2) -->+    <choose>+      <if variable="issued">+        <text value="0"/>+      </if>+      <else-if variable="status">+        <text value="2"/>+      </else-if>+      <else>+        <!-- n.d. -->+        <text value="1"/>+      </else>+    </choose>+  </macro>+  <macro name="date-sort-year">+    <!-- while reference lists are to be sorted chronologically (CMOS18 13.112), it appears that only the year is to be taken into account (CMOS18 13.114) -->+    <choose>+      <if type="personal_communication" variable="event-date issued">+        <date date-parts="year" form="text" variable="event-date"/>+      </if>+      <else>+        <text macro="date-issued-year"/>+      </else>+    </choose>+  </macro>+  <!-- Date elements -->+  <macro name="date-event-full">+    <choose>+      <if is-uncertain-date="issued">+        <!-- guessed-at date (CMOS18 14.44) -->+        <date form="text" prefix="[" suffix="?]" variable="event-date"/>+      </if>+      <else>+        <date form="text" variable="event-date"/>+      </else>+    </choose>+  </macro>+  <macro name="date-event-year">+    <choose>+      <if is-uncertain-date="issued">+        <!-- guessed-at date (CMOS18 14.44) -->+        <date date-parts="year" form="text" prefix="[" suffix="?]" variable="event-date"/>+      </if>+      <else>+        <date date-parts="year" form="text" variable="event-date"/>+      </else>+    </choose>+  </macro>+  <macro name="date-issued-full">+    <choose>+      <if is-uncertain-date="issued">+        <!-- guessed-at date (CMOS18 14.44) -->+        <date form="text" prefix="[" suffix="?]" variable="issued"/>+      </if>+      <else>+        <date form="text" variable="issued"/>+      </else>+    </choose>+  </macro>+  <macro name="date-issued-month">+    <date variable="issued">+      <date-part name="month"/>+    </date>+  </macro>+  <macro name="date-issued-month-day">+    <date variable="issued">+      <date-part name="month"/>+      <date-part name="day" prefix=" "/>+    </date>+  </macro>+  <macro name="date-issued-year">+    <choose>+      <if is-uncertain-date="issued">+        <!-- guessed-at date (CMOS18 14.44) -->+        <date date-parts="year" form="text" prefix="[" suffix="?]" variable="issued"/>+      </if>+      <else>+        <date date-parts="year" form="text" variable="issued"/>+      </else>+    </choose>+  </macro>+  <macro name="date-original-month">+    <date variable="original-date">+      <date-part name="month"/>+    </date>+  </macro>+  <macro name="date-original-month-day">+    <date variable="original-date">+      <date-part name="month"/>+      <date-part name="day" prefix=" "/>+    </date>+  </macro>+  <macro name="date-original-year">+    <choose>+      <if is-uncertain-date="original-date">+        <date date-parts="year" form="text" prefix="[" suffix="?]" variable="original-date"/>+      </if>+      <else>+        <date date-parts="year" form="text" variable="original-date"/>+      </else>+    </choose>+  </macro>+  <!-- 3. Title and descriptions (CMOS18 13.87-101) -->+  <macro name="title-and-descriptions-bib">+    <group delimiter=". ">+      <choose>+        <if variable="title">+          <text macro="title-bib"/>+          <text macro="description-bib"/>+          <text macro="identifier-bib"/>+        </if>+        <else-if match="any" type="bill report">+          <!-- Bills, resolutions, and congressional reports substitute bill number if no title -->+          <!-- Congressional reports are indistinguishable from other reports -->+          <text macro="identifier-number-bib"/>+          <text macro="identifier-bib"/>+          <text macro="description-bib"/>+        </else-if>+        <else>+          <text macro="description-bib"/>+          <text macro="identifier-bib"/>+        </else>+      </choose>+    </group>+  </macro>+  <macro name="title-and-descriptions-short">+    <choose>+      <if variable="title">+        <text macro="title-short"/>+      </if>+      <else-if match="any" type="bill report">+        <!-- Bills, resolutions, and congressional reports substitute bill number if no title -->+        <text macro="legal-identifier-bill-report"/>+      </else-if>+      <else>+        <text macro="description-short"/>+      </else>+    </choose>+  </macro>+  <macro name="title-and-source-bib">+    <group delimiter=". ">+      <choose>+        <if type="broadcast" variable="container-title number title">+          <!-- Bespoke `broadcast` format (CMOS18 14.165, 14.168) -->+          <text macro="source-monographic-title-bib"/>+          <group delimiter=", ">+            <text macro="identifier-number-bib"/>+            <text macro="title-bib"/>+            <text macro="description-bib"/>+            <text macro="source-monographic-identifier-contributors-bib"/>+          </group>+          <text macro="source-series-bib"/>+          <choose>+            <!-- show event information here only if not collapsed with `issued` (CMOS18 14.167) -->+            <if match="any" variable="event-date original-date original-publisher original-publisher-place publisher status">+              <text macro="source-event-bib"/>+            </if>+          </choose>+        </if>+        <else-if type="chapter" variable="container-title genre">+          <!-- 'Introduction to' etc. (CMOS18 14.12, 14.14) -->+          <group delimiter=" ">+            <text macro="title-and-descriptions-bib"/>+            <text macro="source-bib"/>+          </group>+        </else-if>+        <else>+          <text macro="title-and-descriptions-bib"/>+          <text macro="source-bib"/>+        </else>+      </choose>+      <group delimiter=", ">+        <choose>+          <!-- show event information here only if collapsed with `issued` (CMOS18 14.167) -->+          <if match="any" variable="event-date original-date original-publisher original-publisher-place publisher status"/>+          <!-- monographic usage only -->+          <else-if match="any" type="article-journal article-magazine article-newspaper periodical post-weblog review review-book"/>+          <else-if match="any" type="interview paper-conference">+            <choose>+              <if match="any" variable="collection-editor container-author editor editorial-director">+                <!-- monographic usage -->+                <text macro="source-event-bib"/>+              </if>+            </choose>+          </else-if>+          <else>+            <text macro="source-event-bib"/>+          </else>+        </choose>+        <text macro="source-monographic-publication-bib"/>+      </group>+      <text macro="source-medium-bib"/>+      <text macro="source-archive-bib"/>+      <text macro="source-date-accessed-DOI-URL-bib"/>+    </group>+  </macro>+  <!-- 3.1. Title -->+  <macro name="title-bib">+    <choose>+      <if match="any" type="post webpage">+        <!-- Handle `container-title` on `post` or `webpage` in manner of `publisher` -->+        <text macro="title-and-part-filter-review-bib"/>+      </if>+      <else-if match="any" type="article-journal article-magazine article-newspaper periodical post-weblog review review-book">+        <text macro="title-and-part-filter-review-bib"/>+      </else-if>+      <else-if match="any" type="interview paper-conference">+        <choose>+          <if match="any" variable="collection-editor compiler editor editorial-director">+            <!-- monographic usage -->+            <text macro="title-monographic-bib"/>+          </if>+          <else>+            <!-- serial usage -->+            <text macro="title-and-part-filter-review-bib"/>+          </else>+        </choose>+      </else-if>+      <else>+        <text macro="title-monographic-bib"/>+      </else>+    </choose>+  </macro>+  <macro name="title-short">+    <choose>+      <if match="any" type="review review-book" variable="reviewed-author reviewed-genre reviewed-title">+        <!-- If a review has no `reviewed-title`, assume that `title` contains the title of the reviewed work; the description provides it. -->+        <choose>+          <if variable="reviewed-genre title">+            <!-- Quotes, title case -->+            <text form="short" quotes="true" text-case="title" variable="title"/>+          </if>+          <else-if variable="reviewed-genre reviewed-title title">+            <!-- Quotes, title case -->+            <text form="short" quotes="true" text-case="title" variable="title"/>+          </else-if>+          <else>+            <text macro="description-short"/>+          </else>+        </choose>+      </if>+      <else>+        <text macro="title-primary-short"/>+      </else>+    </choose>+  </macro>+  <!-- Title elements -->+  <macro name="title-and-part-filter-review-bib">+    <choose>+      <if match="any" type="review review-book" variable="reviewed-author reviewed-genre reviewed-title">+        <!-- `title` is only the review title if there is a separate `reviewed-genre` or `reviewed-title`; otherwise, it is the title of the reviewed work, printed in the description -->+        <choose>+          <if match="any" variable="reviewed-genre reviewed-title">+            <text macro="title-and-part-title-bib"/>+          </if>+        </choose>+      </if>+      <else>+        <text macro="title-and-part-title-bib"/>+      </else>+    </choose>+  </macro>+  <macro name="title-and-part-title-bib">+    <group delimiter=". ">+      <text macro="title-primary"/>+      <group delimiter=", ">+        <text macro="label-part-number-capitalized"/>+        <text macro="title-part"/>+      </group>+    </group>+  </macro>+  <macro name="title-monographic-bib">+    <!-- For monographic items, assume `part-number` and `part-title` refer to the book/volume. -->+    <!-- There is no `title-monographic-note` as notes always open with the primary title. -->+    <choose>+      <if variable="container-title">+        <text macro="title-primary"/>+      </if>+      <!-- For monographic items without `container-title`, bibliography entries list `part-title` or `volume-title` first if available -->+      <else-if variable="part-title">+        <text macro="title-part"/>+      </else-if>+      <else-if variable="volume-title">+        <text font-style="italic" text-case="title" variable="volume-title"/>+      </else-if>+      <else>+        <text macro="title-primary"/>+      </else>+    </choose>+  </macro>+  <macro name="title-part">+    <choose>+      <if type="patent">+        <!-- No italics or quotes, sentence case -->+        <text form="short" text-case="capitalize-first" variable="part-title"/>+      </if>+      <else-if match="any" type="bill collection legislation regulation treaty">+        <!-- No italics or quotes, title case -->+        <text text-case="title" variable="part-title"/>+      </else-if>+      <else-if type="legal_case">+        <!-- Italicized, sentence case -->+        <text font-style="italic" variable="part-title"/>+      </else-if>+      <else-if match="any" type="book classic graphic hearing map">+        <!-- Italicized, title case (regardless of `container-title`) -->+        <text font-style="italic" text-case="title" variable="part-title"/>+      </else-if>+      <else-if type="entry-encyclopedia" variable="author container-title">+        <!-- Signed encyclopedia entry in quotes, title case (CMOS18 14.132) -->+        <text quotes="true" text-case="title" variable="part-title"/>+      </else-if>+      <else-if type="entry-dictionary" variable="container-title">+        <!-- Quotes, sentence case -->+        <text quotes="true" variable="part-title"/>+      </else-if>+      <else-if type="entry-encyclopedia" variable="container-title">+        <!-- Quotes, sentence case -->+        <text quotes="true" variable="part-title"/>+      </else-if>+      <else-if type="post">+        <!-- Quotes, sentence case -->+        <text quotes="true" variable="part-title"/>+      </else-if>+      <!-- Other types are formatted based on presence of `container-title` -->+      <else-if variable="container-title">+        <!-- Quotes, title case -->+        <text quotes="true" text-case="title" variable="part-title"/>+      </else-if>+      <else-if match="any" type="article dataset document interview manuscript paper-conference personal_communication speech thesis webpage">+        <!-- Container-like but not necessarily with `container-title` -->+        <!-- Quotes, title case -->+        <text quotes="true" text-case="title" variable="part-title"/>+      </else-if>+      <else>+        <!-- Italicized, title case (default) -->+        <text font-style="italic" text-case="title" variable="part-title"/>+      </else>+    </choose>+  </macro>+  <macro name="title-primary">+    <choose>+      <if type="patent">+        <!-- No italics or quotes, sentence case -->+        <text form="short" text-case="capitalize-first" variable="title"/>+      </if>+      <else-if match="any" type="bill collection legislation regulation treaty">+        <!-- No italics or quotes, title case -->+        <text text-case="title" variable="title"/>+      </else-if>+      <else-if type="legal_case">+        <!-- Italicized, sentence case -->+        <text font-style="italic" variable="title"/>+      </else-if>+      <else-if match="any" type="book classic graphic hearing map">+        <!-- Italicized, title case (regardless of `container-title`) -->+        <text font-style="italic" text-case="title" variable="title"/>+      </else-if>+      <else-if type="entry-encyclopedia" variable="author container-title">+        <!-- Signed encyclopedia entry in quotes, title case (CMOS18 14.132) -->+        <text quotes="true" text-case="title" variable="title"/>+      </else-if>+      <else-if type="entry-dictionary" variable="container-title">+        <!-- Quotes, sentence case -->+        <text quotes="true" variable="title"/>+      </else-if>+      <else-if type="entry-encyclopedia" variable="container-title">+        <!-- Quotes, sentence case -->+        <text quotes="true" variable="title"/>+      </else-if>+      <else-if type="post">+        <!-- Quotes, sentence case -->+        <text quotes="true" variable="title"/>+      </else-if>+      <!-- Other types are formatted based on presence of `container-title` -->+      <else-if variable="container-title">+        <!-- Quotes, title case -->+        <text quotes="true" text-case="title" variable="title"/>+      </else-if>+      <else-if match="any" type="article dataset document interview manuscript paper-conference personal_communication speech thesis webpage">+        <!-- Container-like but not necessarily with `container-title` -->+        <!-- Quotes, title case -->+        <text quotes="true" text-case="title" variable="title"/>+      </else-if>+      <else>+        <!-- Italicized, title case (default) -->+        <text font-style="italic" text-case="title" variable="title"/>+      </else>+    </choose>+  </macro>+  <macro name="title-primary-short">+    <choose>+      <if type="patent">+        <!-- No italics or quotes, sentence case -->+        <text form="short" text-case="capitalize-first" variable="title"/>+      </if>+      <else-if match="any" type="bill collection legislation regulation treaty">+        <!-- No italics or quotes, title case -->+        <text form="short" text-case="title" variable="title"/>+      </else-if>+      <else-if type="legal_case">+        <!-- Italicized, sentence case -->+        <text font-style="italic" form="short" variable="title"/>+      </else-if>+      <else-if match="any" type="book classic graphic hearing map">+        <!-- Italicized, title case (regardless of `container-title`) -->+        <text font-style="italic" form="short" text-case="title" variable="title"/>+      </else-if>+      <else-if type="entry-encyclopedia" variable="author container-title">+        <!-- Signed encyclopedia entry in quotes, title case (CMOS18 14.132) -->+        <text form="short" quotes="true" text-case="title" variable="title"/>+      </else-if>+      <else-if type="entry-dictionary" variable="container-title">+        <!-- Quotes, sentence case -->+        <text form="short" quotes="true" variable="title"/>+      </else-if>+      <else-if type="entry-encyclopedia" variable="container-title">+        <!-- Quotes, sentence case -->+        <text form="short" quotes="true" variable="title"/>+      </else-if>+      <else-if type="post">+        <!-- Quotes, sentence case -->+        <text form="short" quotes="true" variable="title"/>+      </else-if>+      <!-- Other types are formatted based on presence of `container-title` -->+      <else-if variable="container-title">+        <!-- Quotes, title case -->+        <text form="short" quotes="true" text-case="title" variable="title"/>+      </else-if>+      <else-if match="any" type="article dataset document interview manuscript paper-conference personal_communication speech thesis webpage">+        <!-- Container-like but not necessarily with `container-title` -->+        <!-- Quotes, title case -->+        <text form="short" quotes="true" text-case="title" variable="title"/>+      </else-if>+      <else>+        <!-- Italicized, title case (default) -->+        <text font-style="italic" form="short" text-case="title" variable="title"/>+      </else>+    </choose>+  </macro>+  <!-- 3.2. Description -->+  <macro name="description-bib">+    <choose>+      <if match="any" type="interview" variable="interviewer">+        <text macro="description-interview-bib"/>+      </if>+      <else-if match="any" type="review review-book" variable="reviewed-author reviewed-genre reviewed-title">+        <text macro="description-review-bib"/>+      </else-if>+      <else-if type="personal_communication">+        <text macro="description-letter-bib"/>+      </else-if>+      <else-if match="any" type="article-journal article-magazine article-newspaper periodical post-weblog review review-book">+        <text macro="description-serial-bib"/>+      </else-if>+      <else-if type="paper-conference">+        <text macro="description-paper-conference-bib"/>+      </else-if>+      <else-if type="song" variable="composer">+        <text macro="description-song-bib"/>+      </else-if>+      <!-- thesis type appears with university name (CMOS18 14.113) -->+      <else-if type="thesis"/>+      <else-if match="none" variable="container-title">+        <!-- Other description -->+        <text macro="description-format-bib"/>+      </else-if>+      <else>+        <text macro="description-generic-bib"/>+      </else>+    </choose>+  </macro>+  <macro name="description-short">+    <choose>+      <if match="any" type="interview" variable="interviewer">+        <text macro="description-interview-short"/>+      </if>+      <else-if match="any" type="review review-book" variable="reviewed-author reviewed-genre reviewed-title">+        <text macro="description-review-short"/>+      </else-if>+      <else-if type="personal_communication">+        <text macro="description-letter-short"/>+      </else-if>+      <else-if match="any" type="article-journal article-magazine article-newspaper periodical post-weblog review review-book">+        <text macro="description-serial-short"/>+      </else-if>+      <else-if type="paper-conference">+        <choose>+          <if match="any" variable="collection-editor container-author editor editorial-director">+            <!-- monographic usage -->+            <text macro="description-format-short"/>+          </if>+          <else>+            <!-- serial usage -->+            <text macro="description-serial-short"/>+          </else>+        </choose>+      </else-if>+      <else>+        <text macro="description-format-short"/>+      </else>+    </choose>+  </macro>+  <!-- Description elements -->+  <macro name="description-format-bib">+    <choose>+      <if variable="genre number"/>+      <else-if variable="genre">+        <text text-case="capitalize-first" variable="genre"/>+      </else-if>+      <else-if type="manuscript">+        <!-- 'unpublished manuscript' if no `genre` (CMOS18 14.114) -->+        <choose>+          <if match="none" variable="archive archive-place container-title DOI number publisher references URL">+            <text term="manuscript" text-case="capitalize-first"/>+          </if>+        </choose>+      </else-if>+      <else-if type="personal_communication">+        <!-- 'personal communication' if no `genre` (CMOS18 14.111) -->+        <choose>+          <if match="none" variable="archive archive-place container-title DOI number publisher references URL">+            <text term="personal-communication" text-case="capitalize-first"/>+          </if>+        </choose>+      </else-if>+    </choose>+  </macro>+  <macro name="description-format-short">+    <choose>+      <if variable="genre">+        <text variable="genre"/>+      </if>+      <else-if variable="medium">+        <text variable="medium"/>+      </else-if>+      <else-if type="manuscript">+        <!-- 'unpublished manuscript' if no `genre` (CMOS18 14.114) -->+        <choose>+          <if match="none" variable="archive archive-place container-title DOI number publisher references URL">+            <text term="manuscript"/>+          </if>+        </choose>+      </else-if>+      <else-if type="personal_communication">+        <!-- 'pers. comm.' if no `genre` (CMOS18 14.111) -->+        <choose>+          <if match="none" variable="archive archive-place container-title DOI number publisher references URL">+            <text form="short" term="personal-communication"/>+          </if>+        </choose>+      </else-if>+      <else-if variable="chapter-number">+        <text macro="label-chapter-number"/>+      </else-if>+    </choose>+  </macro>+  <macro name="description-generic-bib">+    <!-- For conference presentations/performances/events, chapters in reports/standards/generic documents, software, place description within the source element -->+    <choose>+      <if match="any" type="event paper-conference performance speech">+        <choose>+          <if match="any" variable="collection-editor compiler editor editorial-director">+            <!-- monographic usage -->+            <text macro="description-format-bib"/>+          </if>+        </choose>+      </if>+      <else-if match="none" type="document report software standard">+        <text macro="description-format-bib"/>+      </else-if>+    </choose>+  </macro>+  <macro name="description-interview-bib">+    <group delimiter=", ">+      <choose>+        <if variable="genre number">+          <!-- `genre` printed with `number` -->+          <names variable="interviewer">+            <label form="verb" suffix=" " text-case="capitalize-first"/>+            <name and="text"/>+          </names>+        </if>+        <else-if variable="genre">+          <group delimiter=" ">+            <text text-case="capitalize-first" variable="genre"/>+            <group delimiter=" ">+              <text form="verb" term="container-author"/>+              <names variable="interviewer"/>+            </group>+          </group>+        </else-if>+        <else-if variable="interviewer">+          <names variable="interviewer">+            <label form="verb" suffix=" " text-case="capitalize-first"/>+            <name and="text"/>+          </names>+        </else-if>+        <else>+          <text macro="description-format-bib"/>+        </else>+      </choose>+      <text macro="source-event-place-first"/>+    </group>+  </macro>+  <macro name="description-interview-short">+    <choose>+      <if disambiguate="true">+        <names variable="interviewer">+          <label form="verb" suffix=" "/>+          <name and="text"/>+          <substitute>+            <text macro="description-format-short"/>+          </substitute>+        </names>+      </if>+      <else-if match="any" variable="genre medium">+        <choose>+          <if match="none" variable="author chair collection-editor compiler composer curator director editor editor-translator editorial-director executive-producer guest host illustrator organizer producer series-creator translator">+            <!-- capitalize if no author or title -->+            <text macro="description-format-bib"/>+          </if>+          <else>+            <text macro="description-format-short"/>+          </else>+        </choose>+      </else-if>+      <else>+        <!-- generic description for an unpublished interview (CMOS18 14.108) -->+        <text term="interview"/>+      </else>+    </choose>+  </macro>+  <macro name="description-letter-bib">+    <choose>+      <if variable="recipient">+        <group delimiter=", ">+          <choose>+            <if variable="genre number">+              <!-- `genre` appears with `number` -->+              <names variable="recipient">+                <label form="verb" suffix=" " text-case="capitalize-first"/>+                <name and="text"/>+              </names>+            </if>+            <else-if variable="genre">+              <group delimiter=" ">+                <text macro="description-format-bib"/>+                <names variable="recipient">+                  <label form="verb" suffix=" "/>+                  <name and="text"/>+                </names>+              </group>+            </else-if>+            <else>+              <names variable="recipient">+                <label form="verb" suffix=" " text-case="capitalize-first"/>+                <name and="text"/>+              </names>+            </else>+          </choose>+          <text variable="event-place"/>+          <text macro="date-event-full"/>+        </group>+      </if>+      <else>+        <text macro="description-format-bib"/>+      </else>+    </choose>+  </macro>+  <macro name="description-letter-short">+    <!-- shortened notes ideally give author, recipient, place, and date (CMOS18 14.13) -->+    <group delimiter=", ">+      <choose>+        <if variable="genre recipient">+          <group delimiter=" ">+            <text macro="description-format-short"/>+            <names variable="recipient">+              <label form="verb" suffix=" "/>+              <name and="text"/>+            </names>+          </group>+        </if>+        <else>+          <text macro="description-format-short"/>+        </else>+      </choose>+      <text variable="event-place"/>+      <text macro="date-event-full"/>+    </group>+  </macro>+  <macro name="description-paper-conference-bib">+    <choose>+      <if match="any" variable="collection-editor container-author editor editorial-director">+        <!-- monographic usage -->+        <text macro="description-generic-bib"/>+      </if>+      <else>+        <!-- serial usage -->+        <group delimiter=". ">+          <text macro="description-serial-bib"/>+          <text macro="source-event-bib"/>+        </group>+      </else>+    </choose>+  </macro>+  <macro name="description-review-bib">+    <!-- Reviewed item -->+    <group delimiter=". ">+      <group delimiter=", ">+        <group delimiter=" ">+          <text macro="description-review-genre-bib"/>+          <text macro="description-review-title"/>+        </group>+        <choose>+          <if variable="reviewed-genre reviewed-title title">+            <names variable="reviewed-author">+              <label form="verb" suffix=" "/>+              <name and="text"/>+            </names>+          </if>+          <else-if variable="reviewed-genre"/>+          <else>+            <names variable="reviewed-author">+              <label form="verb" suffix=" "/>+              <name and="text"/>+            </names>+          </else>+        </choose>+        <text macro="source-event-place-first"/>+      </group>+      <text macro="label-section-capitalized"/>+    </group>+  </macro>+  <macro name="description-review-genre-bib">+    <choose>+      <if variable="reviewed-genre">+        <group delimiter=" ">+          <text macro="description-review-term-unsigned-bib"/>+          <text variable="reviewed-genre"/>+          <choose>+            <if match="none" variable="reviewed-title">+              <names variable="reviewed-author">+                <label form="verb" suffix=" "/>+                <name and="text"/>+              </names>+            </if>+          </choose>+        </group>+      </if>+      <else-if variable="number">+        <text macro="description-review-term-unsigned-bib"/>+      </else-if>+      <!-- If no `reviewed-genre`, assume that `genre` is entered as 'Review of the book' or similar -->+      <else-if variable="genre">+        <text text-case="capitalize-first" variable="genre"/>+      </else-if>+      <else>+        <text macro="description-review-term-unsigned-bib"/>+      </else>+    </choose>+  </macro>+  <macro name="description-review-short">+    <group delimiter=" ">+      <text term="review-of"/>+      <text macro="description-review-title-short"/>+    </group>+  </macro>+  <macro name="description-review-term-unsigned-bib">+    <!-- Anonymous reviews appear as 'unsigned' (CMOS18 14.102) -->+    <choose>+      <if match="any" variable="author chair collection-editor compiler composer curator director editor editor-translator editorial-director executive-producer guest host illustrator organizer producer series-creator translator">+        <text term="review-of" text-case="capitalize-first"/>+      </if>+      <else>+        <group delimiter=" ">+          <text term="anonymous" text-case="capitalize-first"/>+          <text term="review-of"/>+        </group>+      </else>+    </choose>+  </macro>+  <macro name="description-review-title">+    <choose>+      <if match="any" variable="reviewed-genre reviewed-title">+        <!-- Not possible to distinguish TV series episode from other reviewed works without a reviewed source title -->+        <!-- Adapt for `reviewed-container-title` or similar if it becomes available -->+        <text font-style="italic" text-case="title" variable="reviewed-title"/>+      </if>+      <else>+        <!-- Assume title is title of reviewed work -->+        <text font-style="italic" text-case="title" variable="title"/>+      </else>+    </choose>+  </macro>+  <macro name="description-review-title-short">+    <choose>+      <if match="any" variable="reviewed-genre reviewed-title">+        <!-- Not possible to distinguish TV series episode from other reviewed works without a reviewed source title -->+        <!-- Adapt for `reviewed-container-title` or similar if it becomes available -->+        <text font-style="italic" form="short" text-case="title" variable="reviewed-title"/>+      </if>+      <else>+        <!-- Assume title is title of reviewed work -->+        <text font-style="italic" form="short" text-case="title" variable="title"/>+      </else>+    </choose>+  </macro>+  <macro name="description-serial-bib">+    <group delimiter=". ">+      <text macro="description-format-bib"/>+      <!-- `section` provides magazine departments (CMOS18 14.88) and newspaper column names (CMOS18 14.93) -->+      <text macro="label-section-capitalized"/>+    </group>+  </macro>+  <macro name="description-serial-short">+    <choose>+      <if variable="title"/>+      <else-if variable="genre">+        <text macro="description-format-short"/>+      </else-if>+      <else>+        <text variable="section"/>+      </else>+    </choose>+  </macro>+  <macro name="description-song-bib">+    <!-- Performer of classical music works -->+    <!-- TODO: remove when Zotero fixes mapping of performer to `author` -->+    <group delimiter=" ">+      <!-- Based on `description-format` macro -->+      <choose>+        <if variable="genre">+          <text text-case="capitalize-first" variable="genre"/>+          <text form="verb" term="performer"/>+        </if>+        <!-- providing 'performed by' label for recorded readings (CMOS18 14.164), but it should be omitted for classical music (CMOS18 14.163) -->+        <else>+          <text form="verb" term="performer" text-case="capitalize-first"/>+        </else>+      </choose>+      <names variable="author">+        <substitute>+          <names variable="performer"/>+        </substitute>+      </names>+    </group>+  </macro>+  <!-- 3.3. Identifier (edition, contributors, volume) -->+  <macro name="identifier-bib">+    <group delimiter=". ">+      <choose>+        <if type="patent">+          <text macro="identifier-patent"/>+        </if>+        <else-if type="report">+          <text macro="identifier-report-bib"/>+        </else-if>+        <else-if match="any" type="post webpage">+          <!-- Handle `container-title` on `post` or `webpage` as `publisher` -->+          <text macro="identifier-number-bib"/>+          <text macro="label-version-capitalized"/>+          <text macro="identifier-edition-bib"/>+          <text macro="identifier-contributors-bib"/>+          <text macro="identifier-volume-monographic-bib"/>+        </else-if>+        <else-if variable="container-title">+          <choose>+            <if match="any" type="broadcast graphic map motion_picture">+              <!-- For audiovisual media, number information comes after `title`, not `container-title`; `song` places album catalogue `number` with `publisher` (CMOS18 14.163-164) -->+              <text macro="identifier-number-bib"/>+            </if>+          </choose>+          <text macro="identifier-contributors-bib"/>+        </else-if>+        <else>+          <choose>+            <if match="none" type="song">+              <text macro="identifier-number-bib"/>+            </if>+          </choose>+          <text macro="label-version-capitalized"/>+          <text macro="identifier-edition-bib"/>+          <choose>+            <if match="any" variable="part-title volume-title">+              <text macro="identifier-contributors-bib"/>+            </if>+            <else-if match="any" variable="number-of-volumes part-number volume">+              <!-- `collection-editor` belongs with `collection-title` if item is not multivolume -->+              <choose>+                <if variable="collection-editor">+                  <names variable="collection-editor">+                    <label form="verb" suffix=" " text-case="capitalize-first"/>+                    <name and="text"/>+                  </names>+                </if>+                <else>+                  <text macro="identifier-contributors-bib"/>+                </else>+              </choose>+            </else-if>+            <else>+              <text macro="identifier-contributors-bib"/>+            </else>+          </choose>+          <text macro="identifier-volume-monographic-bib"/>+          <choose>+            <!-- `collection-editor` supplied in `identifier-volume-monographic-bib` if there is a `part-title` or `volume-title` -->+            <if match="any" variable="part-title volume-title"/>+            <else-if match="any" variable="number-of-volumes part-number volume">+              <choose>+                <if variable="collection-editor">+                  <text macro="identifier-contributors-bib"/>+                </if>+              </choose>+            </else-if>+          </choose>+        </else>+      </choose>+    </group>+  </macro>+  <!-- Identifier elements -->+  <macro name="identifier-contributors-bib">+    <choose>+      <if match="any" type="article-journal article-magazine article-newspaper periodical post-weblog review review-book">+        <text macro="identifier-contributors-serial-bib"/>+      </if>+      <else-if match="any" type="interview paper-conference">+        <choose>+          <if match="any" variable="collection-editor compiler editor editorial-director">+            <!-- monographic usage -->+            <text macro="identifier-contributors-monographic-bib"/>+          </if>+          <else>+            <!-- serial usage -->+            <text macro="identifier-contributors-serial-bib"/>+          </else>+        </choose>+      </else-if>+      <else>+        <text macro="identifier-contributors-monographic-bib"/>+      </else>+    </choose>+  </macro>+  <macro name="identifier-contributors-monographic-bib">+    <group delimiter=". ">+      <choose>+        <if match="any" type="post webpage">+          <group delimiter=". ">+            <names variable="container-author">+              <label form="verb" suffix=" " text-case="capitalize-first"/>+              <name and="text"/>+            </names>+            <names variable="editor-translator">+              <label form="verb" suffix=" " text-case="capitalize-first"/>+              <name and="text"/>+            </names>+            <names delimiter=". " variable="editor translator">+              <label form="verb" suffix=" " text-case="capitalize-first"/>+              <name and="text"/>+            </names>+            <names variable="editorial-director">+              <label form="verb" suffix=" " text-case="capitalize-first"/>+              <name and="text"/>+            </names>+            <names variable="guest">+              <label form="verb" suffix=" " text-case="capitalize-first"/>+              <name and="text"/>+            </names>+            <names variable="host">+              <label form="verb" suffix=" " text-case="capitalize-first"/>+              <name and="text"/>+            </names>+            <names variable="illustrator">+              <label form="verb" suffix=" " text-case="capitalize-first"/>+              <name and="text"/>+            </names>+            <names variable="narrator">+              <label form="verb" suffix=" " text-case="capitalize-first"/>+              <name and="text"/>+            </names>+            <names delimiter=". " variable="compiler chair organizer curator">+              <label form="verb" suffix=" " text-case="capitalize-first"/>+              <name and="text"/>+            </names>+            <names delimiter=". " variable="series-creator executive-producer">+              <label form="verb" suffix=" " text-case="capitalize-first"/>+              <name and="text"/>+            </names>+            <names variable="producer">+              <label form="verb" suffix=" " text-case="capitalize-first"/>+              <name and="text"/>+            </names>+            <names variable="director">+              <label form="verb" suffix=" " text-case="capitalize-first"/>+              <name and="text"/>+            </names>+            <choose>+              <if match="any" type="broadcast performance">+                <names variable="script-writer">+                  <label form="verb" suffix=" " text-case="capitalize-first"/>+                  <name and="text"/>+                </names>+              </if>+            </choose>+            <names variable="performer">+              <label form="verb" suffix=" " text-case="capitalize-first"/>+              <name and="text"/>+            </names>+            <choose>+              <if match="none" type="thesis">+                <names variable="contributor">+                  <label form="verb" suffix=" " text-case="capitalize-first"/>+                  <name and="text"/>+                </names>+              </if>+            </choose>+          </group>+        </if>+        <else>+          <!-- Handle `container-title` on `post` or `webpage` as `publisher` -->+          <group delimiter=". ">+            <choose>+              <if match="none" variable="container-title">+                <names variable="container-author">+                  <label form="verb" suffix=" " text-case="capitalize-first"/>+                  <name and="text"/>+                </names>+                <names variable="editor-translator">+                  <label form="verb" suffix=" " text-case="capitalize-first"/>+                  <name and="text"/>+                </names>+                <names delimiter=". " variable="editor translator">+                  <label form="verb" suffix=" " text-case="capitalize-first"/>+                  <name and="text"/>+                </names>+                <names variable="editorial-director">+                  <label form="verb" suffix=" " text-case="capitalize-first"/>+                  <name and="text"/>+                </names>+                <names variable="guest">+                  <label form="verb" suffix=" " text-case="capitalize-first"/>+                  <name and="text"/>+                </names>+                <names variable="host">+                  <label form="verb" suffix=" " text-case="capitalize-first"/>+                  <name and="text"/>+                </names>+              </if>+            </choose>+            <names variable="illustrator">+              <label form="verb" suffix=" " text-case="capitalize-first"/>+              <name and="text"/>+            </names>+            <names variable="narrator">+              <label form="verb" suffix=" " text-case="capitalize-first"/>+              <name and="text"/>+            </names>+            <choose>+              <if match="none" variable="container-title">+                <names delimiter=". " variable="compiler chair organizer curator">+                  <label form="verb" suffix=" " text-case="capitalize-first"/>+                  <name and="text"/>+                </names>+                <names delimiter=". " variable="series-creator executive-producer">+                  <label form="verb" suffix=" " text-case="capitalize-first"/>+                  <name and="text"/>+                </names>+                <names variable="producer">+                  <label form="verb" suffix=" " text-case="capitalize-first"/>+                  <name and="text"/>+                </names>+                <names variable="director">+                  <label form="verb" suffix=" " text-case="capitalize-first"/>+                  <name and="text"/>+                </names>+                <choose>+                  <if match="any" type="broadcast performance">+                    <names variable="script-writer">+                      <label form="verb" suffix=" " text-case="capitalize-first"/>+                      <name and="text"/>+                    </names>+                  </if>+                </choose>+                <names variable="performer">+                  <label form="verb" suffix=" " text-case="capitalize-first"/>+                  <name and="text"/>+                </names>+                <choose>+                  <if match="none" type="song thesis">+                    <names variable="contributor">+                      <label form="verb" suffix=" " text-case="capitalize-first"/>+                      <name and="text"/>+                    </names>+                  </if>+                </choose>+              </if>+            </choose>+            <choose>+              <if type="song">+                <!-- Song contributors attached to album (CMOS18 14.163) -->+                <names variable="contributor">+                  <label form="verb" suffix=" " text-case="capitalize-first"/>+                  <name and="text"/>+                </names>+              </if>+            </choose>+          </group>+        </else>+      </choose>+    </group>+  </macro>+  <macro name="identifier-contributors-serial-bib">+    <group delimiter=". ">+      <names delimiter=". " variable="translator narrator">+        <label form="verb" suffix=" " text-case="capitalize-first"/>+        <name and="text"/>+      </names>+      <names delimiter=", " variable="compiler chair organizer curator">+        <label form="verb" suffix=" " text-case="capitalize-first"/>+        <name and="text"/>+      </names>+      <names delimiter=", " variable="series-creator executive-producer">+        <label form="verb" suffix=" " text-case="capitalize-first"/>+        <name and="text"/>+      </names>+      <names variable="producer">+        <label form="verb" suffix=" " text-case="capitalize-first"/>+        <name and="text"/>+      </names>+      <names variable="director">+        <label form="verb" suffix=" " text-case="capitalize-first"/>+        <name and="text"/>+      </names>+      <names variable="script-writer">+        <label form="verb" suffix=" " text-case="capitalize-first"/>+        <name and="text"/>+      </names>+      <names variable="performer">+        <label form="verb" suffix=" " text-case="capitalize-first"/>+        <name and="text"/>+      </names>+    </group>+  </macro>+  <macro name="identifier-edition-bib">+    <choose>+      <if match="none" variable="original-date">+        <text macro="label-edition-capitalized"/>+      </if>+      <else-if variable="original-title">+        <text macro="label-edition-capitalized"/>+      </else-if>+    </choose>+  </macro>+  <macro name="identifier-number-bib">+    <group delimiter=" ">+      <choose>+        <if is-numeric="number" type="broadcast" variable="genre">+          <text text-case="capitalize-first" variable="genre"/>+          <text variable="number"/>+        </if>+        <else-if is-numeric="number" type="broadcast">+          <text text-case="capitalize-first" value="episode"/>+          <text variable="number"/>+        </else-if>+        <else-if variable="number">+          <text text-case="title" variable="genre"/>+          <text macro="label-number-capitalized"/>+        </else-if>+      </choose>+    </group>+  </macro>+  <macro name="identifier-patent">+    <group delimiter=", ">+      <group delimiter=" ">+        <!-- `authority`: US ; `genre`: patent ; `number`: 123,445 -->+        <text form="short" variable="authority"/>+        <!-- 'US Patent' capitalized in both bibliography and note forms -->+        <choose>+          <if variable="genre">+            <text text-case="capitalize-first" variable="genre"/>+          </if>+          <else>+            <text term="patent" text-case="capitalize-first"/>+          </else>+        </choose>+        <text variable="number"/>+      </group>+      <group delimiter=" ">+        <text value="filed"/>+        <date form="text" variable="submitted"/>+      </group>+      <group delimiter=" ">+        <choose>+          <if variable="issued submitted">+            <text term="and"/>+          </if>+        </choose>+        <text value="issued"/>+        <!-- Always give full issue date, even in author-date (CMOS18 14.158) -->+        <text macro="date-issued-full"/>+      </group>+    </group>+  </macro>+  <macro name="identifier-report-bib">+    <group delimiter=". ">+      <choose>+        <if variable="container-title">+          <!-- If the report is a chapter in a larger report, then most identifying information is printed in the source. -->+          <text macro="identifier-contributors-bib"/>+        </if>+        <else-if variable="title">+          <text macro="identifier-number-bib"/>+          <text macro="label-version-capitalized"/>+          <text macro="identifier-edition-bib"/>+          <text macro="identifier-contributors-bib"/>+          <text macro="identifier-volume-monographic-bib"/>+        </else-if>+        <else>+          <!-- If there is no `title`, then `genre` and `number` are already printed as the title. -->+          <text macro="label-version-capitalized"/>+          <text macro="identifier-edition-bib"/>+          <text macro="identifier-contributors-bib"/>+          <text macro="identifier-volume-monographic-bib"/>+        </else>+      </choose>+    </group>+  </macro>+  <macro name="identifier-volume-bib">+    <!-- In notes styles, bibliography entries may be listed either under an individual volume title or its series, but the former approach is required for author-date, which is the form that this macro implements (CMOS18 14.21) -->+    <group delimiter=", ">+      <choose>+        <if variable="part-number part-title volume volume-title">+          <!-- part and title with individual titles -->+          <group delimiter=" ">+            <text macro="label-part-number-capitalized"/>+            <text value="of"/>+            <text font-style="italic" text-case="title" variable="volume-title"/>+          </group>+          <group delimiter=" ">+            <text macro="label-volume"/>+            <text value="of"/>+            <group delimiter=", ">+              <text macro="title-primary"/>+              <names variable="collection-editor">+                <label form="verb" suffix=" "/>+                <name and="text"/>+              </names>+            </group>+          </group>+        </if>+        <else-if match="any" variable="part-title volume-title">+          <group delimiter=" ">+            <choose>+              <if variable="part-number volume">+                <group delimiter=", ">+                  <text macro="label-volume-capitalized"/>+                  <text macro="label-part-number"/>+                  <text value="of"/>+                </group>+              </if>+              <else-if variable="part-number">+                <text macro="label-part-number-capitalized"/>+                <text value="of"/>+              </else-if>+              <else-if variable="volume">+                <text macro="label-volume-capitalized"/>+                <text value="of"/>+              </else-if>+            </choose>+            <group delimiter=", ">+              <text macro="title-primary"/>+              <names variable="collection-editor">+                <label form="verb" suffix=" "/>+                <name and="text"/>+              </names>+            </group>+          </group>+        </else-if>+        <else-if variable="part-number volume">+          <text macro="label-volume-capitalized"/>+          <text macro="label-part-number"/>+        </else-if>+        <else-if variable="part-number">+          <text macro="label-part-number-capitalized"/>+        </else-if>+        <else-if variable="volume">+          <text macro="label-volume-capitalized"/>+        </else-if>+        <else>+          <text macro="label-number-of-volumes"/>+        </else>+      </choose>+    </group>+  </macro>+  <macro name="identifier-volume-monographic-bib">+    <choose>+      <if match="any" type="article-journal article-magazine article-newspaper periodical post-weblog review review-book"/>+      <else-if match="any" type="interview paper-conference">+        <choose>+          <if match="any" variable="collection-editor compiler editor editorial-director">+            <!-- monographic usage -->+            <text macro="identifier-volume-bib"/>+          </if>+        </choose>+      </else-if>+      <else>+        <text macro="identifier-volume-bib"/>+      </else>+    </choose>+  </macro>+  <!-- 4. Source -->+  <macro name="source-bib">+    <choose>+      <if match="any" type="article-journal article-magazine article-newspaper periodical post-weblog review review-book">+        <!-- serial usage -->+        <text macro="source-serial-bib"/>+      </if>+      <else-if match="any" type="interview paper-conference">+        <choose>+          <if match="any" variable="collection-editor container-author editor editorial-director">+            <!-- monographic usage -->+            <text macro="source-monographic-bib"/>+          </if>+          <else>+            <!-- serial usage -->+            <text macro="source-serial-bib"/>+          </else>+        </choose>+      </else-if>+      <else-if match="any" type="patent post webpage"/>+      <else>+        <text macro="source-monographic-bib"/>+      </else>+    </choose>+  </macro>+  <!-- 4.1. Serial sources -->+  <macro name="source-serial-bib">+    <group delimiter=". ">+      <text macro="source-serial-title-volume-bib"/>+      <choose>+        <if type="article-newspaper">+          <group delimiter=", ">+            <text macro="source-serial-title-bib"/>+            <text macro="source-serial-identifier-bib"/>+          </group>+        </if>+        <else-if variable="collection-title volume">+          <group delimiter=", ">+            <text macro="source-serial-title-bib"/>+            <text macro="source-serial-identifier-bib"/>+          </group>+        </else-if>+        <else-if variable="volume">+          <group delimiter=" ">+            <text macro="source-serial-title-bib"/>+            <text macro="source-serial-identifier-bib"/>+          </group>+        </else-if>+        <else>+          <group delimiter=", ">+            <text macro="source-serial-title-bib"/>+            <text macro="source-serial-identifier-bib"/>+          </group>+        </else>+      </choose>+    </group>+  </macro>+  <!-- Serial source title -->+  <macro name="source-serial-name">+    <group delimiter=" ">+      <text font-style="italic" text-case="title" variable="container-title"/>+      <choose>+        <!-- TODO: remove conditional when Zotero stops double-mapping `event-place` and `publisher-place` -->+        <if match="none" variable="event-date event-title">+          <text prefix="(" suffix=")" variable="publisher-place"/>+        </if>+      </choose>+    </group>+  </macro>+  <macro name="source-serial-title-bib">+    <group delimiter=", ">+      <choose>+        <!-- Journal special issues (CMOS18 14.77) and supplements (CMOS18 14.78) -->+        <if match="none" variable="container-title"/>+        <else-if match="none" type="periodical" variable="supplement-number volume-title"/>+        <!-- TODO: use `container-genre` here once available to allow a custom description of the journal volume -->+        <else-if variable="supplement-number volume-title">+          <text term="supplement" text-case="capitalize-first"/>+        </else-if>+        <else-if type="periodical" variable="supplement-number title">+          <text term="supplement" text-case="capitalize-first"/>+        </else-if>+        <else-if variable="volume-title">+          <text term="special-issue" text-case="capitalize-first"/>+        </else-if>+        <else-if type="periodical" variable="title">+          <text term="special-issue" text-case="capitalize-first"/>+        </else-if>+      </choose>+      <text macro="source-serial-name"/>+      <choose>+        <!-- 'ahead of print' is placed akin to a series (CMOS18 14.75) -->+        <if match="any" variable="available-date collection-title issue number page status supplement-number volume"/>+        <else-if type="article-journal" variable="DOI issued">+          <text term="advance-online-publication"/>+        </else-if>+      </choose>+    </group>+  </macro>+  <macro name="source-serial-title-volume-bib">+    <choose>+      <if variable="volume-title">+        <!-- Journal special issues (CMOS18 14.77) and supplements (CMOS18 14.78) -->+        <group delimiter=", ">+          <group delimiter=" ">+            <text macro="source-monographic-preposition-bib"/>+            <text quotes="true" text-case="title" variable="volume-title"/>+          </group>+          <text macro="source-monographic-identifier-contributors-bib"/>+        </group>+      </if>+    </choose>+  </macro>+  <!-- Serial source identifier -->+  <macro name="source-serial-identifier-bib">+    <choose>+      <if match="any" variable="issue supplement-number volume">+        <group delimiter=": ">+          <text macro="source-serial-identifier-volume-author-date"/>+          <text macro="source-serial-locator"/>+        </group>+      </if>+      <else>+        <group delimiter=", ">+          <group delimiter=". ">+            <text macro="source-serial-identifier-volume-author-date"/>+            <!-- periodical edition always capitalized (CMOS18 14.89) -->+            <text macro="label-edition-capitalized"/>+          </group>+          <text macro="source-serial-locator"/>+        </group>+      </else>+      <!-- TODO: If CSL adds `date-part` detection, add two further conditions to address CMOS18 14.74: delimiting with ":" if there is a `volume` and no month or `issue` or `supplement number`; delimiting with ", " or there is an `issue` or `supplement number` and no month -->+    </choose>+  </macro>+  <macro name="source-serial-identifier-volume-author-date">+    <group delimiter=", ">+      <choose>+        <if type="article-newspaper">+          <!-- newspapers provide the full date in place of volume/issue numbers (CMOS18 14.89) -->+          <text variable="collection-title"/>+          <text macro="source-serial-volume-status-bib"/>+        </if>+        <else-if match="any" variable="issue supplement-number volume">+          <choose>+            <if match="any" type="article-magazine review review-book" variable="reviewed-author reviewed-genre reviewed-title">+              <!-- date appears first if the magazine or review `container-title` has been substituted for a missing author (CMOS18 14.87, 14.102) -->+              <choose>+                <if match="none" variable="author chair collection-editor compiler composer curator director editor editor-translator editorial-director executive-producer guest host illustrator organizer producer series-creator translator">+                  <choose>+                    <!-- no extra date details with a volume plus issue/supplement -->+                    <if variable="issue volume"/>+                    <else-if variable="supplement-number"/>+                    <!-- nothing to substitute if there is no issue/supplement/volume -->+                    <else-if match="none" variable="issue volume"/>+                    <else>+                      <text macro="source-date-bib"/>+                      <!-- for CMOS17 author-date: -->+                      <!-- <text macro="source-date-issued-month-day"/> -->+                    </else>+                  </choose>+                </if>+              </choose>+            </if>+          </choose>+          <!-- `collection-title` is for any serial with multiple series (e.g. '4th ser.') -->+          <text variable="collection-title"/>+          <group delimiter=" ">+            <choose>+              <if variable="volume">+                <choose>+                  <if variable="collection-title">+                    <text macro="label-volume"/>+                  </if>+                  <else-if match="any" type="article-magazine review review-book" variable="reviewed-author reviewed-genre reviewed-title">+                    <!-- provide label if a magazine or review `container-title` has been substituted for a missing author (CMOS18 14.87, 14.102) -->+                    <choose>+                      <if match="any" variable="author chair collection-editor compiler composer curator director editor editor-translator editorial-director executive-producer guest host illustrator organizer producer series-creator translator">+                        <text variable="volume"/>+                      </if>+                      <!-- TODO: when CSL provides date part detection, volume should be lowercase if there is a month, but otherwise capitalized -->+                      <else>+                        <text macro="label-volume-capitalized"/>+                      </else>+                    </choose>+                  </else-if>+                  <else>+                    <text variable="volume"/>+                  </else>+                </choose>+                <group delimiter=", " prefix="(" suffix=")">+                  <choose>+                    <if match="any" variable="issue supplement-number">+                      <text variable="issue"/>+                      <text macro="label-supplement-number"/>+                    </if>+                    <else-if match="any" type="article-magazine review review-book" variable="reviewed-author reviewed-genre reviewed-title">+                      <!-- date for anonymous magazine and review articles only appears here if it did not earlier (CMOS18 14.87, 14.102) -->+                      <choose>+                        <if match="any" variable="author chair collection-editor compiler composer curator director editor editor-translator editorial-director executive-producer guest host illustrator organizer producer series-creator translator">+                          <text macro="source-date-bib"/>+                          <!-- for CMOS17 author-date: -->+                          <!-- <text macro="source-date-issued-month-day"/> -->+                        </if>+                      </choose>+                    </else-if>+                    <else>+                      <text macro="source-date-bib"/>+                      <!-- for CMOS17 author-date: -->+                      <!-- <text macro="source-date-issued-month-day"/> -->+                    </else>+                  </choose>+                </group>+              </if>+              <else-if match="any" variable="issue supplement-number">+                <group delimiter=" ">+                  <group delimiter=", ">+                    <text macro="label-issue"/>+                    <text macro="label-supplement-number"/>+                  </group>+                  <choose>+                    <if match="any" variable="author chair collection-editor compiler composer curator director editor editor-translator editorial-director executive-producer guest host illustrator organizer producer series-creator translator">+                      <text macro="source-date-bib" prefix="(" suffix=")"/>+                      <!-- for CMOS17 author-date: -->+                      <!-- <text macro="source-date-issued-month-day" prefix="(" suffix=")"/> -->+                    </if>+                  </choose>+                </group>+              </else-if>+            </choose>+          </group>+        </else-if>+        <else>+          <text variable="collection-title"/>+          <choose>+            <if match="any" type="interview" variable="interviewer">+              <!-- publisher possible with `interview` (cf. CMOS18 14.110) -->+              <text variable="publisher"/>+            </if>+          </choose>+          <text macro="source-serial-volume-status-bib"/>+        </else>+      </choose>+    </group>+  </macro>+  <macro name="source-serial-volume-status-bib">+    <group delimiter=", ">+      <choose>+        <if match="none" variable="collection-title issue number page supplement-number volume">+          <group delimiter=" ">+            <!-- article accepted for publication and available on publisher website (CMOS18 14.75) -->+            <!-- TODO: use CSL term for `available-date` when available -->+            <text value="accepted"/>+            <date form="text" variable="available-date"/>+          </group>+        </if>+      </choose>+      <group delimiter=" ">+        <text macro="source-date-status-bib"/>+        <text macro="source-date-bib"/>+        <!-- for CMOS17 author-date: -->+        <!-- <text macro="source-date-issued-full-serial"/> -->+      </group>+    </group>+  </macro>+  <!-- Serial source locator -->+  <macro name="source-serial-locator">+    <choose>+      <if match="any" variable="locator number">+        <group delimiter=", ">+          <text macro="label-locator"/>+          <!-- an article ID appears alongside locators in notes (CMOS18 14.71) -->+          <text variable="number"/>+        </group>+      </if>+      <!-- do not give pages for newspapers (CMOS18 14.89) -->+      <else-if type="article-newspaper"/>+      <else>+        <text variable="page"/>+      </else>+    </choose>+  </macro>+  <!-- 4.2. Monographic sources -->+  <macro name="source-monographic-bib">+    <group delimiter=". ">+      <!-- Monographic sources repeat main reference elements -->+      <choose>+        <if variable="container-title">+          <group delimiter=", ">+            <group delimiter=" ">+              <choose>+                <if match="none" type="broadcast motion_picture">+                  <text macro="source-monographic-preposition-bib"/>+                </if>+              </choose>+              <text macro="source-monographic-title-bib"/>+            </group>+            <text macro="source-monographic-description-bib"/>+            <text macro="source-monographic-identifier-bib"/>+            <text macro="source-monographic-locator"/>+          </group>+        </if>+      </choose>+      <text macro="source-series-bib"/>+      <choose>+        <!-- show event information here only if not collapsed with `issued` (CMOS18 14.167) -->+        <if match="any" variable="event-date original-date original-publisher original-publisher-place publisher status">+          <text macro="source-event-bib"/>+        </if>+      </choose>+    </group>+  </macro>+  <!-- Monographic source title -->+  <macro name="source-monographic-preposition-bib">+    <choose>+      <if type="chapter" variable="container-title genre">+        <text value="to"/>+      </if>+      <else-if match="any" type="entry entry-dictionary entry-encyclopedia">+        <choose>+          <if match="any" variable="author composer">+            <!-- Give preposition only for signed entries; otherwise, title is substituted -->+            <text term="in" text-case="capitalize-first"/>+          </if>+        </choose>+      </else-if>+      <!-- if printing chapter page numbers (CMOS17/classic):+      <else-if variable="chapter-number page title"><text term="in" text-case="capitalize-first"/></else-if>+      -->+      <else-if variable="chapter-number">+        <group delimiter=" ">+          <text macro="label-chapter-number-capitalized"/>+          <choose>+            <if type="song">+              <text term="on"/>+            </if>+            <else>+              <text term="in"/>+            </else>+          </choose>+        </group>+      </else-if>+      <else>+        <text term="in" text-case="capitalize-first"/>+      </else>+    </choose>+  </macro>+  <macro name="source-monographic-title-bib">+    <choose>+      <if variable="part-title">+        <text macro="title-part"/>+      </if>+      <else-if variable="volume-title">+        <text font-style="italic" text-case="title" variable="volume-title"/>+      </else-if>+      <else>+        <text font-style="italic" text-case="title" variable="container-title"/>+      </else>+    </choose>+  </macro>+  <!-- Monographic source description -->+  <macro name="source-monographic-description-bib">+    <choose>+      <if match="any" type="event paper-conference performance speech">+        <!-- Conference presentations should describe the session unless published in a proceedings -->+        <choose>+          <if match="none" variable="collection-editor compiler editor editorial-director">+            <!-- serial usage -->+            <text macro="description-format-bib"/>+          </if>+        </choose>+      </if>+      <else-if type="software">+        <!-- For entries in mobile app reference works, place description after `container-title` -->+        <text macro="description-format-bib"/>+      </else-if>+      <else-if match="any" type="document report standard">+        <!-- For chapters in report, standards, and generic documents, place description after `container-title` -->+        <text macro="description-format-bib"/>+      </else-if>+    </choose>+  </macro>+  <!-- Monographic source identifier -->+  <macro name="source-monographic-identifier-bib">+    <!-- Based on `identifier-bib` -->+    <choose>+      <if variable="container-title">+        <group delimiter=", ">+          <choose>+            <if match="none" type="broadcast graphic map motion_picture song">+              <!-- For audiovisual media, number information comes after `title`, not `container-title`; `song` places album catalogue `number` with `publisher` (CMOS18 14.163-164) -->+              <text macro="identifier-number-bib"/>+            </if>+          </choose>+          <text macro="label-version"/>+          <text macro="label-edition"/>+          <choose>+            <if match="any" variable="part-title volume-title">+              <text macro="source-monographic-identifier-contributors-bib"/>+            </if>+            <else-if match="any" variable="number-of-volumes part-number volume">+              <!-- `collection-editor` belongs with `collection-title` if item is not multivolume -->+              <choose>+                <if variable="collection-editor">+                  <names variable="collection-editor">+                    <label form="verb" suffix=" "/>+                    <name and="text"/>+                  </names>+                </if>+                <else>+                  <text macro="source-monographic-identifier-contributors-bib"/>+                </else>+              </choose>+            </else-if>+            <else>+              <text macro="source-monographic-identifier-contributors-bib"/>+            </else>+          </choose>+          <text macro="source-monographic-identifier-volume-bib"/>+          <choose>+            <!-- `collection-editor` supplied in `source-monographic-identifier-volume-bib` if there is a `part-title` or `volume-title` -->+            <if match="any" variable="part-title volume-title"/>+            <else-if match="any" variable="number-of-volumes part-number volume">+              <choose>+                <if variable="collection-editor">+                  <text macro="source-monographic-identifier-contributors-bib"/>+                </if>+              </choose>+            </else-if>+          </choose>+        </group>+      </if>+    </choose>+  </macro>+  <macro name="source-monographic-identifier-contributors-bib">+    <group delimiter=", ">+      <names variable="container-author">+        <label form="verb" suffix=" "/>+        <name and="text"/>+      </names>+      <names variable="editor-translator">+        <label form="verb" suffix=" "/>+        <name and="text"/>+      </names>+      <names delimiter=", " variable="editor translator">+        <label form="verb" suffix=" "/>+        <name and="text"/>+      </names>+      <names variable="guest">+        <label form="verb" suffix=" "/>+        <name and="text"/>+      </names>+      <names variable="host">+        <label form="verb" suffix=" "/>+        <name and="text"/>+      </names>+      <names delimiter=", " variable="chair organizer">+        <label form="verb" suffix=" "/>+        <name and="text"/>+      </names>+      <names delimiter=", " variable="illustrator narrator compiler curator">+        <label form="verb" suffix=" "/>+        <name and="text"/>+      </names>+      <names delimiter=", " variable="series-creator executive-producer">+        <label form="verb" suffix=" "/>+        <name and="text"/>+      </names>+      <names variable="producer">+        <label form="verb" suffix=" "/>+        <name and="text"/>+      </names>+      <names variable="editorial-director">+        <label form="verb" suffix=" "/>+        <name and="text"/>+      </names>+      <choose>+        <if match="any" type="broadcast performance">+          <names variable="script-writer">+            <label form="verb" suffix=" "/>+            <name and="text"/>+          </names>+        </if>+      </choose>+      <names variable="director">+        <label form="verb" suffix=" "/>+        <name and="text"/>+      </names>+      <names variable="performer">+        <label form="verb" suffix=" "/>+        <name and="text"/>+      </names>+      <choose>+        <if match="none" type="song thesis">+          <!-- Song contributors attached to album (CMOS18 14.163) -->+          <names variable="contributor">+            <label form="verb" suffix=" "/>+            <name and="text"/>+          </names>+        </if>+      </choose>+    </group>+  </macro>+  <macro name="source-monographic-identifier-volume-bib">+    <!-- Mostly identical to `identifier-volume-bib` but without capitalization; giving `container-title` rather than `title-primary`; and ensuring volume number -->+    <group delimiter=", ">+      <choose>+        <if variable="part-number part-title volume volume-title">+          <!-- part and title with individual titles -->+          <group delimiter=" ">+            <text macro="label-part-number"/>+            <text value="of"/>+            <text font-style="italic" text-case="title" variable="volume-title"/>+          </group>+          <group delimiter=" ">+            <text macro="label-volume"/>+            <text value="of"/>+            <group delimiter=", ">+              <text font-style="italic" text-case="title" variable="container-title"/>+              <names variable="collection-editor">+                <label form="verb" suffix=" "/>+                <name and="text"/>+              </names>+            </group>+          </group>+        </if>+        <else-if match="any" variable="part-title volume-title">+          <group delimiter=" ">+            <choose>+              <if variable="part-number volume">+                <group delimiter=", ">+                  <text macro="label-volume"/>+                  <text macro="label-part-number"/>+                  <text value="of"/>+                </group>+              </if>+              <else-if variable="part-number">+                <text macro="label-part-number"/>+                <text value="of"/>+              </else-if>+              <else-if variable="volume">+                <text macro="label-volume"/>+                <text value="of"/>+              </else-if>+            </choose>+            <group delimiter=", ">+              <text font-style="italic" text-case="title" variable="container-title"/>+              <names variable="collection-editor">+                <label form="verb" suffix=" "/>+                <name and="text"/>+              </names>+            </group>+          </group>+        </else-if>+        <else-if match="any" variable="part-number volume">+          <choose>+            <if is-numeric="volume" match="none">+              <text macro="label-volume"/>+            </if>+            <else-if variable="container-title">+              <!-- remove condition in styles that print chapter page numbers (CMOS17/classic) -->+              <text macro="label-volume"/>+            </else-if>+            <else-if is-numeric="volume" variable="page">+              <choose>+                <!-- check for variables that might come between the volume and page number -->+                <if match="any" variable="collection-editor part-number part-title volume-title">+                  <text macro="label-volume"/>+                </if>+              </choose>+            </else-if>+            <else>+              <text macro="label-volume"/>+            </else>+          </choose>+          <text macro="label-part-number"/>+        </else-if>+        <else>+          <text macro="label-number-of-volumes"/>+        </else>+      </choose>+    </group>+  </macro>+  <!-- Monographic source locator -->+  <macro name="source-monographic-locator">+    <choose>+      <if is-numeric="volume" locator="page">+        <group delimiter=":">+          <choose>+            <if match="none" variable="collection-editor part-number part-title volume-title">+              <text variable="volume"/>+            </if>+          </choose>+          <text variable="locator"/>+        </group>+      </if>+      <else-if variable="locator">+        <text macro="label-locator"/>+      </else-if>+      <!-- remove `container-title` condition in styles that print chapter page numbers (CMOS17/classic) -->+      <else-if variable="container-title"/>+      <else-if is-numeric="volume" variable="page">+        <!-- collapse the volume and page number if adjacent -->+        <group delimiter=":">+          <choose>+            <!-- check for variables that might come between the volume and page number -->+            <if match="none" variable="collection-editor part-number part-title volume-title">+              <text variable="volume"/>+            </if>+          </choose>+          <text variable="page"/>+        </group>+      </else-if>+      <else>+        <text variable="page"/>+      </else>+    </choose>+  </macro>+  <!-- 4.3. Series -->+  <macro name="source-series-bib">+    <group delimiter=", ">+      <choose>+        <if variable="collection-editor collection-title">+          <choose>+            <if match="any" variable="number-of-volumes part-number part-title volume volume-title">+              <text macro="source-series-title"/>+            </if>+            <else>+              <text text-case="title" variable="collection-title"/>+              <names variable="collection-editor">+                <label form="verb" suffix=" "/>+                <name and="text"/>+              </names>+              <text macro="label-collection-number"/>+              <text macro="label-issue"/>+            </else>+          </choose>+        </if>+        <else>+          <text macro="source-series-title"/>+        </else>+      </choose>+    </group>+  </macro>+  <macro name="source-series-title">+    <group delimiter=", ">+      <choose>+        <if variable="issue">+          <text text-case="title" variable="collection-title"/>+          <text macro="label-collection-number"/>+          <text macro="label-issue"/>+        </if>+        <else-if is-numeric="collection-number" variable="collection-title">+          <group delimiter=" ">+            <text text-case="title" variable="collection-title"/>+            <text variable="collection-number"/>+          </group>+        </else-if>+        <else-if variable="collection-title">+          <text text-case="title" variable="collection-title"/>+          <text variable="collection-number"/>+        </else-if>+      </choose>+    </group>+  </macro>+  <!-- 4.4. Event -->+  <macro name="source-event-bib">+    <group delimiter=" ">+      <choose>+        <!-- omit types that provide event information in description  -->+        <if match="any" type="interview" variable="interviewer"/>+        <else-if type="personal_communication" variable="recipient"/>+        <else-if match="any" type="review review-book" variable="reviewed-author reviewed-genre reviewed-title"/>+        <else-if match="any" variable="event event-date event-title">+          <!-- TODO: To prevent Zotero from printing `event-place`, due to its double-mapping of `publisher-place` and `event-place`. Remove this when that is changed. -->+          <choose>+            <if type="paper-conference">+              <choose>+                <if match="none" variable="collection-editor compiler editor editorial-director issue page supplement-number volume">+                  <!-- Don't print event info for conference papers published in proceedings -->+                  <text macro="source-event-status-bib"/>+                  <text macro="source-event-description-bib"/>+                </if>+              </choose>+            </if>+            <else>+              <!-- For other item types, print event info even if published (e.g. collection catalogs, performance programs). -->+              <text macro="source-event-status-bib"/>+              <text macro="source-event-description-bib"/>+            </else>+          </choose>+        </else-if>+      </choose>+    </group>+  </macro>+  <macro name="source-event-place-first">+    <!-- for descriptive elements for interviews, reviews, letters -->+    <choose>+      <if match="any" variable="event event-date event-title">+        <group delimiter=", ">+          <text variable="event-title"/>+          <text variable="event-place"/>+          <text macro="date-event-full"/>+        </group>+      </if>+    </choose>+  </macro>+  <macro name="source-event-status-bib">+    <group delimiter=" ">+      <choose>+        <if type="broadcast" variable="status">+          <!-- 'aired', 'performed', etc. (CMOS18 14.165) -->+          <text text-case="capitalize-first" variable="status"/>+        </if>+        <else-if type="paper-conference">+          <choose>+            <if variable="genre">+              <text text-case="capitalize-first" value="presented"/>+            </if>+            <else>+              <text form="short" term="paper-conference" text-case="capitalize-first"/>+              <text value="presented"/>+            </else>+          </choose>+          <choose>+            <if variable="event-title">+              <text term="at"/>+            </if>+          </choose>+        </else-if>+        <else-if type="song">+          <text text-case="capitalize-first" value="recorded"/>+          <choose>+            <if variable="event-title">+              <text term="at"/>+            </if>+          </choose>+        </else-if>+        <else-if variable="event-date issued"/>+        <else-if match="none" variable="issued">+          <text text-case="capitalize-first" variable="status"/>+        </else-if>+      </choose>+    </group>+  </macro>+  <macro name="source-event-title">+    <choose>+      <!-- TODO: We expect `event-title` to be used, but processors and applications may not be updated yet. This macro ensures that either `event` or `event-title` can be accepted. Remove if processor logic and application adoption can handle this. -->+      <if variable="event-title">+        <text variable="event-title"/>+      </if>+      <else>+        <text variable="event"/>+      </else>+    </choose>+  </macro>+  <macro name="source-event-title-capitalized">+    <choose>+      <!-- TODO: We expect `event-title` to be used, but processors and applications may not be updated yet. This macro ensures that either `event` or `event-title` can be accepted. Remove if processor logic and application adoption can handle this. -->+      <if variable="event-title">+        <text text-case="capitalize-first" variable="event-title"/>+      </if>+      <else>+        <text text-case="capitalize-first" variable="event"/>+      </else>+    </choose>+  </macro>+  <macro name="source-event-description-bib">+    <group delimiter=", ">+      <choose>+        <if type="song">+          <text macro="source-event-title"/>+        </if>+        <else-if type="paper-conference" variable="genre">+          <text macro="source-event-title-capitalized"/>+        </else-if>+        <else-if type="paper-conference">+          <text macro="source-event-title"/>+        </else-if>+        <else>+          <text macro="source-event-title-capitalized"/>+        </else>+      </choose>+      <text macro="date-event-full"/>+      <text variable="event-place"/>+    </group>+  </macro>+  <!-- 4.5. Facts of publication -->+  <macro name="source-monographic-publication-bib">+    <group delimiter=". ">+      <choose>+        <!-- Provide only for monographic types -->+        <if match="any" type="article-journal article-magazine article-newspaper periodical post-weblog review review-book"/>+        <else-if match="any" type="interview paper-conference">+          <choose>+            <if match="any" variable="collection-editor container-author editor editorial-director">+              <!-- monographic usage -->+              <text macro="source-publication-and-date-bib"/>+            </if>+          </choose>+        </else-if>+        <!-- `patent` date in identification (CMOS18 14.158) -->+        <else-if type="patent"/>+        <else>+          <text macro="source-publication-and-date-bib"/>+        </else>+      </choose>+      <text macro="source-publication-original-title-bib"/>+    </group>+  </macro>+  <macro name="source-publication-and-date-bib">+    <group delimiter=", ">+      <choose>+        <if match="any" type="post webpage">+          <!-- `container-title` functions like a publisher with social media and website sources (CMOS18 14.104-106) -->+          <text text-case="title" variable="container-title"/>+        </if>+      </choose>+      <choose>+        <if type="broadcast" variable="DOI">+          <!-- a podcast publisher appears before the date, whereas the network of an aired show appears after (CMOS18 14.165); unfortunately CSL stores both in `publisher` -->+          <!-- TODO: `DOI` or `URL` detection is the only way to distinguish radio/TV from podcasts, but it is obviously imprecise; modify if CSL provides a `podcast` type -->+          <text macro="source-publication-history-bib"/>+        </if>+        <else-if type="broadcast" variable="URL">+          <text macro="source-publication-history-bib"/>+        </else-if>+        <else-if type="broadcast"/>+        <else>+          <text macro="source-publication-history-bib"/>+        </else>+      </choose>+      <group delimiter=" ">+        <text macro="source-date-status-bib"/>+        <text macro="source-date-bib"/>+      </group>+      <choose>+        <if type="broadcast" variable="URL"/>+        <else-if type="broadcast">+          <group delimiter=" ">+            <text term="on"/>+            <text macro="source-publication-history-bib"/>+          </group>+        </else-if>+      </choose>+    </group>+  </macro>+  <!-- Facts of publication elements -->+  <macro name="source-publication-description-bib">+    <choose>+      <if type="article" variable="genre"/>+      <else-if type="article">+        <!-- `preprint` term attached to repository name, but specific working paper descriptors appear in description (CMOS18 14.76, 14.116) -->+        <text term="preprint" text-case="capitalize-first"/>+      </else-if>+      <else-if type="thesis">+        <!-- thesis type appears with university name (CMOS18 14.113) -->+        <text macro="description-format-bib"/>+      </else-if>+      <else-if match="any" variable="original-publisher original-publisher-place">+        <choose>+          <!-- `edition` provides an alternative label to `reprint` (CMOS18 14.16) -->+          <if match="any" variable="edition original-title"/>+          <else-if match="none" type="book chapter classic entry entry-dictionary entry-encyclopedia interview musical_score pamphlet paper-conference report thesis"/>+          <else-if variable="issued original-date">+            <text text-case="capitalize-first" value="reprint"/>+          </else-if>+        </choose>+      </else-if>+    </choose>+  </macro>+  <macro name="source-publication-history-bib">+    <choose>+      <if variable="original-title">+        <!-- `original-title` is covered in `source-publication-original-title-bib` -->+        <group delimiter=", ">+          <text macro="source-publication-description-bib"/>+          <text macro="source-publication-publisher-bib"/>+        </group>+      </if>+      <else-if match="any" variable="edition original-publisher original-publisher-place">+        <group delimiter=". ">+          <!-- full stop to separate original date if `original-publisher` (CMOS18 14.16) -->+          <group delimiter=", ">+            <text macro="source-publication-publisher-original-bib"/>+            <text macro="source-date-original"/>+          </group>+          <group delimiter=". ">+            <choose>+              <if variable="issued original-date">+                <text macro="label-edition-capitalized"/>+              </if>+            </choose>+            <group delimiter=", ">+              <text macro="source-publication-description-bib"/>+              <text macro="source-publication-publisher-bib"/>+            </group>+          </group>+        </group>+      </else-if>+      <else>+        <group delimiter="; ">+          <!-- semicolon to separate original date if no publisher (CMOS18 14.165) -->+          <text macro="source-date-original"/>+          <group delimiter=", ">+            <text macro="source-publication-description-bib"/>+            <text macro="source-publication-publisher-bib"/>+          </group>+        </group>+      </else>+    </choose>+  </macro>+  <macro name="source-publication-original-title-bib">+    <!-- Work originally published under a different title (CMOS18 13.101) -->+    <choose>+      <if variable="original-title">+        <group delimiter=" ">+          <text term="original-work-published" text-case="capitalize-first"/>+          <group delimiter=", ">+            <names variable="original-author"/>+            <text font-style="italic" text-case="title" variable="original-title"/>+          </group>+          <group delimiter=", " prefix="(" suffix=")">+            <text macro="source-publication-publisher-original-bib"/>+            <text macro="source-date-original"/>+          </group>+        </group>+      </if>+    </choose>+  </macro>+  <macro name="source-publication-publisher-bib">+    <group delimiter=" ">+      <choose>+        <if type="thesis" variable="publisher">+          <text text-case="capitalize-first" variable="publisher"/>+        </if>+        <else-if variable="publisher">+          <group delimiter=": ">+            <!-- <text text-case="capitalize-first" variable="publisher-place"/> -->+            <text text-case="capitalize-first" variable="publisher"/>+          </group>+        </else-if>+        <!-- TODO: remove conditional when Zotero fixes double-mapping of `event-place` -->+        <else-if match="any" variable="event-date event-title"/>+        <else>+          <text text-case="capitalize-first" variable="publisher-place"/>+        </else>+      </choose>+      <choose>+        <if type="song">+          <!-- Album catalogue number follows label name (CMOS18 14.163-164) -->+          <text variable="number"/>+        </if>+      </choose>+    </group>+  </macro>+  <macro name="source-publication-publisher-original-bib">+    <choose>+      <if variable="original-publisher">+        <group delimiter=": ">+          <!-- <text text-case="capitalize-first" variable="original-publisher-place"/> -->+          <text text-case="capitalize-first" variable="original-publisher"/>+        </group>+      </if>+      <else>+        <text text-case="capitalize-first" variable="original-publisher-place"/>+      </else>+    </choose>+  </macro>+  <!-- 4.6. Date -->+  <macro name="source-date-bib">+    <!-- the date represents the last-mentioned title (CMOS18 14.21) -->+    <!-- there is no `source-date-note` as the date of a multivolume work is not used in note form -->+    <choose>+      <if variable="available-date volume-title">+        <!-- TODO: Is there a better CSL variable for a date of a multivolume work (CMOS18 14.21)? -->+        <date date-parts="year" form="text" variable="available-date"/>+      </if>+      <else-if variable="available-date part-title">+        <date date-parts="year" form="text" variable="available-date"/>+      </else-if>+      <else>+        <text macro="source-date-issued-month-day"/>+      </else>+    </choose>+  </macro>+  <!-- Date elements -->+  <macro name="source-date-issued-month-day">+    <!-- Variant for author-date styles -->+    <!-- Give full date for more ephemeral types -->+    <!-- NB: any changes must also be applied to `source-date-original-month-day` -->+    <choose>+      <if type="personal_communication" variable="event-date issued">+        <!-- Provide issue date for letters listed under event-date -->+        <text macro="date-issued-year"/>+      </if>+      <else-if match="any" type="article-journal article-magazine article-newspaper periodical post-weblog review review-book">+        <text macro="source-date-issued-month-day-serial"/>+      </else-if>+      <else-if match="any" type="interview paper-conference">+        <choose>+          <if match="none" variable="collection-editor compiler editor editorial-director">+            <!-- serial usage -->+            <text macro="source-date-issued-month-day-serial"/>+          </if>+        </choose>+      </else-if>+      <else-if match="any" type="entry entry-dictionary entry-encyclopedia">+        <choose>+          <if match="any" variable="DOI URL">+            <!-- Online reference works use full dates (CMOS18 14.131) -->+            <text macro="date-issued-month-day"/>+          </if>+        </choose>+      </else-if>+      <else-if match="any" type="article broadcast collection dataset document event graphic interview manuscript map patent performance personal_communication post software song speech standard webpage">+        <text macro="date-issued-month-day"/>+      </else-if>+    </choose>+  </macro>+  <macro name="source-date-issued-month-day-serial">+    <choose>+      <if type="article-newspaper">+        <!-- newspapers provide the full date in place of volume/issue numbers (CMOS18 14.89) -->+        <text macro="date-issued-month-day"/>+      </if>+      <else-if match="any" variable="issue supplement-number volume">+        <text macro="date-issued-month"/>+      </else-if>+      <else>+        <text macro="date-issued-month-day"/>+      </else>+    </choose>+  </macro>+  <macro name="source-date-original">+    <text macro="source-date-original-month-day"/>+  </macro>+  <macro name="source-date-original-month-day">+    <!-- Give full date for more ephemeral types -->+    <!-- Macro derived from `source-date-issued-month-day` -->+    <choose>+      <if type="personal_communication" variable="event-date original-date">+        <!-- Provide original date for letters listed under event-date -->+        <text macro="date-original-year"/>+      </if>+      <else-if match="any" type="article-journal article-magazine article-newspaper periodical post-weblog review review-book">+        <choose>+          <if match="any" variable="issue supplement-number volume">+            <text macro="date-original-month"/>+          </if>+          <else>+            <text macro="date-original-month-day"/>+          </else>+        </choose>+      </else-if>+      <else-if match="any" type="interview paper-conference">+        <choose>+          <if match="none" variable="collection-editor compiler editor editorial-director">+            <!-- serial usage -->+            <choose>+              <if match="any" variable="issue supplement-number volume">+                <text macro="date-original-month"/>+              </if>+              <else>+                <text macro="date-original-month-day"/>+              </else>+            </choose>+          </if>+        </choose>+      </else-if>+      <else-if match="any" type="entry entry-dictionary entry-encyclopedia">+        <choose>+          <if match="any" variable="DOI URL">+            <!-- Online reference works use full dates (CMOS18 14.131) -->+            <text macro="date-original-month-day"/>+          </if>+        </choose>+      </else-if>+      <else-if match="any" type="article broadcast collection dataset document event graphic interview manuscript map patent performance personal_communication post software song speech standard webpage">+        <text macro="date-original-month-day"/>+      </else-if>+    </choose>+  </macro>+  <macro name="source-date-status-bib">+    <choose>+      <if type="broadcast" variable="event-title issued status"/>+      <!-- on a `broadcast`, if there is an `event-title`, `status` appears with `event-date` as part of `source-event` (CMOS18 14.165) -->+      <else-if variable="issued status">+        <!-- `status` specifies date type, e.g. 'effective', 'last modified', 'approved' (CMOS18 14.104 for `webpage`; CMOS18 14.159 for `standard`) -->+        <choose>+          <if match="any" variable="original-date original-publisher original-publisher-place original-title publisher">+            <text variable="status"/>+          </if>+          <else>+            <text text-case="capitalize-first" variable="status"/>+          </else>+        </choose>+      </else-if>+      <else-if type="broadcast" variable="issued URL"/>+      <else-if type="broadcast" variable="issued">+        <!-- `status` of a radio or TV broadcast is 'aired' if unspecified (CMOS18 14.165) -->+        <text text-case="capitalize-first" value="aired"/>+      </else-if>+      <else-if type="software" variable="issued publisher">+        <!-- `status` of software is 'released' if unspecified (CMOS18 14.169) -->+        <choose>+          <if match="any" variable="author chair collection-editor compiler composer contributor curator director editor editor-translator editorial-director executive-producer guest host illustrator organizer producer series-creator translator">+            <!-- lowercase if `publisher` is adjacent -->+            <text value="released"/>+          </if>+          <else>+            <text text-case="capitalize-first" value="released"/>+          </else>+        </choose>+      </else-if>+      <else-if type="software" variable="original-date">+        <!-- lowercase if `original-date` is adjacent -->+        <text value="released"/>+      </else-if>+      <else-if type="software" variable="issued">+        <!-- capitalize if `publisher` is not present -->+        <text text-case="capitalize-first" value="released"/>+      </else-if>+    </choose>+  </macro>+  <!-- 4.7. Locator (including page references) -->+  <macro name="source-locator-author-date">+    <choose>+      <if match="any" type="entry entry-dictionary entry-encyclopedia">+        <choose>+          <if match="any" variable="author locator">+            <text macro="label-locator"/>+          </if>+          <else-if variable="container-title title">+            <!-- unsigned reference entry title appears in the locator (CMOS18 13.130) -->+            <group delimiter=" ">+              <choose>+                <if match="none" variable="DOI URL">+                  <!-- Only print reference entries use `sub-verbo` (CMOS18 14.131) -->+                  <text form="short" term="sub-verbo"/>+                </if>+              </choose>+              <text form="short" quotes="true" variable="title"/>+            </group>+          </else-if>+        </choose>+      </if>+      <else>+        <text macro="label-locator"/>+      </else>+    </choose>+  </macro>+  <!-- 4.8. Medium -->+  <macro name="source-medium-bib">+    <group delimiter=", ">+      <text text-case="capitalize-first" variable="medium"/>+      <text variable="scale"/>+      <text variable="dimensions"/>+    </group>+  </macro>+  <!-- 4.9. Archival location -->+  <macro name="source-archive-bib">+    <choose>+      <!-- With `archive_collection` or `archive-place`: physical archives -->+      <if type="graphic">+        <text macro="source-archive-name-first"/>+      </if>+      <else-if match="any" type="collection document manuscript personal_communication" variable="archive_collection archive-place">+        <text macro="source-archive-location-first-bib"/>+      </else-if>+      <!-- Without `archive_collection` or `archive-place`: digital archives (database and identifier) -->+      <else>+        <text macro="source-archive-identifier"/>+      </else>+    </choose>+  </macro>+  <macro name="source-archive-note">+    <choose>+      <!-- With `archive_collection` or `archive-place`: physical archives -->+      <if type="graphic">+        <text macro="source-archive-name-first"/>+      </if>+      <else-if match="any" type="collection document manuscript personal_communication" variable="archive_collection archive-place">+        <text macro="source-archive-location-first-note"/>+      </else-if>+      <!-- Without `archive_collection` or `archive-place`: digital archives (database and identifier) -->+      <else>+        <text macro="source-archive-identifier"/>+      </else>+    </choose>+  </macro>+  <!-- Archival elements -->+  <macro name="source-archive-identifier">+    <choose>+      <if variable="archive archive_location">+        <!-- database identifier: the only example is `thesis`, but presumably this is for all types (CMOS18 14.113) -->+        <group delimiter=" ">+          <text variable="archive"/>+          <text prefix="(" suffix=")" variable="archive_location"/>+        </group>+      </if>+      <else>+        <group delimiter=", ">+          <text variable="archive"/>+          <text variable="archive_location"/>+        </group>+      </else>+    </choose>+  </macro>+  <macro name="source-archive-location-first-bib">+    <!-- Order of elements begins with the most specific (CMOS18 14.119, 14.127) -->+    <!-- In note styles, the bibliography generally provide entries for a `collection` rather than individual items (CMOS18 14.120, 14.128) -->+    <group delimiter=". ">+      <group delimiter=", ">+        <text text-case="capitalize-first" variable="archive_location"/>+        <text variable="archive_collection"/>+      </group>+      <group delimiter=", ">+        <text variable="archive"/>+        <text variable="archive-place"/>+      </group>+    </group>+  </macro>+  <macro name="source-archive-location-first-note">+    <!-- Order of elements begins with the most specific (CMOS18 14.119, 14.127) -->+    <!-- In note styles, the bibliography generally provide entries for a `collection` rather than individual items (CMOS18 14.120, 14.128) -->+    <group delimiter=", ">+      <group delimiter=", ">+        <text variable="archive_location"/>+        <text variable="archive_collection"/>+      </group>+      <group delimiter=", ">+        <text variable="archive"/>+        <text variable="archive-place"/>+      </group>+    </group>+  </macro>+  <macro name="source-archive-name-first">+    <!-- Archive (gallery) name first for art (CMOS18 14.133) -->+    <group delimiter=", ">+      <text variable="archive"/>+      <text variable="archive-place"/>+      <text variable="archive_collection"/>+      <text variable="archive_location"/>+    </group>+  </macro>+  <!-- 4.10. URL or persistent identifier -->+  <macro name="source-date-accessed-DOI-URL-bib">+    <group delimiter=". ">+      <choose>+        <if variable="DOI"/>+        <else-if match="any" variable="available-date event-date issued status"/>+        <else-if variable="accessed URL">+          <group delimiter=" ">+            <text term="accessed" text-case="capitalize-first"/>+            <date form="text" variable="accessed"/>+          </group>+        </else-if>+      </choose>+      <text macro="source-DOI-URL"/>+    </group>+  </macro>+  <macro name="source-DOI-URL">+    <choose>+      <if variable="DOI">+        <text prefix="https://doi.org/" variable="DOI"/>+      </if>+      <else-if variable="URL">+        <text variable="URL"/>+      </else-if>+    </choose>+  </macro>+  <!-- 5. Notes -->+  <!-- TODO: add variables for distributor and exhibitions if available in CSL -->+  <!-- 6. Legal references: Bluebook style (shared with APA) -->+  <!-- Where APA or Chicago diverge from Bluebook, the official manual is followed -->+  <macro name="legal-reference">+    <!-- Type usage:++         `bill`+         : bills, resolutions, federal reports++         `legal_case`+         : all legal and court cases++         `hearing`+         : hearings and testimony++         `legislation`+         : statutes, constitutional items, and charters++         `regulation`+         : codified regulations, uncodified regulations, executive orders++         `treaty`+         : treaties+    -->+    <group delimiter=", ">+      <choose>+        <if type="treaty">+          <text macro="legal-title"/>+          <names variable="author">+            <!-- Treaty parties should be included at least for bilateral treaties (Bluebook 21.4.2) -->+            <name delimiter="-" et-al-min="100" et-al-use-first="99" form="short"/>+          </names>+          <text macro="legal-date"/>+          <!-- treaty source/report in addition to URL (Bluebook 21.4.5) -->+          <text macro="legal-source"/>+        </if>+        <else>+          <group delimiter=" ">+            <group delimiter=", ">+              <text macro="legal-title"/>+              <text macro="legal-source"/>+            </group>+            <text macro="legal-date"/>+            <text macro="legal-identifier"/>+          </group>+        </else>+      </choose>+      <group delimiter=" ">+        <!-- locator for use in notes -->+        <choose>+          <if locator="page" variable="page">+            <text term="at"/>+          </if>+        </choose>+        <text macro="label-locator"/>+      </group>+    </group>+  </macro>+  <!-- 6.1. Legal date -->+  <macro name="legal-date">+    <choose>+      <if type="treaty">+        <text macro="date-issued-full"/>+      </if>+      <else-if type="legal_case">+        <text macro="legal-date-case"/>+      </else-if>+      <else-if match="any" type="bill hearing legislation regulation">+        <group delimiter=" " prefix="(" suffix=")">+          <group delimiter=" ">+            <text macro="date-original-year"/>+            <text form="symbol" term="and"/>+          </group>+          <choose>+            <if variable="issued">+              <text macro="date-issued-year"/>+            </if>+            <else>+              <!-- Show proposal date for uncodified regulations. Assume date is entered literally ala "proposed May 23, 2016". -->+              <!-- TODO: Add `proposed` date here if that becomes available -->+              <date form="text" variable="submitted"/>+            </else>+          </choose>+        </group>+      </else-if>+    </choose>+  </macro>+  <macro name="legal-date-case">+    <group delimiter=" " prefix="(" suffix=")">+      <text variable="authority"/>+      <choose>+        <if variable="container-title">+          <!-- Print only year for cases published in reporters-->+          <text macro="date-issued-year"/>+        </if>+        <else>+          <text macro="date-issued-full"/>+        </else>+      </choose>+    </group>+  </macro>+  <!-- 6.2.1. Legal title -->+  <macro name="legal-title">+    <choose>+      <if match="any" type="bill legal_case legislation regulation treaty">+        <text text-case="title" variable="title"/>+      </if>+      <else-if type="hearing">+        <!-- use standard format (Bluebook 13.3) -->+        <group delimiter=": " font-style="italic">+          <text text-case="capitalize-first" variable="title"/>+          <group delimiter=" ">+            <text term="hearing" text-case="capitalize-first"/>+            <group delimiter=" ">+              <group delimiter=" ">+                <text term="on"/>+                <text variable="number"/>+              </group>+              <group delimiter=" ">+                <text value="before the"/>+                <text variable="section"/>+              </group>+            </group>+          </group>+        </group>+      </else-if>+    </choose>+  </macro>+  <!-- 6.2.2. Legal identifier -->+  <macro name="legal-identifier">+    <choose>+      <if type="hearing">+        <group delimiter=" " prefix="(" suffix=")">+          <!-- Use the 'verb' form of the hearing term to hold 'testimony of' -->+          <text form="verb" term="hearing"/>+          <names variable="author">+            <name and="symbol" initialize="false"/>+          </names>+        </group>+      </if>+      <else-if match="any" type="bill legislation regulation">+        <!-- For uncodified regulations, assume future code section is in `status`. -->+        <text prefix="(" suffix=")" variable="status"/>+      </else-if>+    </choose>+  </macro>+  <macro name="legal-identifier-bill-report">+    <group delimiter=" ">+      <text variable="genre"/>+      <choose>+        <if match="any" variable="authority chapter-number container-title">+          <text variable="number"/>+        </if>+        <else>+          <!-- If there is no legislative body, session number, or code/record title, assume the item is a congressional report and include 'No.' label. -->+          <text macro="label-number-capitalized"/>+        </else>+      </choose>+    </group>+  </macro>+  <!-- 6.3. Legal source -->+  <macro name="legal-source">+    <!-- Expect legal item `container-title` to be stored in short form -->+    <choose>+      <if type="bill">+        <text macro="legal-source-bill"/>+      </if>+      <else-if type="hearing">+        <text macro="legal-source-hearing"/>+      </else-if>+      <else-if type="legal_case">+        <text macro="legal-source-case"/>+      </else-if>+      <else-if type="legislation">+        <text macro="legal-source-legislation"/>+      </else-if>+      <else-if type="regulation">+        <text macro="legal-source-regulation"/>+      </else-if>+      <else-if type="treaty">+        <text macro="legal-source-treaty"/>+      </else-if>+    </choose>+  </macro>+  <!-- Legal source types -->+  <macro name="legal-source-bill">+    <group delimiter=", ">+      <text macro="legal-identifier-bill-report"/>+      <group delimiter=" ">+        <text variable="authority"/>+        <!-- `chapter-number` is a session number -->+        <text variable="chapter-number"/>+      </group>+      <group delimiter=" ">+        <text variable="volume"/>+        <text variable="container-title"/>+        <text variable="page-first"/>+      </group>+    </group>+  </macro>+  <macro name="legal-source-case">+    <group delimiter=" ">+      <choose>+        <if variable="container-title">+          <group delimiter=" ">+            <text variable="volume"/>+            <text variable="container-title"/>+            <text macro="label-section-symbol"/>+            <choose>+              <if match="any" variable="page page-first">+                <text variable="page-first"/>+              </if>+              <else>+                <text value="___"/>+              </else>+            </choose>+          </group>+        </if>+        <else>+          <text macro="label-number-capitalized"/>+        </else>+      </choose>+    </group>+  </macro>+  <macro name="legal-source-hearing">+    <group delimiter=" ">+      <text variable="authority"/>+      <!-- `chapter-number` is a session number -->+      <text variable="chapter-number"/>+    </group>+  </macro>+  <macro name="legal-source-legislation">+    <choose>+      <if variable="number">+        <!-- `number` is a public law number -->+        <group delimiter=", ">+          <group delimiter=" ">+            <choose>+              <if variable="genre">+                <text text-case="capitalize-first" variable="genre"/>+              </if>+              <else>+                <text form="short" term="legislation" text-case="capitalize-first"/>+              </else>+            </choose>+            <text macro="label-number-capitalized"/>+          </group>+          <group delimiter=" ">+            <text variable="volume"/>+            <text variable="container-title"/>+            <text variable="page-first"/>+          </group>+        </group>+      </if>+      <else>+        <group delimiter=" ">+          <text variable="volume"/>+          <text variable="container-title"/>+          <choose>+            <if variable="section">+              <text macro="label-section-symbol"/>+            </if>+            <else>+              <text variable="page-first"/>+            </else>+          </choose>+        </group>+      </else>+    </choose>+  </macro>+  <macro name="legal-source-regulation">+    <group delimiter=", ">+      <group delimiter=" ">+        <text variable="genre"/>+        <text macro="label-number-capitalized"/>+      </group>+      <group delimiter=" ">+        <text variable="volume"/>+        <text variable="container-title"/>+        <choose>+          <if variable="section">+            <text macro="label-section-symbol"/>+          </if>+          <else>+            <text variable="page-first"/>+          </else>+        </choose>+      </group>+    </group>+  </macro>+  <macro name="legal-source-treaty">+    <group delimiter=" ">+      <number variable="volume"/>+      <text variable="container-title"/>+      <choose>+        <if match="any" variable="page page-first">+          <text variable="page-first"/>+        </if>+        <else>+          <text macro="label-number-capitalized"/>+        </else>+      </choose>+    </group>+  </macro>+  <!-- Citation -->+  <macro name="citation-author-date-item">+    <group delimiter=", ">+      <choose>+        <if type="classic">+          <text macro="author-inline"/>+          <choose>+            <if variable="author">+              <text macro="title-and-descriptions-short"/>+            </if>+          </choose>+        </if>+        <else-if match="any" variable="event-date issued">+          <choose>+            <if match="any" type="interview personal_communication">+              <choose>+                <if match="any" variable="archive archive-place container-title DOI number publisher references URL">+                  <group delimiter=" ">+                    <text macro="author-inline"/>+                    <text macro="date-short"/>+                  </group>+                </if>+                <else>+                  <!-- unpublished `interview` or `personal_communication` use inline format (CMOS18 14.111) -->+                  <text macro="author-inline"/>+                  <text macro="title-and-descriptions-short"/>+                  <text macro="date-short"/>+                </else>+              </choose>+            </if>+            <else>+              <group delimiter=" ">+                <text macro="author-inline"/>+                <text macro="date-short"/>+              </group>+            </else>+          </choose>+        </else-if>+        <else>+          <!--- Comma with forthcoming or n.d. -->+          <text macro="author-inline"/>+          <choose>+            <if match="any" type="interview personal_communication">+              <choose>+                <if match="none" variable="archive archive-place container-title DOI number publisher references URL">+                  <!-- unpublished `interview` or `personal_communication` use inline format (CMOS18 14.111) -->+                  <text macro="title-and-descriptions-short"/>+                </if>+              </choose>+            </if>+          </choose>+          <text macro="date-short"/>+        </else>+      </choose>+    </group>+  </macro>+  <citation after-collapse-delimiter="; " collapse="year" disambiguate-add-givenname="true" disambiguate-add-names="true" disambiguate-add-year-suffix="true" et-al-min="3" et-al-use-first="1">+    <layout delimiter="; " prefix="(" suffix=")">+      <choose>+        <if type="classic">+          <!-- with `classic`, a non-numeric canonical reference or identifying number is separated by a space rather than a comma (CMOS18 14.145) -->+          <choose>+            <if is-numeric="locator">+              <group delimiter=", ">+                <text macro="citation-author-date-item"/>+                <text macro="source-locator-author-date"/>+              </group>+            </if>+            <else-if locator="chapter line verse" match="any">+              <group delimiter=" ">+                <text macro="citation-author-date-item"/>+                <text macro="source-locator-author-date"/>+              </group>+            </else-if>+            <else>+              <group delimiter=", ">+                <text macro="citation-author-date-item"/>+                <text macro="source-locator-author-date"/>+              </group>+            </else>+          </choose>+        </if>+        <else>+          <group delimiter=", ">+            <text macro="citation-author-date-item"/>+            <text macro="source-locator-author-date"/>+          </group>+        </else>+      </choose>+    </layout>+  </citation>+  <!-- Bibliography -->+  <macro name="bibliography-author-date">+    <group delimiter=". ">+      <choose>+        <if match="any" type="bill hearing legal_case legislation regulation treaty">+          <!-- Legal items have different orders and delimiters -->+          <text macro="legal-reference"/>+          <text macro="source-date-accessed-DOI-URL-bib"/>+          <text variable="references"/>+        </if>+        <else>+          <text macro="author-bib"/>+          <text macro="date"/>+          <text macro="title-and-source-bib"/>+          <text variable="references"/>+        </else>+      </choose>+    </group>+  </macro>+  <bibliography et-al-min="7" et-al-use-first="3" hanging-indent="true">+    <sort>+      <key macro="author-sort"/>+      <key macro="date-sort-group"/>+      <key macro="date-sort-year"/>+      <key macro="date"/>+      <key macro="title-and-descriptions-bib"/>+      <key macro="source-bib"/>+      <key variable="volume"/>+      <key variable="part-number"/>+      <key variable="event-date"/>+      <key variable="issued"/>+      <key macro="source-archive-bib"/>+    </sort>+    <layout suffix=".">+      <choose>+        <if type="classic">+          <choose>+            <if match="any" variable="archive editor translator publisher">+              <text macro="bibliography-author-date"/>+            </if>+          </choose>+        </if>+        <else-if match="any" type="entry entry-dictionary entry-encyclopedia">+          <choose>+            <if variable="author">+              <!-- Signed reference entries appear in the bibliography (CMOS18 14.132) -->+              <text macro="bibliography-author-date"/>+            </if>+            <else-if match="any" variable="DOI URL">+              <!-- Provide a bibliography if necessary identifying information is not in text -->+              <text macro="bibliography-author-date"/>+            </else-if>+          </choose>+        </else-if>+        <else-if match="any" type="interview personal_communication">+          <choose>+            <if match="any" variable="archive archive-place container-title DOI number publisher references URL">+              <!-- Personal communications only appear in the bibliography if the reader can retrieve them (CMOS18 14.13, 14.111) -->+              <text macro="bibliography-author-date"/>+            </if>+          </choose>+        </else-if>+        <else>+          <text macro="bibliography-author-date"/>+        </else>+      </choose>     </layout>   </bibliography> </style>
data/docx/word/document.xml view
@@ -15,9 +15,7 @@         <w:pStyle w:val="Title" />       </w:pPr>       <w:r>-        <w:t xml:space="preserve">-Title-</w:t>+        <w:t xml:space="preserve">Title</w:t>       </w:r>     </w:p>     <w:p>@@ -25,9 +23,7 @@         <w:pStyle w:val="Subtitle" />       </w:pPr>       <w:r>-        <w:t xml:space="preserve">-Subtitle-</w:t>+        <w:t xml:space="preserve">Subtitle</w:t>       </w:r>     </w:p>     <w:p>@@ -35,9 +31,7 @@         <w:pStyle w:val="Author" />       </w:pPr>       <w:r>-        <w:t xml:space="preserve">-Author-</w:t>+        <w:t xml:space="preserve">Author</w:t>       </w:r>     </w:p>     <w:p>@@ -45,9 +39,7 @@         <w:pStyle w:val="Date" />       </w:pPr>       <w:r>-        <w:t xml:space="preserve">-Date-</w:t>+        <w:t xml:space="preserve">Date</w:t>       </w:r>     </w:p>     <w:p>@@ -55,9 +47,7 @@         <w:pStyle w:val="Abstract" />       </w:pPr>       <w:r>-        <w:t xml:space="preserve">-Abstract-</w:t>+        <w:t xml:space="preserve">Abstract</w:t>       </w:r>     </w:p>     <w:p>@@ -66,9 +56,7 @@       </w:pPr>       <w:bookmarkStart w:id="21" w:name="heading-1" />       <w:r>-        <w:t xml:space="preserve">-Heading 1-</w:t>+        <w:t xml:space="preserve">Heading 1</w:t>       </w:r>       <w:bookmarkEnd w:id="21" />     </w:p>@@ -78,9 +66,7 @@       </w:pPr>       <w:bookmarkStart w:id="22" w:name="heading-2" />       <w:r>-        <w:t xml:space="preserve">-Heading 2-</w:t>+        <w:t xml:space="preserve">Heading 2</w:t>       </w:r>       <w:bookmarkEnd w:id="22" />     </w:p>@@ -90,9 +76,7 @@       </w:pPr>       <w:bookmarkStart w:id="23" w:name="heading-3" />       <w:r>-        <w:t xml:space="preserve">-Heading 3-</w:t>+        <w:t xml:space="preserve">Heading 3</w:t>       </w:r>       <w:bookmarkEnd w:id="23" />     </w:p>@@ -102,9 +86,7 @@       </w:pPr>       <w:bookmarkStart w:id="24" w:name="heading-4" />       <w:r>-        <w:t xml:space="preserve">-Heading 4-</w:t>+        <w:t xml:space="preserve">Heading 4</w:t>       </w:r>       <w:bookmarkEnd w:id="24" />     </w:p>@@ -114,9 +96,7 @@       </w:pPr>       <w:bookmarkStart w:id="25" w:name="heading-5" />       <w:r>-        <w:t xml:space="preserve">-Heading 5-</w:t>+        <w:t xml:space="preserve">Heading 5</w:t>       </w:r>       <w:bookmarkEnd w:id="25" />     </w:p>@@ -126,9 +106,7 @@       </w:pPr>       <w:bookmarkStart w:id="26" w:name="heading-6" />       <w:r>-        <w:t xml:space="preserve">-Heading 6-</w:t>+        <w:t xml:space="preserve">Heading 6</w:t>       </w:r>       <w:bookmarkEnd w:id="26" />     </w:p>@@ -138,9 +116,7 @@       </w:pPr>       <w:bookmarkStart w:id="27" w:name="heading-7" />       <w:r>-        <w:t xml:space="preserve">-Heading 7-</w:t>+        <w:t xml:space="preserve">Heading 7</w:t>       </w:r>       <w:bookmarkEnd w:id="27" />     </w:p>@@ -150,9 +126,7 @@       </w:pPr>       <w:bookmarkStart w:id="28" w:name="heading-8" />       <w:r>-        <w:t xml:space="preserve">-Heading 8-</w:t>+        <w:t xml:space="preserve">Heading 8</w:t>       </w:r>       <w:bookmarkEnd w:id="28" />     </w:p>@@ -162,9 +136,7 @@       </w:pPr>       <w:bookmarkStart w:id="29" w:name="heading-9" />       <w:r>-        <w:t xml:space="preserve">-Heading 9-</w:t>+        <w:t xml:space="preserve">Heading 9</w:t>       </w:r>       <w:bookmarkEnd w:id="29" />     </w:p>@@ -173,9 +145,7 @@         <w:pStyle w:val="FirstParagraph" />       </w:pPr>       <w:r>-        <w:t xml:space="preserve">-First Paragraph.-</w:t>+        <w:t xml:space="preserve">First Paragraph.</w:t>       </w:r>     </w:p>     <w:p>@@ -183,57 +153,39 @@         <w:pStyle w:val="BodyText" />       </w:pPr>       <w:r>-        <w:t xml:space="preserve">-Body Text. Body Text Char.-</w:t>+        <w:t xml:space="preserve">Body Text. Body Text Char.</w:t>       </w:r>       <w:r>-        <w:t xml:space="preserve">- -</w:t>+        <w:t xml:space="preserve"> </w:t>       </w:r>       <w:r>         <w:rPr>           <w:rStyle w:val="VerbatimChar" />         </w:rPr>-        <w:t xml:space="preserve">-Verbatim Char-</w:t>+        <w:t xml:space="preserve">Verbatim Char</w:t>       </w:r>       <w:r>-        <w:t xml:space="preserve">-.-</w:t>+        <w:t xml:space="preserve">.</w:t>       </w:r>       <w:r>-        <w:t xml:space="preserve">- -</w:t>+        <w:t xml:space="preserve"> </w:t>       </w:r>       <w:hyperlink r:id="rId30">         <w:r>           <w:rPr>             <w:rStyle w:val="Hyperlink" />           </w:rPr>-          <w:t xml:space="preserve">-Hyperlink-</w:t>+          <w:t xml:space="preserve">Hyperlink</w:t>         </w:r>       </w:hyperlink>       <w:r>-        <w:t xml:space="preserve">-.-</w:t>+        <w:t xml:space="preserve">.</w:t>       </w:r>       <w:r>-        <w:t xml:space="preserve">- -</w:t>+        <w:t xml:space="preserve"> </w:t>       </w:r>       <w:r>-        <w:t xml:space="preserve">-Footnote.-</w:t>+        <w:t xml:space="preserve">Footnote.</w:t>       </w:r>       <w:r>         <w:rPr>@@ -247,9 +199,7 @@         <w:pStyle w:val="BlockText" />       </w:pPr>       <w:r>-        <w:t xml:space="preserve">-Block Text.-</w:t>+        <w:t xml:space="preserve">Block Text.</w:t>       </w:r>     </w:p>     <w:p>@@ -257,9 +207,7 @@         <w:pStyle w:val="TableCaption" />       </w:pPr>       <w:r>-        <w:t xml:space="preserve">-Table caption.-</w:t>+        <w:t xml:space="preserve">Table caption.</w:t>       </w:r>     </w:p>     <w:tbl>@@ -286,9 +234,7 @@               <w:jc w:val="left" />             </w:pPr>             <w:r>-              <w:t xml:space="preserve">-Table-</w:t>+              <w:t xml:space="preserve">Table</w:t>             </w:r>           </w:p>         </w:tc>@@ -305,9 +251,7 @@               <w:jc w:val="left" />             </w:pPr>             <w:r>-              <w:t xml:space="preserve">-Table-</w:t>+              <w:t xml:space="preserve">Table</w:t>             </w:r>           </w:p>         </w:tc>@@ -320,9 +264,7 @@               <w:jc w:val="left" />             </w:pPr>             <w:r>-              <w:t xml:space="preserve">-1-</w:t>+              <w:t xml:space="preserve">1</w:t>             </w:r>           </w:p>         </w:tc>@@ -333,9 +275,7 @@               <w:jc w:val="left" />             </w:pPr>             <w:r>-              <w:t xml:space="preserve">-2-</w:t>+              <w:t xml:space="preserve">2</w:t>             </w:r>           </w:p>         </w:tc>@@ -346,9 +286,7 @@         <w:pStyle w:val="ImageCaption" />       </w:pPr>       <w:r>-        <w:t xml:space="preserve">-Image Caption-</w:t>+        <w:t xml:space="preserve">Image Caption</w:t>       </w:r>     </w:p>     <w:p>@@ -356,9 +294,7 @@         <w:pStyle w:val="DefinitionTerm" />       </w:pPr>       <w:r>-        <w:t xml:space="preserve">-DefinitionTerm-</w:t>+        <w:t xml:space="preserve">DefinitionTerm</w:t>       </w:r>     </w:p>     <w:p>@@ -366,9 +302,7 @@         <w:pStyle w:val="Definition" />       </w:pPr>       <w:r>-        <w:t xml:space="preserve">-Definition-</w:t>+        <w:t xml:space="preserve">Definition</w:t>       </w:r>     </w:p>     <w:p>@@ -376,9 +310,7 @@         <w:pStyle w:val="DefinitionTerm" />       </w:pPr>       <w:r>-        <w:t xml:space="preserve">-DefinitionTerm-</w:t>+        <w:t xml:space="preserve">DefinitionTerm</w:t>       </w:r>     </w:p>     <w:p>@@ -386,11 +318,13 @@         <w:pStyle w:val="Definition" />       </w:pPr>       <w:r>-        <w:t xml:space="preserve">-Definition-</w:t>+        <w:t xml:space="preserve">Definition</w:t>       </w:r>     </w:p>-    <w:sectPr />+    <w:sectPr>+      <w:footnotePr>+        <w:numRestart w:val="eachSect" />+      </w:footnotePr>+    </w:sectPr>   </w:body> </w:document>
data/docx/word/fontTable.xml view
@@ -1,52 +1,52 @@-<?xml version="1.0" encoding="UTF-8"?>+<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <w:fonts xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">-&#9;<w:font w:name="Symbol">-&#9;&#9;<w:panose1 w:val="02000500000000000000" />-&#9;&#9;<w:charset w:val="02" />-&#9;&#9;<w:family w:val="auto" />-&#9;&#9;<w:pitch w:val="variable" />-&#9;&#9;<w:sig w:usb0="00000000" w:usb1="00000000" w:usb2="00010000" w:usb3="00000000" w:csb0="80000000" w:csb1="00000000" />-&#9;</w:font>-&#9;<w:font w:name="Times New Roman">-&#9;&#9;<w:panose1 w:val="02020603050405020304" />-&#9;&#9;<w:charset w:val="00" />-&#9;&#9;<w:family w:val="auto" />-&#9;&#9;<w:pitch w:val="variable" />-&#9;&#9;<w:sig w:usb0="00000003" w:usb1="00000000" w:usb2="00000000" w:usb3="00000000" w:csb0="00000001" w:csb1="00000000" />-&#9;</w:font>-&#9;<w:font w:name="Courier New">-&#9;&#9;<w:panose1 w:val="02070309020205020404" />-&#9;&#9;<w:charset w:val="00" />-&#9;&#9;<w:family w:val="auto" />-&#9;&#9;<w:pitch w:val="variable" />-&#9;&#9;<w:sig w:usb0="00000003" w:usb1="00000000" w:usb2="00000000" w:usb3="00000000" w:csb0="00000001" w:csb1="00000000" />-&#9;</w:font>-&#9;<w:font w:name="Wingdings">-&#9;&#9;<w:panose1 w:val="05020102010804080708" />-&#9;&#9;<w:charset w:val="02" />-&#9;&#9;<w:family w:val="auto" />-&#9;&#9;<w:pitch w:val="variable" />-&#9;&#9;<w:sig w:usb0="00000000" w:usb1="00000000" w:usb2="00010000" w:usb3="00000000" w:csb0="80000000" w:csb1="00000000" />-&#9;</w:font>-&#9;<w:font w:name="Cambria">-&#9;&#9;<w:panose1 w:val="02040503050406030204" />-&#9;&#9;<w:charset w:val="00" />-&#9;&#9;<w:family w:val="auto" />-&#9;&#9;<w:pitch w:val="variable" />-&#9;&#9;<w:sig w:usb0="00000003" w:usb1="00000000" w:usb2="00000000" w:usb3="00000000" w:csb0="00000001" w:csb1="00000000" />-&#9;</w:font>-&#9;<w:font w:name="Calibri">-&#9;&#9;<w:panose1 w:val="020F0502020204030204" />-&#9;&#9;<w:charset w:val="00" />-&#9;&#9;<w:family w:val="auto" />-&#9;&#9;<w:pitch w:val="variable" />-&#9;&#9;<w:sig w:usb0="00000003" w:usb1="00000000" w:usb2="00000000" w:usb3="00000000" w:csb0="00000001" w:csb1="00000000" />-&#9;</w:font>-&#9;<w:font w:name="Arial">-&#9;&#9;<w:panose1 w:val="020B0604020202020204" />-&#9;&#9;<w:charset w:val="00" />-&#9;&#9;<w:family w:val="auto" />-&#9;&#9;<w:pitch w:val="variable" />-&#9;&#9;<w:sig w:usb0="00000003" w:usb1="00000000" w:usb2="00000000" w:usb3="00000000" w:csb0="00000001" w:csb1="00000000" />-&#9;</w:font>+  <w:font w:name="Aptos">+    <w:panose1 w:val="020B0004020202020204"/>+    <w:charset w:val="00"/>+    <w:family w:val="swiss"/>+    <w:pitch w:val="variable"/>+    <w:sig w:usb0="20000287" w:usb1="00000003" w:usb2="00000000" w:usb3="00000000" w:csb0="0000019F" w:csb1="00000000"/>+  </w:font>+  <w:font w:name="Times New Roman">+    <w:panose1 w:val="02020603050405020304"/>+    <w:charset w:val="00"/>+    <w:family w:val="roman"/>+    <w:pitch w:val="variable"/>+    <w:sig w:usb0="E0002EFF" w:usb1="C000785B" w:usb2="00000009" w:usb3="00000000" w:csb0="000001FF" w:csb1="00000000"/>+  </w:font>+  <w:font w:name="Aptos Display">+    <w:panose1 w:val="020B0004020202020204"/>+    <w:charset w:val="00"/>+    <w:family w:val="swiss"/>+    <w:pitch w:val="variable"/>+    <w:sig w:usb0="20000287" w:usb1="00000003" w:usb2="00000000" w:usb3="00000000" w:csb0="0000019F" w:csb1="00000000"/>+  </w:font>+  <w:font w:name="Cambria Math">+    <w:panose1 w:val="02040503050406030204"/>+    <w:charset w:val="00"/>+    <w:family w:val="roman"/>+    <w:pitch w:val="variable"/>+    <w:sig w:usb0="E00002FF" w:usb1="420024FF" w:usb2="00000000" w:usb3="00000000" w:csb0="0000019F" w:csb1="00000000"/>+  </w:font>+  <w:font w:name="Courier New">+    <w:panose1 w:val="02070309020205020404"/>+    <w:charset w:val="00"/>+    <w:family w:val="modern"/>+    <w:pitch w:val="fixed"/>+    <w:sig w:usb0="E0002AFF" w:usb1="C0007843" w:usb2="00000009" w:usb3="00000000" w:csb0="000001FF" w:csb1="00000000"/>+  </w:font>+  <w:font w:name="Cambria">+    <w:panose1 w:val="02040503050406030204"/>+    <w:charset w:val="00"/>+    <w:family w:val="roman"/>+    <w:pitch w:val="variable"/>+    <w:sig w:usb0="E00002FF" w:usb1="400004FF" w:usb2="00000000" w:usb3="00000000" w:csb0="0000019F" w:csb1="00000000"/>+  </w:font>+  <w:font w:name="Calibri">+    <w:panose1 w:val="020F0502020204030204"/>+    <w:charset w:val="00"/>+    <w:family w:val="swiss"/>+    <w:pitch w:val="variable"/>+    <w:sig w:usb0="E0002AFF" w:usb1="C000247B" w:usb2="00000009" w:usb3="00000000" w:csb0="000001FF" w:csb1="00000000"/>+  </w:font> </w:fonts>
data/docx/word/footnotes.xml view
@@ -1,7 +1,21 @@ <?xml version="1.0" encoding="UTF-8"?>-<w:footnotes xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"><w:footnote w:type="continuationSeparator" w:id="0"><w:p><w:r><w:continuationSeparator /></w:r></w:p></w:footnote><w:footnote w:type="separator" w:id="-1"><w:p><w:r><w:separator /></w:r></w:p></w:footnote><w:footnote w:id="31"><w:p><w:pPr><w:pStyle w:val="FootnoteText" /></w:pPr><w:r>-  <w:rPr>-    <w:rStyle w:val="FootnoteReference" />-  </w:rPr>-  <w:footnoteRef />-</w:r><w:r><w:t xml:space="preserve"> </w:t></w:r><w:r><w:t xml:space="preserve">Footnote Text.</w:t></w:r></w:p></w:footnote></w:footnotes>+<w:footnotes xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing">+  <w:footnote w:type="continuationSeparator" w:id="0"><w:p><w:r><w:continuationSeparator /></w:r></w:p></w:footnote>+  <w:footnote w:type="separator" w:id="-1"><w:p><w:r><w:separator /></w:r></w:p></w:footnote>+  <w:footnote w:id="31">+    <w:p>+      <w:pPr><w:pStyle w:val="FootnoteText" /></w:pPr>+      <w:r>+        <w:rPr>+          <w:rStyle w:val="FootnoteReference" />+        </w:rPr>+      <w:footnoteRef />+      </w:r>+      <w:r><w:t>Footnote Text.</w:t></w:r>+    </w:p>+    <w:p>+      <w:pPr><w:pStyle w:val="FootnoteBlockText"/></w:pPr>+      <w:r><w:t>Footnote Block Text</w:t></w:r>+    </w:p>+  </w:footnote>+</w:footnotes>
data/docx/word/styles.xml view
@@ -3,10 +3,10 @@   <w:docDefaults>     <w:rPrDefault>       <w:rPr>-        <w:rFonts w:asciiTheme="minorHAnsi" w:eastAsiaTheme="minorHAnsi" w:hAnsiTheme="minorHAnsi" w:cstheme="minorBidi" />+        <w:rFonts w:asciiTheme="minorHAnsi" w:eastAsiaTheme="minorEastAsia" w:hAnsiTheme="minorHAnsi" w:cstheme="minorBidi" />         <w:sz w:val="24" />         <w:szCs w:val="24" />-        <w:lang w:val="en-US" w:eastAsia="en-US" w:bidi="ar-SA" />+        <w:lang w:val="en-US" w:eastAsia="zh-CN" w:bidi="ar-SA" />       </w:rPr>     </w:rPrDefault>     <w:pPrDefault>@@ -20,7 +20,7 @@     <w:name w:val="Normal" />     <w:qFormat />   </w:style>-    <w:style w:type="paragraph" w:styleId="BodyText">+  <w:style w:type="paragraph" w:styleId="BodyText">     <w:name w:val="Body Text" />     <w:basedOn w:val="Normal" />     <w:link w:val="BodyTextChar" />@@ -47,57 +47,103 @@     <w:name w:val="Title" />     <w:basedOn w:val="Normal" />     <w:next w:val="BodyText" />+    <w:link w:val="TitleChar" />+    <w:uiPriority w:val="10" />     <w:qFormat />+    <w:rsid w:val="00A10FD9" />     <w:pPr>-      <w:keepNext />-      <w:keepLines />-      <w:spacing w:before="480" w:after="240" />+      <w:spacing w:after="80" w:line="240" w:lineRule="auto" />+      <w:contextualSpacing />       <w:jc w:val="center" />     </w:pPr>     <w:rPr>-      <w:rFonts w:asciiTheme="majorHAnsi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:cstheme="majorBidi" />-      <w:b />-      <w:bCs />-      <w:color w:val="345A8A" w:themeColor="accent1" w:themeShade="B5" />-      <w:sz w:val="36" />-      <w:szCs w:val="36" />+      <w:rFonts w:asciiTheme="majorHAnsi"+      w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi"+      w:cstheme="majorBidi" />+      <w:sz w:val="56" />+      <w:szCs w:val="56" />     </w:rPr>   </w:style>- <w:style w:type="paragraph" w:styleId="Subtitle">+  <w:style w:type="character" w:customStyle="1"+  w:styleId="TitleChar">+    <w:name w:val="Title Char" />+    <w:basedOn w:val="DefaultParagraphFont" />+    <w:link w:val="Title" />+    <w:uiPriority w:val="10" />+    <w:rsid w:val="00A10FD9" />+    <w:rPr>+      <w:rFonts w:asciiTheme="majorHAnsi"+      w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi"+      w:cstheme="majorBidi" />+      <w:sz w:val="56" />+      <w:szCs w:val="56" />+    </w:rPr>+  </w:style>+  <w:style w:type="paragraph" w:styleId="Subtitle">     <w:name w:val="Subtitle" />     <w:basedOn w:val="Title" />     <w:next w:val="BodyText" />+    <w:link w:val="SubtitleChar" />+    <w:uiPriority w:val="11" />     <w:qFormat />+    <w:rsid w:val="00A10FD9" />     <w:pPr>-      <w:keepNext />-      <w:keepLines />-      <w:spacing w:before="240" w:after="240" />-      <w:jc w:val="center" />+      <w:numPr>+        <w:ilvl w:val="1" />+      </w:numPr>     </w:pPr>     <w:rPr>-      <w:sz w:val="30" />-      <w:szCs w:val="30" />+      <w:rFonts w:eastAsiaTheme="majorEastAsia"+      w:cstheme="majorBidi" />+      <w:spacing w:val="15" />+      <w:sz w:val="28" />+      <w:szCs w:val="28" />     </w:rPr>- </w:style>+  </w:style>+  <w:style w:type="character" w:customStyle="1"+  w:styleId="SubtitleChar">+    <w:name w:val="Subtitle Char" />+    <w:basedOn w:val="DefaultParagraphFont" />+    <w:link w:val="Subtitle" />+    <w:uiPriority w:val="11" />+    <w:rsid w:val="00A10FD9" />+    <w:rPr>+      <w:rFonts w:eastAsiaTheme="majorEastAsia"+      w:cstheme="majorBidi" />+      <w:color w:val="595959" w:themeColor="text1"+      w:themeTint="A6" />+      <w:spacing w:val="15" />+      <w:sz w:val="28" />+      <w:szCs w:val="28" />+    </w:rPr>+  </w:style>   <w:style w:type="paragraph" w:customStyle="1" w:styleId="Author">     <w:name w:val="Author" />+    <w:basedOn w:val="Title" />     <w:next w:val="BodyText" />     <w:qFormat />     <w:pPr>       <w:keepNext />       <w:keepLines />-      <w:jc w:val="center" />     </w:pPr>+    <w:rPr>+      <w:sz w:val="24" />+      <w:szCs w:val="24" />+    </w:rPr>   </w:style>   <w:style w:type="paragraph" w:styleId="Date">     <w:name w:val="Date" />+    <w:basedOn w:val="Title" />     <w:next w:val="BodyText" />     <w:qFormat />     <w:pPr>       <w:keepNext />       <w:keepLines />-      <w:jc w:val="center" />     </w:pPr>+    <w:rPr>+      <w:sz w:val="24" />+      <w:szCs w:val="24" />+    </w:rPr>   </w:style>   <w:style w:type="paragraph" w:customStyle="1" w:styleId="AbstractTitle">     <w:name w:val="Abstract Title" />@@ -112,7 +158,6 @@     </w:pPr>     <w:rPr>       <w:b />-      <w:color w:val="345A8A" />       <w:sz w:val="20" />       <w:szCs w:val="20" />     </w:rPr>@@ -141,193 +186,371 @@     <w:rPr />   </w:style>   <w:style w:type="paragraph" w:styleId="Heading1">-    <w:name w:val="Heading 1" />+    <w:name w:val="heading 1" />     <w:basedOn w:val="Normal" />     <w:next w:val="BodyText" />+    <w:link w:val="Heading1Char" />     <w:uiPriority w:val="9" />     <w:qFormat />+    <w:rsid w:val="00A10FD9" />     <w:pPr>       <w:keepNext />       <w:keepLines />-      <w:spacing w:before="480" w:after="0" />+      <w:spacing w:before="360" w:after="80" />       <w:outlineLvl w:val="0" />     </w:pPr>     <w:rPr>-      <w:rFonts w:asciiTheme="majorHAnsi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:cstheme="majorBidi" />-      <w:b />-      <w:bCs />-      <w:color w:val="4F81BD" w:themeColor="accent1" />-      <w:sz w:val="32" />-      <w:szCs w:val="32" />+      <w:rFonts w:asciiTheme="majorHAnsi"+      w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi"+      w:cstheme="majorBidi" />+      <w:color w:val="0F4761" w:themeColor="accent1"+      w:themeShade="BF" />+      <w:sz w:val="40" />+      <w:szCs w:val="40" />     </w:rPr>   </w:style>   <w:style w:type="paragraph" w:styleId="Heading2">-    <w:name w:val="Heading 2" />+    <w:name w:val="heading 2" />     <w:basedOn w:val="Normal" />     <w:next w:val="BodyText" />+    <w:link w:val="Heading2Char" />     <w:uiPriority w:val="9" />+    <w:semiHidden />     <w:unhideWhenUsed />     <w:qFormat />+    <w:rsid w:val="00A10FD9" />     <w:pPr>       <w:keepNext />       <w:keepLines />-      <w:spacing w:before="200" w:after="0" />+      <w:spacing w:before="160" w:after="80" />       <w:outlineLvl w:val="1" />     </w:pPr>     <w:rPr>-      <w:rFonts w:asciiTheme="majorHAnsi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:cstheme="majorBidi" />-      <w:b />-      <w:bCs />-      <w:color w:val="4F81BD" w:themeColor="accent1" />-      <w:sz w:val="28" />-      <w:szCs w:val="28" />+      <w:rFonts w:asciiTheme="majorHAnsi"+      w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi"+      w:cstheme="majorBidi" />+      <w:color w:val="0F4761" w:themeColor="accent1"+      w:themeShade="BF" />+      <w:sz w:val="32" />+      <w:szCs w:val="32" />     </w:rPr>   </w:style>   <w:style w:type="paragraph" w:styleId="Heading3">-    <w:name w:val="Heading 3" />+    <w:name w:val="heading 3" />     <w:basedOn w:val="Normal" />     <w:next w:val="BodyText" />+    <w:link w:val="Heading3Char" />     <w:uiPriority w:val="9" />+    <w:semiHidden />     <w:unhideWhenUsed />     <w:qFormat />+    <w:rsid w:val="00A10FD9" />     <w:pPr>       <w:keepNext />       <w:keepLines />-      <w:spacing w:before="200" w:after="0" />+      <w:spacing w:before="160" w:after="80" />       <w:outlineLvl w:val="2" />     </w:pPr>     <w:rPr>-      <w:rFonts w:asciiTheme="majorHAnsi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:cstheme="majorBidi" />-      <w:b />-      <w:bCs />-      <w:color w:val="4F81BD" w:themeColor="accent1" />-      <w:sz w:val="24" />-      <w:szCs w:val="24" />+      <w:rFonts w:eastAsiaTheme="majorEastAsia"+      w:cstheme="majorBidi" />+      <w:color w:val="0F4761" w:themeColor="accent1"+      w:themeShade="BF" />+      <w:sz w:val="28" />+      <w:szCs w:val="28" />     </w:rPr>   </w:style>   <w:style w:type="paragraph" w:styleId="Heading4">-    <w:name w:val="Heading 4" />+    <w:name w:val="heading 4" />     <w:basedOn w:val="Normal" />     <w:next w:val="BodyText" />+    <w:link w:val="Heading4Char" />     <w:uiPriority w:val="9" />+    <w:semiHidden />     <w:unhideWhenUsed />     <w:qFormat />+    <w:rsid w:val="00A10FD9" />     <w:pPr>       <w:keepNext />       <w:keepLines />-      <w:spacing w:before="200" w:after="0" />+      <w:spacing w:before="80" w:after="40" />       <w:outlineLvl w:val="3" />     </w:pPr>     <w:rPr>-      <w:rFonts w:asciiTheme="majorHAnsi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:cstheme="majorBidi" />-      <w:bCs />+      <w:rFonts w:eastAsiaTheme="majorEastAsia"+      w:cstheme="majorBidi" />       <w:i />-      <w:color w:val="4F81BD" w:themeColor="accent1" />-      <w:sz w:val="24" />-      <w:szCs w:val="24" />+      <w:iCs />+      <w:color w:val="0F4761" w:themeColor="accent1"+      w:themeShade="BF" />     </w:rPr>   </w:style>   <w:style w:type="paragraph" w:styleId="Heading5">-    <w:name w:val="Heading 5" />+    <w:name w:val="heading 5" />     <w:basedOn w:val="Normal" />     <w:next w:val="BodyText" />+    <w:link w:val="Heading5Char" />     <w:uiPriority w:val="9" />+    <w:semiHidden />     <w:unhideWhenUsed />     <w:qFormat />+    <w:rsid w:val="00A10FD9" />     <w:pPr>       <w:keepNext />       <w:keepLines />-      <w:spacing w:before="200" w:after="0" />+      <w:spacing w:before="80" w:after="40" />       <w:outlineLvl w:val="4" />     </w:pPr>     <w:rPr>-      <w:rFonts w:asciiTheme="majorHAnsi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:cstheme="majorBidi" />-      <w:iCs />-      <w:color w:val="4F81BD" w:themeColor="accent1" />-      <w:sz w:val="24" />-      <w:szCs w:val="24" />+      <w:rFonts w:eastAsiaTheme="majorEastAsia"+      w:cstheme="majorBidi" />+      <w:color w:val="0F4761" w:themeColor="accent1"+      w:themeShade="BF" />     </w:rPr>   </w:style>   <w:style w:type="paragraph" w:styleId="Heading6">-    <w:name w:val="Heading 6" />+    <w:name w:val="heading 6" />     <w:basedOn w:val="Normal" />     <w:next w:val="BodyText" />+    <w:link w:val="Heading6Char" />     <w:uiPriority w:val="9" />+    <w:semiHidden />     <w:unhideWhenUsed />     <w:qFormat />+    <w:rsid w:val="00A10FD9" />     <w:pPr>       <w:keepNext />       <w:keepLines />-      <w:spacing w:before="200" w:after="0" />+      <w:spacing w:before="40" w:after="0" />       <w:outlineLvl w:val="5" />     </w:pPr>     <w:rPr>-      <w:rFonts w:asciiTheme="majorHAnsi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:cstheme="majorBidi" />-      <w:color w:val="4F81BD" w:themeColor="accent1" />-      <w:sz w:val="24" />-      <w:szCs w:val="24" />+      <w:rFonts w:eastAsiaTheme="majorEastAsia"+      w:cstheme="majorBidi" />+      <w:i />+      <w:iCs />+      <w:color w:val="595959" w:themeColor="text1"+      w:themeTint="A6" />     </w:rPr>   </w:style>   <w:style w:type="paragraph" w:styleId="Heading7">-    <w:name w:val="Heading 7" />+    <w:name w:val="heading 7" />     <w:basedOn w:val="Normal" />     <w:next w:val="BodyText" />+    <w:link w:val="Heading7Char" />     <w:uiPriority w:val="9" />+    <w:semiHidden />     <w:unhideWhenUsed />     <w:qFormat />+    <w:rsid w:val="00A10FD9" />     <w:pPr>       <w:keepNext />       <w:keepLines />-      <w:spacing w:before="200" w:after="0" />+      <w:spacing w:before="40" w:after="0" />       <w:outlineLvl w:val="6" />     </w:pPr>     <w:rPr>-      <w:rFonts w:asciiTheme="majorHAnsi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:cstheme="majorBidi" />-      <w:color w:val="4F81BD" w:themeColor="accent1" />-      <w:sz w:val="24" />-      <w:szCs w:val="24" />+      <w:rFonts w:eastAsiaTheme="majorEastAsia"+      w:cstheme="majorBidi" />+      <w:color w:val="595959" w:themeColor="text1"+      w:themeTint="A6" />     </w:rPr>   </w:style>   <w:style w:type="paragraph" w:styleId="Heading8">-    <w:name w:val="Heading 8" />+    <w:name w:val="heading 8" />     <w:basedOn w:val="Normal" />     <w:next w:val="BodyText" />+    <w:link w:val="Heading8Char" />     <w:uiPriority w:val="9" />+    <w:semiHidden />     <w:unhideWhenUsed />     <w:qFormat />+    <w:rsid w:val="00A10FD9" />     <w:pPr>       <w:keepNext />       <w:keepLines />-      <w:spacing w:before="200" w:after="0" />+      <w:spacing w:after="0" />       <w:outlineLvl w:val="7" />     </w:pPr>     <w:rPr>-      <w:rFonts w:asciiTheme="majorHAnsi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:cstheme="majorBidi" />-      <w:color w:val="4F81BD" w:themeColor="accent1" />-      <w:sz w:val="24" />-      <w:szCs w:val="24" />+      <w:rFonts w:eastAsiaTheme="majorEastAsia"+      w:cstheme="majorBidi" />+      <w:i />+      <w:iCs />+      <w:color w:val="272727" w:themeColor="text1"+      w:themeTint="D8" />     </w:rPr>   </w:style>   <w:style w:type="paragraph" w:styleId="Heading9">-    <w:name w:val="Heading 9" />+    <w:name w:val="heading 9" />     <w:basedOn w:val="Normal" />     <w:next w:val="BodyText" />+    <w:link w:val="Heading9Char" />     <w:uiPriority w:val="9" />+    <w:semiHidden />     <w:unhideWhenUsed />     <w:qFormat />+    <w:rsid w:val="00A10FD9" />     <w:pPr>       <w:keepNext />       <w:keepLines />-      <w:spacing w:before="200" w:after="0" />+      <w:spacing w:after="0" />       <w:outlineLvl w:val="8" />     </w:pPr>     <w:rPr>-      <w:rFonts w:asciiTheme="majorHAnsi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:cstheme="majorBidi" />-      <w:color w:val="4F81BD" w:themeColor="accent1" />-      <w:sz w:val="24" />-      <w:szCs w:val="24" />+      <w:rFonts w:eastAsiaTheme="majorEastAsia"+      w:cstheme="majorBidi" />+      <w:color w:val="272727" w:themeColor="text1"+      w:themeTint="D8" />     </w:rPr>   </w:style>+  <w:style w:type="character" w:customStyle="1" w:styleId="Heading1Char">+    <w:name w:val="Heading 1 Char" />+    <w:basedOn w:val="DefaultParagraphFont" />+    <w:link w:val="Heading1" />+    <w:uiPriority w:val="9" />+    <w:rsid w:val="00A10FD9" />+    <w:rPr>+      <w:rFonts w:asciiTheme="majorHAnsi"+      w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi"+      w:cstheme="majorBidi" />+      <w:color w:val="0F4761" w:themeColor="accent1"+      w:themeShade="BF" />+      <w:sz w:val="40" />+      <w:szCs w:val="40" />+    </w:rPr>+  </w:style>+  <w:style w:type="character" w:customStyle="1"+  w:styleId="Heading2Char">+    <w:name w:val="Heading 2 Char" />+    <w:basedOn w:val="DefaultParagraphFont" />+    <w:link w:val="Heading2" />+    <w:uiPriority w:val="9" />+    <w:semiHidden />+    <w:rsid w:val="00A10FD9" />+    <w:rPr>+      <w:rFonts w:asciiTheme="majorHAnsi"+      w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi"+      w:cstheme="majorBidi" />+      <w:color w:val="0F4761" w:themeColor="accent1"+      w:themeShade="BF" />+      <w:sz w:val="32" />+      <w:szCs w:val="32" />+    </w:rPr>+  </w:style>+  <w:style w:type="character" w:customStyle="1"+  w:styleId="Heading3Char">+    <w:name w:val="Heading 3 Char" />+    <w:basedOn w:val="DefaultParagraphFont" />+    <w:link w:val="Heading3" />+    <w:uiPriority w:val="9" />+    <w:semiHidden />+    <w:rsid w:val="00A10FD9" />+    <w:rPr>+      <w:rFonts w:eastAsiaTheme="majorEastAsia"+      w:cstheme="majorBidi" />+      <w:color w:val="0F4761" w:themeColor="accent1"+      w:themeShade="BF" />+      <w:sz w:val="28" />+      <w:szCs w:val="28" />+    </w:rPr>+  </w:style>+  <w:style w:type="character" w:customStyle="1"+  w:styleId="Heading4Char">+    <w:name w:val="Heading 4 Char" />+    <w:basedOn w:val="DefaultParagraphFont" />+    <w:link w:val="Heading4" />+    <w:uiPriority w:val="9" />+    <w:semiHidden />+    <w:rsid w:val="00A10FD9" />+    <w:rPr>+      <w:rFonts w:eastAsiaTheme="majorEastAsia"+      w:cstheme="majorBidi" />+      <w:i />+      <w:iCs />+      <w:color w:val="0F4761" w:themeColor="accent1"+      w:themeShade="BF" />+    </w:rPr>+  </w:style>+  <w:style w:type="character" w:customStyle="1"+  w:styleId="Heading5Char">+    <w:name w:val="Heading 5 Char" />+    <w:basedOn w:val="DefaultParagraphFont" />+    <w:link w:val="Heading5" />+    <w:uiPriority w:val="9" />+    <w:semiHidden />+    <w:rsid w:val="00A10FD9" />+    <w:rPr>+      <w:rFonts w:eastAsiaTheme="majorEastAsia"+      w:cstheme="majorBidi" />+      <w:color w:val="0F4761" w:themeColor="accent1"+      w:themeShade="BF" />+    </w:rPr>+  </w:style>+  <w:style w:type="character" w:customStyle="1"+  w:styleId="Heading6Char">+    <w:name w:val="Heading 6 Char" />+    <w:basedOn w:val="DefaultParagraphFont" />+    <w:link w:val="Heading6" />+    <w:uiPriority w:val="9" />+    <w:semiHidden />+    <w:rsid w:val="00A10FD9" />+    <w:rPr>+      <w:rFonts w:eastAsiaTheme="majorEastAsia"+      w:cstheme="majorBidi" />+      <w:i />+      <w:iCs />+      <w:color w:val="595959" w:themeColor="text1"+      w:themeTint="A6" />+    </w:rPr>+  </w:style>+  <w:style w:type="character" w:customStyle="1"+  w:styleId="Heading7Char">+    <w:name w:val="Heading 7 Char" />+    <w:basedOn w:val="DefaultParagraphFont" />+    <w:link w:val="Heading7" />+    <w:uiPriority w:val="9" />+    <w:semiHidden />+    <w:rsid w:val="00A10FD9" />+    <w:rPr>+      <w:rFonts w:eastAsiaTheme="majorEastAsia"+      w:cstheme="majorBidi" />+      <w:color w:val="595959" w:themeColor="text1"+      w:themeTint="A6" />+    </w:rPr>+  </w:style>+  <w:style w:type="character" w:customStyle="1"+  w:styleId="Heading8Char">+    <w:name w:val="Heading 8 Char" />+    <w:basedOn w:val="DefaultParagraphFont" />+    <w:link w:val="Heading8" />+    <w:uiPriority w:val="9" />+    <w:semiHidden />+    <w:rsid w:val="00A10FD9" />+    <w:rPr>+      <w:rFonts w:eastAsiaTheme="majorEastAsia"+      w:cstheme="majorBidi" />+      <w:i />+      <w:iCs />+      <w:color w:val="272727" w:themeColor="text1"+      w:themeTint="D8" />+    </w:rPr>+  </w:style>+  <w:style w:type="character" w:customStyle="1"+  w:styleId="Heading9Char">+    <w:name w:val="Heading 9 Char" />+    <w:basedOn w:val="DefaultParagraphFont" />+    <w:link w:val="Heading9" />+    <w:uiPriority w:val="9" />+    <w:semiHidden />+    <w:rsid w:val="00A10FD9" />+    <w:rPr>+      <w:rFonts w:eastAsiaTheme="majorEastAsia"+      w:cstheme="majorBidi" />+      <w:color w:val="272727" w:themeColor="text1"+      w:themeTint="D8" />+    </w:rPr>+  </w:style>   <w:style w:type="paragraph" w:styleId="BlockText">     <w:name w:val="Block Text" />     <w:basedOn w:val="BodyText" />@@ -350,8 +573,8 @@   </w:style>   <w:style w:type="paragraph" w:styleId="FootnoteBlockText">     <w:name w:val="Footnote Block Text" />-    <w:basedOn w:val="Footnote Text" />-    <w:next w:val="Footnote Text" />+    <w:basedOn w:val="FootnoteText" />+    <w:next w:val="FootnoteText" />     <w:uiPriority w:val="9" />     <w:unhideWhenUsed />     <w:qFormat />@@ -381,13 +604,6 @@       </w:tblCellMar>     </w:tblPr>     <w:tblStylePr w:type="firstRow">-      <w:tblPr>-        <w:jc w:val="left"/>-        <w:tblInd w:w="0" w:type="dxa"/>-      </w:tblPr>-      <w:trPr>-        <w:jc w:val="left"/>-      </w:trPr>       <w:tcPr>         <w:tcBorders>           <w:bottom w:val="single"/>
data/docx/word/theme/theme1.xml view
@@ -1,2 +1,293 @@-<?xml version="1.0" encoding="UTF-8"?>-<a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="Office Theme"><a:themeElements><a:clrScheme name="Office"><a:dk1><a:sysClr val="windowText" lastClr="000000" /></a:dk1><a:lt1><a:sysClr val="window" lastClr="FFFFFF" /></a:lt1><a:dk2><a:srgbClr val="1F497D" /></a:dk2><a:lt2><a:srgbClr val="EEECE1" /></a:lt2><a:accent1><a:srgbClr val="4F81BD" /></a:accent1><a:accent2><a:srgbClr val="C0504D" /></a:accent2><a:accent3><a:srgbClr val="9BBB59" /></a:accent3><a:accent4><a:srgbClr val="8064A2" /></a:accent4><a:accent5><a:srgbClr val="4BACC6" /></a:accent5><a:accent6><a:srgbClr val="F79646" /></a:accent6><a:hlink><a:srgbClr val="0000FF" /></a:hlink><a:folHlink><a:srgbClr val="800080" /></a:folHlink></a:clrScheme><a:fontScheme name="Office"><a:majorFont><a:latin typeface="Calibri" /><a:ea typeface="" /><a:cs typeface="" /><a:font script="Jpan" typeface="MS ゴシック" /><a:font script="Hang" typeface="맑은 고딕" /><a:font script="Hans" typeface="宋体" /><a:font script="Hant" typeface="新細明體" /><a:font script="Arab" typeface="Times New Roman" /><a:font script="Hebr" typeface="Times New Roman" /><a:font script="Thai" typeface="Angsana New" /><a:font script="Ethi" typeface="Nyala" /><a:font script="Beng" typeface="Vrinda" /><a:font script="Gujr" typeface="Shruti" /><a:font script="Khmr" typeface="MoolBoran" /><a:font script="Knda" typeface="Tunga" /><a:font script="Guru" typeface="Raavi" /><a:font script="Cans" typeface="Euphemia" /><a:font script="Cher" typeface="Plantagenet Cherokee" /><a:font script="Yiii" typeface="Microsoft Yi Baiti" /><a:font script="Tibt" typeface="Microsoft Himalaya" /><a:font script="Thaa" typeface="MV Boli" /><a:font script="Deva" typeface="Mangal" /><a:font script="Telu" typeface="Gautami" /><a:font script="Taml" typeface="Latha" /><a:font script="Syrc" typeface="Estrangelo Edessa" /><a:font script="Orya" typeface="Kalinga" /><a:font script="Mlym" typeface="Kartika" /><a:font script="Laoo" typeface="DokChampa" /><a:font script="Sinh" typeface="Iskoola Pota" /><a:font script="Mong" typeface="Mongolian Baiti" /><a:font script="Viet" typeface="Times New Roman" /><a:font script="Uigh" typeface="Microsoft Uighur" /></a:majorFont><a:minorFont><a:latin typeface="Cambria" /><a:ea typeface="" /><a:cs typeface="" /><a:font script="Jpan" typeface="MS 明朝" /><a:font script="Hang" typeface="맑은 고딕" /><a:font script="Hans" typeface="宋体" /><a:font script="Hant" typeface="新細明體" /><a:font script="Arab" typeface="Arial" /><a:font script="Hebr" typeface="Arial" /><a:font script="Thai" typeface="Cordia New" /><a:font script="Ethi" typeface="Nyala" /><a:font script="Beng" typeface="Vrinda" /><a:font script="Gujr" typeface="Shruti" /><a:font script="Khmr" typeface="DaunPenh" /><a:font script="Knda" typeface="Tunga" /><a:font script="Guru" typeface="Raavi" /><a:font script="Cans" typeface="Euphemia" /><a:font script="Cher" typeface="Plantagenet Cherokee" /><a:font script="Yiii" typeface="Microsoft Yi Baiti" /><a:font script="Tibt" typeface="Microsoft Himalaya" /><a:font script="Thaa" typeface="MV Boli" /><a:font script="Deva" typeface="Mangal" /><a:font script="Telu" typeface="Gautami" /><a:font script="Taml" typeface="Latha" /><a:font script="Syrc" typeface="Estrangelo Edessa" /><a:font script="Orya" typeface="Kalinga" /><a:font script="Mlym" typeface="Kartika" /><a:font script="Laoo" typeface="DokChampa" /><a:font script="Sinh" typeface="Iskoola Pota" /><a:font script="Mong" typeface="Mongolian Baiti" /><a:font script="Viet" typeface="Arial" /><a:font script="Uigh" typeface="Microsoft Uighur" /></a:minorFont></a:fontScheme><a:fmtScheme name="Office"><a:fillStyleLst><a:solidFill><a:schemeClr val="phClr" /></a:solidFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="50000" /><a:satMod val="300000" /></a:schemeClr></a:gs><a:gs pos="35000"><a:schemeClr val="phClr"><a:tint val="37000" /><a:satMod val="300000" /></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:tint val="15000" /><a:satMod val="350000" /></a:schemeClr></a:gs></a:gsLst><a:lin ang="16200000" scaled="1" /></a:gradFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="100000" /><a:shade val="100000" /><a:satMod val="130000" /></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:tint val="50000" /><a:shade val="100000" /><a:satMod val="350000" /></a:schemeClr></a:gs></a:gsLst><a:lin ang="16200000" scaled="0" /></a:gradFill></a:fillStyleLst><a:lnStyleLst><a:ln w="9525" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr"><a:shade val="95000" /><a:satMod val="105000" /></a:schemeClr></a:solidFill><a:prstDash val="solid" /></a:ln><a:ln w="25400" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr" /></a:solidFill><a:prstDash val="solid" /></a:ln><a:ln w="38100" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr" /></a:solidFill><a:prstDash val="solid" /></a:ln></a:lnStyleLst><a:effectStyleLst><a:effectStyle><a:effectLst><a:outerShdw blurRad="40000" dist="20000" dir="5400000" rotWithShape="0"><a:srgbClr val="000000"><a:alpha val="38000" /></a:srgbClr></a:outerShdw></a:effectLst></a:effectStyle><a:effectStyle><a:effectLst><a:outerShdw blurRad="40000" dist="23000" dir="5400000" rotWithShape="0"><a:srgbClr val="000000"><a:alpha val="35000" /></a:srgbClr></a:outerShdw></a:effectLst></a:effectStyle><a:effectStyle><a:effectLst><a:outerShdw blurRad="40000" dist="23000" dir="5400000" rotWithShape="0"><a:srgbClr val="000000"><a:alpha val="35000" /></a:srgbClr></a:outerShdw></a:effectLst><a:scene3d><a:camera prst="orthographicFront"><a:rot lat="0" lon="0" rev="0" /></a:camera><a:lightRig rig="threePt" dir="t"><a:rot lat="0" lon="0" rev="1200000" /></a:lightRig></a:scene3d><a:sp3d><a:bevelT w="63500" h="25400" /></a:sp3d></a:effectStyle></a:effectStyleLst><a:bgFillStyleLst><a:solidFill><a:schemeClr val="phClr" /></a:solidFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="40000" /><a:satMod val="350000" /></a:schemeClr></a:gs><a:gs pos="40000"><a:schemeClr val="phClr"><a:tint val="45000" /><a:shade val="99000" /><a:satMod val="350000" /></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:shade val="20000" /><a:satMod val="255000" /></a:schemeClr></a:gs></a:gsLst><a:path path="circle"><a:fillToRect l="50000" t="-80000" r="50000" b="180000" /></a:path></a:gradFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="80000" /><a:satMod val="300000" /></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:shade val="30000" /><a:satMod val="200000" /></a:schemeClr></a:gs></a:gsLst><a:path path="circle"><a:fillToRect l="50000" t="50000" r="50000" b="50000" /></a:path></a:gradFill></a:bgFillStyleLst></a:fmtScheme></a:themeElements><a:objectDefaults><a:spDef><a:spPr /><a:bodyPr /><a:lstStyle /><a:style><a:lnRef idx="1"><a:schemeClr val="accent1" /></a:lnRef><a:fillRef idx="3"><a:schemeClr val="accent1" /></a:fillRef><a:effectRef idx="2"><a:schemeClr val="accent1" /></a:effectRef><a:fontRef idx="minor"><a:schemeClr val="lt1" /></a:fontRef></a:style></a:spDef><a:lnDef><a:spPr /><a:bodyPr /><a:lstStyle /><a:style><a:lnRef idx="2"><a:schemeClr val="accent1" /></a:lnRef><a:fillRef idx="0"><a:schemeClr val="accent1" /></a:fillRef><a:effectRef idx="1"><a:schemeClr val="accent1" /></a:effectRef><a:fontRef idx="minor"><a:schemeClr val="tx1" /></a:fontRef></a:style></a:lnDef></a:objectDefaults><a:extraClrSchemeLst /></a:theme>+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>+<a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="Office Theme">+  <a:themeElements>+    <a:clrScheme name="Office">+      <a:dk1>+        <a:sysClr val="windowText" lastClr="000000"/>+      </a:dk1>+      <a:lt1>+        <a:sysClr val="window" lastClr="FFFFFF"/>+      </a:lt1>+      <a:dk2>+        <a:srgbClr val="0E2841"/>+      </a:dk2>+      <a:lt2>+        <a:srgbClr val="E8E8E8"/>+      </a:lt2>+      <a:accent1>+        <a:srgbClr val="156082"/>+      </a:accent1>+      <a:accent2>+        <a:srgbClr val="E97132"/>+      </a:accent2>+      <a:accent3>+        <a:srgbClr val="196B24"/>+      </a:accent3>+      <a:accent4>+        <a:srgbClr val="0F9ED5"/>+      </a:accent4>+      <a:accent5>+        <a:srgbClr val="A02B93"/>+      </a:accent5>+      <a:accent6>+        <a:srgbClr val="4EA72E"/>+      </a:accent6>+      <a:hlink>+        <a:srgbClr val="467886"/>+      </a:hlink>+      <a:folHlink>+        <a:srgbClr val="96607D"/>+      </a:folHlink>+    </a:clrScheme>+    <a:fontScheme name="Office">+      <a:majorFont>+        <a:latin typeface="Aptos Display" panose="02110004020202020204"/>+        <a:ea typeface=""/>+        <a:cs typeface=""/>+        <a:font script="Jpan" typeface="游ゴシック Light"/>+        <a:font script="Hang" typeface="맑은 고딕"/>+        <a:font script="Hans" typeface="等线 Light"/>+        <a:font script="Hant" typeface="新細明體"/>+        <a:font script="Arab" typeface="Times New Roman"/>+        <a:font script="Hebr" typeface="Times New Roman"/>+        <a:font script="Thai" typeface="Angsana New"/>+        <a:font script="Ethi" typeface="Nyala"/>+        <a:font script="Beng" typeface="Vrinda"/>+        <a:font script="Gujr" typeface="Shruti"/>+        <a:font script="Khmr" typeface="MoolBoran"/>+        <a:font script="Knda" typeface="Tunga"/>+        <a:font script="Guru" typeface="Raavi"/>+        <a:font script="Cans" typeface="Euphemia"/>+        <a:font script="Cher" typeface="Plantagenet Cherokee"/>+        <a:font script="Yiii" typeface="Microsoft Yi Baiti"/>+        <a:font script="Tibt" typeface="Microsoft Himalaya"/>+        <a:font script="Thaa" typeface="MV Boli"/>+        <a:font script="Deva" typeface="Mangal"/>+        <a:font script="Telu" typeface="Gautami"/>+        <a:font script="Taml" typeface="Latha"/>+        <a:font script="Syrc" typeface="Estrangelo Edessa"/>+        <a:font script="Orya" typeface="Kalinga"/>+        <a:font script="Mlym" typeface="Kartika"/>+        <a:font script="Laoo" typeface="DokChampa"/>+        <a:font script="Sinh" typeface="Iskoola Pota"/>+        <a:font script="Mong" typeface="Mongolian Baiti"/>+        <a:font script="Viet" typeface="Times New Roman"/>+        <a:font script="Uigh" typeface="Microsoft Uighur"/>+        <a:font script="Geor" typeface="Sylfaen"/>+        <a:font script="Armn" typeface="Arial"/>+        <a:font script="Bugi" typeface="Leelawadee UI"/>+        <a:font script="Bopo" typeface="Microsoft JhengHei"/>+        <a:font script="Java" typeface="Javanese Text"/>+        <a:font script="Lisu" typeface="Segoe UI"/>+        <a:font script="Mymr" typeface="Myanmar Text"/>+        <a:font script="Nkoo" typeface="Ebrima"/>+        <a:font script="Olck" typeface="Nirmala UI"/>+        <a:font script="Osma" typeface="Ebrima"/>+        <a:font script="Phag" typeface="Phagspa"/>+        <a:font script="Syrn" typeface="Estrangelo Edessa"/>+        <a:font script="Syrj" typeface="Estrangelo Edessa"/>+        <a:font script="Syre" typeface="Estrangelo Edessa"/>+        <a:font script="Sora" typeface="Nirmala UI"/>+        <a:font script="Tale" typeface="Microsoft Tai Le"/>+        <a:font script="Talu" typeface="Microsoft New Tai Lue"/>+        <a:font script="Tfng" typeface="Ebrima"/>+      </a:majorFont>+      <a:minorFont>+        <a:latin typeface="Aptos" panose="02110004020202020204"/>+        <a:ea typeface=""/>+        <a:cs typeface=""/>+        <a:font script="Jpan" typeface="游明朝"/>+        <a:font script="Hang" typeface="맑은 고딕"/>+        <a:font script="Hans" typeface="等线"/>+        <a:font script="Hant" typeface="新細明體"/>+        <a:font script="Arab" typeface="Arial"/>+        <a:font script="Hebr" typeface="Arial"/>+        <a:font script="Thai" typeface="Cordia New"/>+        <a:font script="Ethi" typeface="Nyala"/>+        <a:font script="Beng" typeface="Vrinda"/>+        <a:font script="Gujr" typeface="Shruti"/>+        <a:font script="Khmr" typeface="DaunPenh"/>+        <a:font script="Knda" typeface="Tunga"/>+        <a:font script="Guru" typeface="Raavi"/>+        <a:font script="Cans" typeface="Euphemia"/>+        <a:font script="Cher" typeface="Plantagenet Cherokee"/>+        <a:font script="Yiii" typeface="Microsoft Yi Baiti"/>+        <a:font script="Tibt" typeface="Microsoft Himalaya"/>+        <a:font script="Thaa" typeface="MV Boli"/>+        <a:font script="Deva" typeface="Mangal"/>+        <a:font script="Telu" typeface="Gautami"/>+        <a:font script="Taml" typeface="Latha"/>+        <a:font script="Syrc" typeface="Estrangelo Edessa"/>+        <a:font script="Orya" typeface="Kalinga"/>+        <a:font script="Mlym" typeface="Kartika"/>+        <a:font script="Laoo" typeface="DokChampa"/>+        <a:font script="Sinh" typeface="Iskoola Pota"/>+        <a:font script="Mong" typeface="Mongolian Baiti"/>+        <a:font script="Viet" typeface="Arial"/>+        <a:font script="Uigh" typeface="Microsoft Uighur"/>+        <a:font script="Geor" typeface="Sylfaen"/>+        <a:font script="Armn" typeface="Arial"/>+        <a:font script="Bugi" typeface="Leelawadee UI"/>+        <a:font script="Bopo" typeface="Microsoft JhengHei"/>+        <a:font script="Java" typeface="Javanese Text"/>+        <a:font script="Lisu" typeface="Segoe UI"/>+        <a:font script="Mymr" typeface="Myanmar Text"/>+        <a:font script="Nkoo" typeface="Ebrima"/>+        <a:font script="Olck" typeface="Nirmala UI"/>+        <a:font script="Osma" typeface="Ebrima"/>+        <a:font script="Phag" typeface="Phagspa"/>+        <a:font script="Syrn" typeface="Estrangelo Edessa"/>+        <a:font script="Syrj" typeface="Estrangelo Edessa"/>+        <a:font script="Syre" typeface="Estrangelo Edessa"/>+        <a:font script="Sora" typeface="Nirmala UI"/>+        <a:font script="Tale" typeface="Microsoft Tai Le"/>+        <a:font script="Talu" typeface="Microsoft New Tai Lue"/>+        <a:font script="Tfng" typeface="Ebrima"/>+      </a:minorFont>+    </a:fontScheme>+    <a:fmtScheme name="Office">+      <a:fillStyleLst>+        <a:solidFill>+          <a:schemeClr val="phClr"/>+        </a:solidFill>+        <a:gradFill rotWithShape="1">+          <a:gsLst>+            <a:gs pos="0">+              <a:schemeClr val="phClr">+                <a:lumMod val="110000"/>+                <a:satMod val="105000"/>+                <a:tint val="67000"/>+              </a:schemeClr>+            </a:gs>+            <a:gs pos="50000">+              <a:schemeClr val="phClr">+                <a:lumMod val="105000"/>+                <a:satMod val="103000"/>+                <a:tint val="73000"/>+              </a:schemeClr>+            </a:gs>+            <a:gs pos="100000">+              <a:schemeClr val="phClr">+                <a:lumMod val="105000"/>+                <a:satMod val="109000"/>+                <a:tint val="81000"/>+              </a:schemeClr>+            </a:gs>+          </a:gsLst>+          <a:lin ang="5400000" scaled="0"/>+        </a:gradFill>+        <a:gradFill rotWithShape="1">+          <a:gsLst>+            <a:gs pos="0">+              <a:schemeClr val="phClr">+                <a:satMod val="103000"/>+                <a:lumMod val="102000"/>+                <a:tint val="94000"/>+              </a:schemeClr>+            </a:gs>+            <a:gs pos="50000">+              <a:schemeClr val="phClr">+                <a:satMod val="110000"/>+                <a:lumMod val="100000"/>+                <a:shade val="100000"/>+              </a:schemeClr>+            </a:gs>+            <a:gs pos="100000">+              <a:schemeClr val="phClr">+                <a:lumMod val="99000"/>+                <a:satMod val="120000"/>+                <a:shade val="78000"/>+              </a:schemeClr>+            </a:gs>+          </a:gsLst>+          <a:lin ang="5400000" scaled="0"/>+        </a:gradFill>+      </a:fillStyleLst>+      <a:lnStyleLst>+        <a:ln w="6350" cap="flat" cmpd="sng" algn="ctr">+          <a:solidFill>+            <a:schemeClr val="phClr"/>+          </a:solidFill>+          <a:prstDash val="solid"/>+          <a:miter lim="800000"/>+        </a:ln>+        <a:ln w="12700" cap="flat" cmpd="sng" algn="ctr">+          <a:solidFill>+            <a:schemeClr val="phClr"/>+          </a:solidFill>+          <a:prstDash val="solid"/>+          <a:miter lim="800000"/>+        </a:ln>+        <a:ln w="19050" cap="flat" cmpd="sng" algn="ctr">+          <a:solidFill>+            <a:schemeClr val="phClr"/>+          </a:solidFill>+          <a:prstDash val="solid"/>+          <a:miter lim="800000"/>+        </a:ln>+      </a:lnStyleLst>+      <a:effectStyleLst>+        <a:effectStyle>+          <a:effectLst/>+        </a:effectStyle>+        <a:effectStyle>+          <a:effectLst/>+        </a:effectStyle>+        <a:effectStyle>+          <a:effectLst>+            <a:outerShdw blurRad="57150" dist="19050" dir="5400000" algn="ctr" rotWithShape="0">+              <a:srgbClr val="000000">+                <a:alpha val="63000"/>+              </a:srgbClr>+            </a:outerShdw>+          </a:effectLst>+        </a:effectStyle>+      </a:effectStyleLst>+      <a:bgFillStyleLst>+        <a:solidFill>+          <a:schemeClr val="phClr"/>+        </a:solidFill>+        <a:solidFill>+          <a:schemeClr val="phClr">+            <a:tint val="95000"/>+            <a:satMod val="170000"/>+          </a:schemeClr>+        </a:solidFill>+        <a:gradFill rotWithShape="1">+          <a:gsLst>+            <a:gs pos="0">+              <a:schemeClr val="phClr">+                <a:tint val="93000"/>+                <a:satMod val="150000"/>+                <a:shade val="98000"/>+                <a:lumMod val="102000"/>+              </a:schemeClr>+            </a:gs>+            <a:gs pos="50000">+              <a:schemeClr val="phClr">+                <a:tint val="98000"/>+                <a:satMod val="130000"/>+                <a:shade val="90000"/>+                <a:lumMod val="103000"/>+              </a:schemeClr>+            </a:gs>+            <a:gs pos="100000">+              <a:schemeClr val="phClr">+                <a:shade val="63000"/>+                <a:satMod val="120000"/>+              </a:schemeClr>+            </a:gs>+          </a:gsLst>+          <a:lin ang="5400000" scaled="0"/>+        </a:gradFill>+      </a:bgFillStyleLst>+    </a:fmtScheme>+  </a:themeElements>+  <a:objectDefaults/>+  <a:extraClrSchemeLst/>+  <a:extLst>+    <a:ext uri="{05A4C25C-085E-4340-85A3-A5531E510DB2}">+      <thm15:themeFamily xmlns:thm15="http://schemas.microsoft.com/office/thememl/2012/main" name="Office Theme" id="{2E142A2C-CD16-42D6-873A-C26D2A0506FA}" vid="{1BDDFF52-6CD6-40A5-AB3C-68EB2F1E4D0A}"/>+    </a:ext>+  </a:extLst>+</a:theme>
data/epub.css view
@@ -19,16 +19,12 @@   line-height: 1.2;   font-family: Georgia, serif;   color: #1a1a1a;-  background-color: #fdfdfd; } p {   text-indent: 0;   margin: 1em 0;   widows: 2;   orphans: 2;-}-a, a:visited {-  color: #1a1a1a; } img {   max-width: 100%;
data/odt/content.xml view
@@ -1,2 +1,82 @@ <?xml version="1.0" encoding="UTF-8"?>-<office:document-content xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.3"><office:scripts/><office:font-face-decls><style:font-face style:name="StarSymbol" svg:font-family="StarSymbol"/><style:font-face style:name="Tahoma1" svg:font-family="Tahoma"/><style:font-face style:name="Courier New" svg:font-family="&apos;Courier New&apos;" style:font-family-generic="modern" style:font-pitch="fixed"/><style:font-face style:name="Times New Roman" svg:font-family="&apos;Times New Roman&apos;" style:font-family-generic="roman" style:font-pitch="variable"/><style:font-face style:name="Arial" svg:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable"/><style:font-face style:name="Lucida Sans Unicode" svg:font-family="&apos;Lucida Sans Unicode&apos;" style:font-family-generic="system" style:font-pitch="variable"/><style:font-face style:name="Tahoma" svg:font-family="Tahoma" style:font-family-generic="system" style:font-pitch="variable"/></office:font-face-decls><office:automatic-styles><style:style style:name="P1" style:family="paragraph" style:parent-style-name="Footer"><style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/></style:style></office:automatic-styles><office:body><office:text><text:sequence-decls><text:sequence-decl text:display-outline-level="0" text:name="Illustration"/><text:sequence-decl text:display-outline-level="0" text:name="Table"/><text:sequence-decl text:display-outline-level="0" text:name="Text"/><text:sequence-decl text:display-outline-level="0" text:name="Drawing"/></text:sequence-decls><text:p text:style-name="Standard">Hello World!</text:p></office:text></office:body></office:document-content>+<office:document-content xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.3">+  <office:scripts/>+  <office:font-face-decls>+    <style:font-face style:name="StarSymbol" svg:font-family="StarSymbol"/>+    <style:font-face style:name="Tahoma1" svg:font-family="Tahoma"/>+    <style:font-face style:name="Courier New" svg:font-family="&apos;Courier New&apos;" style:font-family-generic="modern" style:font-pitch="fixed"/>+    <style:font-face style:name="Times New Roman" svg:font-family="&apos;Times New Roman&apos;" style:font-family-generic="roman" style:font-pitch="variable"/>+    <style:font-face style:name="Arial" svg:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable"/>+    <style:font-face style:name="Lucida Sans Unicode" svg:font-family="&apos;Lucida Sans Unicode&apos;" style:font-family-generic="system" style:font-pitch="variable"/>+    <style:font-face style:name="Tahoma" svg:font-family="Tahoma" style:font-family-generic="system" style:font-pitch="variable"/>+  </office:font-face-decls>+  <office:automatic-styles>+    <style:style style:name="DemoTable" style:family="table">+      <style:table-properties style:width="6in" table:align="margins"/>+    </style:style>+    <style:style style:name="DemoTable.A" style:family="table-column">+      <style:table-column-properties style:column-width="3in"/>+    </style:style>+  </office:automatic-styles>+  <office:body>+    <office:text>+      <text:sequence-decls>+        <text:sequence-decl text:display-outline-level="0" text:name="Illustration"/>+        <text:sequence-decl text:display-outline-level="0" text:name="Table"/>+        <text:sequence-decl text:display-outline-level="0" text:name="Text"/>+        <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/>+      </text:sequence-decls>+      <text:p text:style-name="Title">Title</text:p>+      <text:p text:style-name="Subtitle">Subtitle</text:p>+      <text:p text:style-name="Author">Author</text:p>+      <text:p text:style-name="Date">Date</text:p>+      <text:p text:style-name="Abstract">Abstract.</text:p>+      <text:h text:style-name="Heading_20_1" text:outline-level="1">Heading 1</text:h>+      <text:h text:style-name="Heading_20_2" text:outline-level="2">Heading 2</text:h>+      <text:h text:style-name="Heading_20_3" text:outline-level="3">Heading 3</text:h>+      <text:h text:style-name="Heading_20_4" text:outline-level="4">Heading 4</text:h>+      <text:h text:style-name="Heading_20_5" text:outline-level="5">Heading 5</text:h>+      <text:h text:style-name="Heading_20_6" text:outline-level="6">Heading 6</text:h>+      <text:p text:style-name="First_20_paragraph">First Paragraph.</text:p>+      <text:p text:style-name="Text_20_body">Body Text. <text:span text:style-name="Emphasis">Emphasis</text:span>. <text:span text:style-name="Strong_20_Emphasis">Strong Emphasis</text:span>. <text:span text:style-name="Strikeout">Strikeout</text:span>. <text:span text:style-name="Superscript">Superscript</text:span>. <text:span text:style-name="Subscript">Subscript</text:span>. <text:span text:style-name="Source_20_Text">Source Text</text:span>. <text:span text:style-name="Highlighted">Highlighted</text:span>. <text:a xlink:type="simple" xlink:href="https://pandoc.org"><text:span text:style-name="Definition">Hyperlink</text:span></text:a>. Footnote.<text:note text:id="ftn1" text:note-class="footnote"><text:note-citation>1</text:note-citation><text:note-body><text:p text:style-name="Footnote">Footnote text.</text:p></text:note-body></text:note></text:p>+      <text:p text:style-name="Quotations">Block quote.</text:p>+      <text:p text:style-name="Preformatted_20_Text">Preformatted Text.</text:p>+      <text:list text:style-name="List_20_1">+        <text:list-item>+          <text:p text:style-name="List_20_Bullet">Bullet list item.</text:p>+        </text:list-item>+      </text:list>+      <text:list text:style-name="Numbering_20_1">+        <text:list-item>+          <text:p text:style-name="List_20_Number">Numbered list item.</text:p>+        </text:list-item>+      </text:list>+      <text:p text:style-name="TableCaption">Table caption.</text:p>+      <table:table table:name="DemoTable" table:style-name="DemoTable">+        <table:table-column table:style-name="DemoTable.A"/>+        <table:table-column table:style-name="DemoTable.A"/>+        <table:table-header-rows>+          <table:table-row>+            <table:table-cell office:value-type="string">+              <text:p text:style-name="Table_20_Heading">Table Heading</text:p>+            </table:table-cell>+            <table:table-cell office:value-type="string">+              <text:p text:style-name="Table_20_Heading">Table Heading</text:p>+            </table:table-cell>+          </table:table-row>+        </table:table-header-rows>+        <table:table-row>+          <table:table-cell office:value-type="string">+            <text:p text:style-name="Table_20_Contents">Table Contents</text:p>+          </table:table-cell>+          <table:table-cell office:value-type="string">+            <text:p text:style-name="Table_20_Contents">Table Contents</text:p>+          </table:table-cell>+        </table:table-row>+      </table:table>+      <text:p text:style-name="FigureCaption">Image caption.</text:p>+      <text:p text:style-name="Definition_20_Term">Definition Term</text:p>+      <text:p text:style-name="Definition_20_Definition">Definition.</text:p>+    </office:text>+  </office:body>+</office:document-content>
data/odt/styles.xml view
@@ -73,6 +73,26 @@       style:font-size-complex="12pt" style:language-complex="zxx"       style:country-complex="none" />     </style:default-style>+    <style:style style:name="Title" style:family="paragraph"+      style:parent-style-name="Heading" style:next-style-name="Subtitle"+      style:class="chapter">+      <style:paragraph-properties fo:text-align="center"+        style:justify-single-word="false" fo:margin-top="0in"+        fo:margin-bottom="0.0835in" style:contextual-spacing="false" />+      <style:text-properties fo:font-size="28pt" fo:font-weight="bold"+        style:font-size-asian="28pt" style:font-weight-asian="bold"+        style:font-size-complex="28pt" style:font-weight-complex="bold" />+    </style:style>+    <style:style style:name="Subtitle" style:family="paragraph"+      style:parent-style-name="Heading" style:next-style-name="Text_20_body"+      style:class="chapter">+      <style:paragraph-properties fo:text-align="center"+        style:justify-single-word="false" fo:margin-top="0.0835in"+        fo:margin-bottom="0.0835in" style:contextual-spacing="false" />+      <style:text-properties fo:font-size="18pt" fo:font-style="italic"+        style:font-size-asian="18pt" style:font-style-asian="italic"+        style:font-size-complex="18pt" style:font-style-complex="italic" />+    </style:style>     <style:style style:name="Author" style:family="paragraph"       style:parent-style-name="Standard" style:class="html">         <style:paragraph-properties fo:text-align="center" />@@ -136,6 +156,24 @@     style:parent-style-name="Text_20_body" style:class="list">       <style:text-properties style:font-name-complex="Tahoma1" />     </style:style>+    <style:style style:name="List_20_Bullet"+    style:display-name="List Bullet" style:family="paragraph"+    style:parent-style-name="List" style:class="list" />+    <style:style style:name="List_20_Bullet_20_Tight"+    style:display-name="List Bullet Tight" style:family="paragraph"+    style:parent-style-name="List" style:class="list">+      <style:paragraph-properties fo:margin-top="0in"+      fo:margin-bottom="0in" style:contextual-spacing="false" />+    </style:style>+    <style:style style:name="List_20_Number"+    style:display-name="List Number" style:family="paragraph"+    style:parent-style-name="List" style:class="list" />+    <style:style style:name="List_20_Number_20_Tight"+    style:display-name="List Number Tight" style:family="paragraph"+    style:parent-style-name="List" style:class="list">+      <style:paragraph-properties fo:margin-top="0in"+      fo:margin-bottom="0in" style:contextual-spacing="false" />+    </style:style>     <style:style style:name="Caption" style:family="paragraph"     style:parent-style-name="Standard" style:class="extra">       <style:paragraph-properties fo:margin-top="0.0835in"@@ -148,6 +186,9 @@       style:font-size-complex="12pt"       style:font-style-complex="italic" />     </style:style>+    <style:style style:name="TableCaption" style:family="paragraph"+    style:parent-style-name="Caption" style:class="extra">+    </style:style>     <style:style style:name="Table" style:family="paragraph"     style:parent-style-name="Caption" style:class="extra">     </style:style>@@ -247,18 +288,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">
+ data/templates/after-header-includes.latex view
@@ -0,0 +1,10 @@+\usepackage{bookmark}+\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available+\urlstyle{$if(urlstyle)$$urlstyle$$else$same$endif$}+$if(links-as-notes)$+% Make links footnotes instead of hotlinks:+\DeclareRobustCommand{\href}[2]{#2\footnote{\url{#1}}}+$endif$+$if(verbatim-in-note)$+\VerbatimFootnotes % allow verbatim text in footnotes+$endif$
data/templates/article.jats_publishing view
@@ -98,7 +98,7 @@ <surname>$if(author.non-dropping-particle)$${author.non-dropping-particle} $endif$$author.surname$</surname> <given-names>$author.given-names$$if(author.dropping-particle)$ ${author.dropping-particle}$endif$</given-names> $if(author.prefix)$-<prefix>${author.suffix}</prefix>+<prefix>${author.prefix}</prefix> $endif$ $if(author.suffix)$ <suffix>${author.suffix}</suffix>@@ -109,6 +109,17 @@ $else$ <string-name>$author$</string-name> $endif$+$for(author.roles)$+$if(it.credit)$+<role vocab="credit"$if(it.degree)$ degree-contribution="$it.degree$"$endif$+      vocab-identifier="https://credit.niso.org/"+      vocab-term-identifier="https://credit.niso.org/contributor-roles/$it.credit$/"+      vocab-term="$it.credit-name$"+>$if(it.name)$$it.name$$else$$it.credit-name$$endif$</role>+$elseif(it.name)$+<role>$it.name$</role>+$endif$+$endfor$ $if(author.email)$ <email>$author.email$</email> $endif$@@ -232,5 +243,10 @@ $back$ $endif$ </back>+$if(floats-group)$+<floats-group>+$floats-group$+</floats-group>+$endif$ </article> 
+ data/templates/common.latex view
@@ -0,0 +1,263 @@+$if(linestretch)$+\usepackage{setspace}+$endif$+$--+$-- paragraph formatting+$--+$if(indent)$+$else$+\makeatletter+\@ifundefined{KOMAClassName}{% if non-KOMA class+  \IfFileExists{parskip.sty}{%+    \usepackage{parskip}+  }{% else+    \setlength{\parindent}{0pt}+    \setlength{\parskip}{6pt plus 2pt minus 1pt}}+}{% if KOMA class+  \KOMAoptions{parskip=half}}+\makeatother+$endif$+$if(beamer)$+$else$+$if(block-headings)$+% Make \paragraph and \subparagraph free-standing+\makeatletter+\ifx\paragraph\undefined\else+  \let\oldparagraph\paragraph+  \renewcommand{\paragraph}{+    \@ifstar+      \xxxParagraphStar+      \xxxParagraphNoStar+  }+  \newcommand{\xxxParagraphStar}[1]{\oldparagraph*{#1}\mbox{}}+  \newcommand{\xxxParagraphNoStar}[1]{\oldparagraph{#1}\mbox{}}+\fi+\ifx\subparagraph\undefined\else+  \let\oldsubparagraph\subparagraph+  \renewcommand{\subparagraph}{+    \@ifstar+      \xxxSubParagraphStar+      \xxxSubParagraphNoStar+  }+  \newcommand{\xxxSubParagraphStar}[1]{\oldsubparagraph*{#1}\mbox{}}+  \newcommand{\xxxSubParagraphNoStar}[1]{\oldsubparagraph{#1}\mbox{}}+\fi+\makeatother+$endif$+$endif$+$--+$-- verbatim in notes+$--+$if(verbatim-in-note)$+\usepackage{fancyvrb}+$endif$+$-- highlighting+$if(listings)$+\usepackage{listings}+\newcommand{\passthrough}[1]{#1}+\lstset{defaultdialect=[5.3]Lua}+\lstset{defaultdialect=[x86masm]Assembler}+$endif$+$if(lhs)$+\lstnewenvironment{code}{\lstset{language=Haskell,basicstyle=\small\ttfamily}}{}+$endif$+$if(highlighting-macros)$+$highlighting-macros$+$endif$+$--+$-- tables+$--+$if(tables)$+\usepackage{longtable,booktabs,array}+\newcounter{none} % for unnumbered tables+$if(multirow)$+\usepackage{multirow}+$endif$+\usepackage{calc} % for calculating minipage widths+$if(beamer)$+\usepackage{caption}+% Make caption package work with longtable+\makeatletter+\def\fnum@table{\tablename~\thetable}+\makeatother+$else$+% Correct order of tables after \paragraph or \subparagraph+\usepackage{etoolbox}+\makeatletter+\patchcmd\longtable{\par}{\if@noskipsec\mbox{}\fi\par}{}{}+\makeatother+% Allow footnotes in longtable head/foot+\IfFileExists{footnotehyper.sty}{\usepackage{footnotehyper}}{\usepackage{footnote}}+\makesavenoteenv{longtable}+$endif$+$endif$+$--+$-- graphics+$--+$if(graphics)$+\usepackage{graphicx}+\makeatletter+\newsavebox\pandoc@box+\newcommand*\pandocbounded[1]{% scales image to fit in text height/width+  \sbox\pandoc@box{#1}%+  \Gscale@div\@tempa{\textheight}{\dimexpr\ht\pandoc@box+\dp\pandoc@box\relax}%+  \Gscale@div\@tempb{\linewidth}{\wd\pandoc@box}%+  \ifdim\@tempb\p@<\@tempa\p@\let\@tempa\@tempb\fi% select the smaller of both+  \ifdim\@tempa\p@<\p@\scalebox{\@tempa}{\usebox\pandoc@box}%+  \else\usebox{\pandoc@box}%+  \fi%+}+% Set default figure placement to htbp+\def\fps@figure{htbp}+\makeatother+$endif$+$if(svg)$+\usepackage{svg}+$endif$+$--+$-- strikeout/underline+$--+$if(strikeout)$+\ifLuaTeX+  \usepackage{luacolor}+  \usepackage[soul]{lua-ul}+\else+  \usepackage{soul}+$if(beamer)$+  \makeatletter+  \let\HL\hl+  \renewcommand\hl{% fix for beamer highlighting+    \let\set@color\beamerorig@set@color+    \let\reset@color\beamerorig@reset@color+    \HL}+  \makeatother+$endif$+$if(CJKmainfont)$+  \ifXeTeX+    % soul's \st doesn't work for CJK:+    \usepackage{xeCJKfntef}+    \renewcommand{\st}[1]{\sout{#1}}+  \fi+$endif$+\fi+$endif$+$--+$-- CSL citations+$--+$if(csl-refs)$+% definitions for citeproc citations+\NewDocumentCommand\citeproctext{}{}+\NewDocumentCommand\citeproc{mm}{%+  \begingroup\def\citeproctext{#2}\cite{#1}\endgroup}+\makeatletter+ % allow citations to break across lines+ \let\@cite@ofmt\@firstofone+ % avoid brackets around text for \cite:+ \def\@biblabel#1{}+ \def\@cite#1#2{{#1\if@tempswa , #2\fi}}+\makeatother+\newlength{\cslhangindent}+\setlength{\cslhangindent}{1.5em}+\newlength{\csllabelwidth}+\setlength{\csllabelwidth}{3em}+\newenvironment{CSLReferences}[2] % #1 hanging-indent, #2 entry-spacing+ {\begin{list}{}{%+  \setlength{\itemindent}{0pt}+  \setlength{\leftmargin}{0pt}+  \setlength{\parsep}{0pt}+  % turn on hanging indent if param 1 is 1+  \ifodd #1+   \setlength{\leftmargin}{\cslhangindent}+   \setlength{\itemindent}{-1\cslhangindent}+  \fi+  % set entry spacing+  \setlength{\itemsep}{#2\baselineskip}}}+ {\end{list}}+\usepackage{calc}+\newcommand{\CSLBlock}[1]{\hfill\break\parbox[t]{\linewidth}{\strut\ignorespaces#1\strut}}+\newcommand{\CSLLeftMargin}[1]{\parbox[t]{\csllabelwidth}{\strut#1\strut}}+\newcommand{\CSLRightInline}[1]{\parbox[t]{\linewidth - \csllabelwidth}{\strut#1\strut}}+\newcommand{\CSLIndent}[1]{\hspace{\cslhangindent}#1}+$endif$+$--+$-- Babel language support+$--+$if(lang)$+\ifLuaTeX+\usepackage[bidi=basic$if(shorthands)$$else$,shorthands=off$endif$$for(babeloptions)$,$babeloptions$$endfor$]{babel}+\else+\usepackage[bidi=default$if(shorthands)$$else$,shorthands=off$endif$$for(babeloptions)$,$babeloptions$$endfor$]{babel}+\fi+$if(babel-lang)$+$if(mainfont)$+\ifPDFTeX+\else+\babelfont{rm}[$for(mainfontoptions)$$mainfontoptions$$sep$,$endfor$$if(mainfontfallback)$,RawFeature={fallback=mainfontfallback}$endif$]{$mainfont$}+\fi+$endif$+$endif$+$for(babelfonts/pairs)$+\babelfont[$babelfonts.key$]{rm}{$babelfonts.value$}+$endfor$+\ifLuaTeX+  \usepackage{selnolig} % disable illegal ligatures+\fi+$endif$+$--+$-- pagestyle+$--+$if(pagestyle)$+\pagestyle{$pagestyle$}+$endif$+$--+$-- prevent overfull lines+$--+\setlength{\emergencystretch}{3em} % prevent overfull lines+$--+$-- tight lists+$--+\providecommand{\tightlist}{%+  \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}+$--+$-- subfigure support+$--+$if(subfigure)$+\usepackage{subcaption}+$endif$+$--+$-- text direction support for pdftex+$--+$if(dir)$+\ifPDFTeX+  \TeXXeTstate=1+  \newcommand{\RL}[1]{\beginR #1\endR}+  \newcommand{\LR}[1]{\beginL #1\endL}+  \newenvironment{RTL}{\beginR}{\endR}+  \newenvironment{LTR}{\beginL}{\endL}+\fi+\ifluatex+  \newcommand{\RL}[1]{\bgroup\textdir TRT#1\egroup}+  \newcommand{\LR}[1]{\bgroup\textdir TLT#1\egroup}+  \newenvironment{RTL}{\textdir TRT\pardir TRT\bodydir TRT}{}+  \newenvironment{LTR}{\textdir TLT\pardir TLT\bodydir TLT}{}+\fi+$endif$+$--+$-- bibliography support support for natbib and biblatex+$--+$if(natbib)$+\usepackage[$natbiboptions$]{natbib}+\bibliographystyle{$if(biblio-style)$$biblio-style$$else$plainnat$endif$}+$endif$+$if(biblatex)$+\usepackage[$if(biblio-style)$style=$biblio-style$,$endif$$for(biblatexoptions)$$biblatexoptions$$sep$,$endfor$]{biblatex}+$for(bibliography)$+\addbibresource{$bibliography$}+$endfor$+$endif$+$--+$-- csquotes+$--+$if(csquotes)$+\usepackage[$for(csquotesoptions)$$csquotesoptions$$sep$,$endfor$]{csquotes}+$endif$
+ data/templates/default.ansi view
@@ -0,0 +1,21 @@+$if(titleblock)$+$titleblock$++$endif$+$for(header-includes)$+$header-includes$++$endfor$+$for(include-before)$+$include-before$++$endfor$+$if(toc)$+$table-of-contents$++$endif$+$body$+$for(include-after)$++$include-after$+$endfor$
+ data/templates/default.bbcode view
@@ -0,0 +1,1 @@+$body$
+ data/templates/default.beamer view
@@ -0,0 +1,204 @@+$passoptions.latex()$+\documentclass[+$if(fontsize)$+  $fontsize$,+$endif$+  ignorenonframetext,+$if(handout)$+  handout,+$endif$+$if(aspectratio)$+  aspectratio=$aspectratio$,+$endif$+$if(babel-lang)$+  $babel-lang$,+$endif$+$for(classoption)$+  $classoption$$sep$,+$endfor$+]{$documentclass$}+$if(geometry)$+\geometry{$for(geometry)$$geometry$$sep$,$endfor$}+$endif$+\newif\ifbibliography+$if(background-image)$+\usebackgroundtemplate{%+  \includegraphics[width=\paperwidth]{$background-image$}%+}+% In beamer background-image does not work well when other images are used, so this is the workaround+\pgfdeclareimage[width=\paperwidth,height=\paperheight]{background}{$background-image$}+\usebackgroundtemplate{\pgfuseimage{background}}+$endif$+\usepackage{pgfpages}+\setbeamertemplate{caption}[numbered]+\setbeamertemplate{caption label separator}{: }+\setbeamercolor{caption name}{fg=normal text.fg}+\beamertemplatenavigationsymbols$if(navigation)$$navigation$$else$empty$endif$+$--+$-- section numbering+$--+$if(numbersections)$+$else$+% remove section numbering+\setbeamertemplate{part page}{+  \centering+  \begin{beamercolorbox}[sep=16pt,center]{part title}+    \usebeamerfont{part title}\insertpart\par+  \end{beamercolorbox}+}+\setbeamertemplate{section page}{+  \centering+  \begin{beamercolorbox}[sep=12pt,center]{section title}+    \usebeamerfont{section title}\insertsection\par+  \end{beamercolorbox}+}+\setbeamertemplate{subsection page}{+  \centering+  \begin{beamercolorbox}[sep=8pt,center]{subsection title}+    \usebeamerfont{subsection title}\insertsubsection\par+  \end{beamercolorbox}+}+$endif$+$for(beameroption)$+\setbeameroption{$beameroption$}+$endfor$+% Prevent slide breaks in the middle of a paragraph+\widowpenalties 1 10000+\raggedbottom+$if(section-titles)$+\AtBeginPart{+  \frame{\partpage}+}+\AtBeginSection{+  \ifbibliography+  \else+    \frame{\sectionpage}+  \fi+}+\AtBeginSubsection{+  \frame{\subsectionpage}+}+$endif$+$fonts.latex()$+$-- Set Beamer theme before user font settings so they can override theme+$if(theme)$+\usetheme[$for(themeoptions)$$themeoptions$$sep$,$endfor$]{$theme$}+$endif$+$if(colortheme)$+\usecolortheme[$for(colorthemeoptions)$$colorthemeoptions$$sep$,$endfor$]{$colortheme$}+$endif$+$if(fonttheme)$+\usefonttheme[$for(fontthemeoptions)$$fontthemeoptions$$sep$,$endfor$]{$fonttheme$}+$endif$+$if(mainfont)$+\usefonttheme{serif} % use mainfont rather than sansfont for slide text+$endif$+$if(innertheme)$+\useinnertheme[$for(innerthemeoptions)$$innerthemeoptions$$sep$,$endfor$]{$innertheme$}+$endif$+$if(outertheme)$+\useoutertheme[$for(outerthemeoptions)$$outerthemeoptions$$sep$,$endfor$]{$outertheme$}+$endif$+$font-settings.latex()$+$common.latex()$+$for(header-includes)$+$header-includes$+$endfor$+$after-header-includes.latex()$+$hypersetup.latex()$++$if(title)$+\title$if(shorttitle)$[$shorttitle$]$endif${\texorpdfstring{$title$}{$title-meta$}$if(thanks)$\thanks{$thanks$}$endif$}+$endif$+$if(subtitle)$+\subtitle$if(shortsubtitle)$[$shortsubtitle$]$endif${\texorpdfstring{$subtitle$}{$subtitle-meta$}}+$endif$+\author$if(shortauthor)$[$shortauthor$]$endif${\texorpdfstring{$for(author)$$author$$sep$ \and $endfor$}{$author-meta$}}+\date$if(shortdate)$[$shortdate$]$endif${$date$}+$if(institute)$+\institute$if(shortinstitute)$[$shortinstitute$]$endif${$for(institute)$$institute$$sep$ \and $endfor$}+$endif$+$if(titlegraphic)$+\titlegraphic{+$for(titlegraphic)$+  \includegraphics$if(titlegraphicoptions)$[$for(titlegraphicoptions)$$titlegraphicoptions$$sep$, $endfor$]$endif${$titlegraphic$}$sep$\enspace+$endfor$}+$endif$+$if(logo)$+\logo{\includegraphics$if(logooptions)$[$for(logooptions)$$logooptions$$sep$, $endfor$]$endif${$logo$}}+$endif$++\begin{document}+$if(title)$+\frame{\titlepage}+$if(abstract)$+\begin{abstract}+$abstract$+\end{abstract}+$endif$+$endif$++$for(include-before)$+$include-before$++$endfor$+$if(toc)$+$if(toc-title)$+\renewcommand*\contentsname{$toc-title$}+$endif$+\begin{frame}[allowframebreaks]+$if(toc-title)$+  \frametitle{$toc-title$}+$endif$+  \setcounter{tocdepth}{$toc-depth$}+  \tableofcontents+\end{frame}+\setcounter{tocdepth}{$toc-depth$}+\tableofcontents+}+$endif$+$if(lof)$+\listoffigures+$endif$+$if(lot)$+\listoftables+$endif$+$if(linestretch)$+\setstretch{$linestretch$}+$endif$+$body$++$if(natbib)$+$if(bibliography)$+$if(biblio-title)$+$if(has-chapters)$+\renewcommand\bibname{$biblio-title$}+$else$+\renewcommand\refname{$biblio-title$}+$endif$+$endif$+\begin{frame}[allowframebreaks]{$biblio-title$}+$if(nocite-ids)$+  \nocite{$for(nocite-ids)$$it$$sep$, $endfor$}+$endif$+  \bibliographytrue+  \bibliography{$for(bibliography)$$bibliography$$sep$,$endfor$}+\end{frame}++$endif$+$endif$+$if(biblatex)$+\begin{frame}[allowframebreaks]{$biblio-title$}+$if(nocite-ids)$+  \nocite{$for(nocite-ids)$$it$$sep$, $endfor$}+$endif$+  \bibliographytrue+  \printbibliography[heading=none]+\end{frame}++$endif$+$for(include-after)$+$include-after$++$endfor$+\end{document}
data/templates/default.context view
@@ -1,3 +1,8 @@+$if(tagging)$+\setupbackend[format=pdf/ua-2]+\enabledirectives[backend.usetags=mkiv]+\setuptagging[state=start]+$endif$ $if(context-lang)$ \mainlanguage[$context-lang$] $endif$@@ -47,7 +52,6 @@    profile={$if(pdfaiccprofile)$$for(pdfaiccprofile)$$pdfaiccprofile$$sep$,$endfor$$else$sRGB.icc$endif$},    intent=$if(pdfaintent)$$pdfaintent$$else$sRGB IEC61966-2.1$endif$] $endif$-\setupbackend[export=yes] \setupstructure[state=start,method=auto]  % use microtypography@@ -61,19 +65,19 @@  $-- set up font fallbacks $for(mainfontfallback)$-\definefallbackfamily[mainface][rm][$mainfontfallback$][range=0x0000-0xFFFF, check=yes, force=no]+\definefallbackfamily[mainface][rm][$mainfontfallback/nowrap$][range=0x0000-0xFFFF, check=yes, force=no] $endfor$ $for(sansfontfallback)$-\definefallbackfamily[mainface][ss][$sansfontfallback$][range=0x0000-0xFFFF, check=yes, force=no]+\definefallbackfamily[mainface][ss][$sansfontfallback/nowrap$][range=0x0000-0xFFFF, check=yes, force=no] $endfor$ $for(monofontfallback)$-\definefallbackfamily[mainface][tt][$monofontfallback$][range=0x0000-0xFFFF, check=yes, force=no]+\definefallbackfamily[mainface][tt][$monofontfallback/nowrap$][range=0x0000-0xFFFF, check=yes, force=no] $endfor$ \definefallbackfamily[mainface][rm][CMU Serif][preset=range:greek, force=yes]-\definefontfamily[mainface][rm][$if(mainfont)$$mainfont$$else$Latin Modern Roman$endif$]-\definefontfamily[mainface][mm][$if(mathfont)$$mathfont$$else$Latin Modern Math$endif$]-\definefontfamily[mainface][ss][$if(sansfont)$$sansfont$$else$Latin Modern Sans$endif$]-\definefontfamily[mainface][tt][$if(monofont)$$monofont$$else$Latin Modern Typewriter$endif$][features=none]+\definefontfamily[mainface][rm][$if(mainfont)$$mainfont/nowrap$$else$Latin Modern Roman$endif$]+\definefontfamily[mainface][mm][$if(mathfont)$$mathfont/nowrap$$else$Latin Modern Math$endif$]+\definefontfamily[mainface][ss][$if(sansfont)$$sansfont/nowrap$$else$Latin Modern Sans$endif$]+\definefontfamily[mainface][tt][$if(monofont)$$monofont/nowrap$$else$Latin Modern Typewriter$endif$][features=none] \setupbodyfont[mainface$if(fontsize)$,$fontsize$$endif$]  \setupwhitespace[$if(whitespace)$$whitespace$$else$medium$endif$]
data/templates/default.epub2 view
@@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">-<html xmlns="http://www.w3.org/1999/xhtml"$if(lang)$ lang="$lang$" xml:lang="$lang$"$endif$>+<html xmlns="http://www.w3.org/1999/xhtml"$if(lang)$ lang="$lang$" xml:lang="$lang$"$endif$$if(dir)$ dir="$dir$"$endif$> <head>   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />   <meta http-equiv="Content-Style-Type" content="text/css" />
data/templates/default.epub3 view
@@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html>-<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops"$if(lang)$ lang="$lang$" xml:lang="$lang$"$endif$>+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops"$if(lang)$ lang="$lang$" xml:lang="$lang$"$endif$$if(dir)$ dir="$dir$"$endif$> <head>   <meta charset="utf-8" />   <meta name="generator" content="pandoc" />
data/templates/default.html4 view
@@ -3,7 +3,7 @@ <head>   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />   <meta http-equiv="Content-Style-Type" content="text/css" />-  <meta name="generator" content="pandoc" />+  <meta name="generator" content="pandoc $pandoc-version$" /> $for(author-meta)$   <meta name="author" content="$author-meta$" /> $endfor$@@ -27,9 +27,6 @@   $header-includes$ $endfor$ $if(math)$-$if(mathjax)$-  <script src="https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?features=es6"></script>-$endif$   $math$ $endif$ </head>
data/templates/default.html5 view
@@ -1,8 +1,8 @@ <!DOCTYPE html>-<html xmlns="http://www.w3.org/1999/xhtml" lang="$lang$" xml:lang="$lang$"$if(dir)$ dir="$dir$"$endif$>+<html xmlns="http://www.w3.org/1999/xhtml"$if(lang)$ lang="$lang$" xml:lang="$lang$"$endif$$if(dir)$ dir="$dir$"$endif$> <head>   <meta charset="utf-8" />-  <meta name="generator" content="pandoc" />+  <meta name="generator" content="pandoc $pandoc-version$" />   <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" /> $for(author-meta)$   <meta name="author" content="$author-meta$" />@@ -27,9 +27,6 @@   $header-includes$ $endfor$ $if(math)$-$if(mathjax)$-  <script src="https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?features=es6"></script>-$endif$   $math$ $endif$ </head>
data/templates/default.icml view
@@ -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$"
data/templates/default.jats_articleauthoring view
@@ -31,7 +31,7 @@ <surname>$if(author.non-dropping-particle)$${author.non-dropping-particle} $endif$${author.surname}</surname> <given-names>${author.given-names}$if(author.dropping-particle)$ ${author.dropping-particle}$endif$</given-names> $if(author.prefix)$-<prefix>${author.suffix}</prefix>+<prefix>${author.prefix}</prefix> $endif$ $if(author.suffix)$ <suffix>${author.suffix}</suffix>@@ -90,6 +90,11 @@ <funding-group> <funding-statement>$article.funding-statement$</funding-statement> </funding-group>+$endif$+$if(supplementary-material)$+<supplementary-material>+$supplementary-material$+</supplementary-material> $endif$ </article-meta> </front>
data/templates/default.latex view
@@ -1,556 +1,84 @@-% Options for packages loaded elsewhere-\PassOptionsToPackage{unicode$for(hyperrefoptions)$,$hyperrefoptions$$endfor$}{hyperref}-\PassOptionsToPackage{hyphens}{url}-$if(colorlinks)$-\PassOptionsToPackage{dvipsnames,svgnames,x11names}{xcolor}-$endif$-$if(CJKmainfont)$-\PassOptionsToPackage{space}{xeCJK}-$endif$-%+$document-metadata.latex()$+$passoptions.latex()$ \documentclass[+$for(babel-otherlangs)$+  $babel-otherlangs$,+$endfor$+$if(babel-lang)$+  $babel-lang$,+$endif$ $if(fontsize)$   $fontsize$, $endif$ $if(papersize)$   $papersize$paper, $endif$-$if(beamer)$-  ignorenonframetext,-$if(handout)$-  handout,-$endif$-$if(aspectratio)$-  aspectratio=$aspectratio$,-$endif$-$endif$ $for(classoption)$   $classoption$$sep$, $endfor$ ]{$documentclass$}-$if(beamer)$-$if(background-image)$-\usebackgroundtemplate{%-  \includegraphics[width=\paperwidth]{$background-image$}%-}-% In beamer background-image does not work well when other images are used, so this is the workaround-\pgfdeclareimage[width=\paperwidth,height=\paperheight]{background}{$background-image$}-\usebackgroundtemplate{\pgfuseimage{background}}-$endif$-\usepackage{pgfpages}-\setbeamertemplate{caption}[numbered]-\setbeamertemplate{caption label separator}{: }-\setbeamercolor{caption name}{fg=normal text.fg}-\beamertemplatenavigationsymbols$if(navigation)$$navigation$$else$empty$endif$-$for(beameroption)$-\setbeameroption{$beameroption$}-$endfor$-% Prevent slide breaks in the middle of a paragraph-\widowpenalties 1 10000-\raggedbottom-$if(section-titles)$-\setbeamertemplate{part page}{-  \centering-  \begin{beamercolorbox}[sep=16pt,center]{part title}-    \usebeamerfont{part title}\insertpart\par-  \end{beamercolorbox}-}-\setbeamertemplate{section page}{-  \centering-  \begin{beamercolorbox}[sep=12pt,center]{part title}-    \usebeamerfont{section title}\insertsection\par-  \end{beamercolorbox}-}-\setbeamertemplate{subsection page}{-  \centering-  \begin{beamercolorbox}[sep=8pt,center]{part title}-    \usebeamerfont{subsection title}\insertsubsection\par-  \end{beamercolorbox}-}-\AtBeginPart{-  \frame{\partpage}-}-\AtBeginSection{-  \ifbibliography-  \else-    \frame{\sectionpage}-  \fi-}-\AtBeginSubsection{-  \frame{\subsectionpage}-}-$endif$-$endif$ $if(beamerarticle)$ \usepackage{beamerarticle} % needs to be loaded first $endif$-\usepackage{amsmath,amssymb}-$if(linestretch)$-\usepackage{setspace}-$endif$-\usepackage{iftex}-\ifPDFTeX-  \usepackage[$if(fontenc)$$fontenc$$else$T1$endif$]{fontenc}-  \usepackage[utf8]{inputenc}-  \usepackage{textcomp} % provide euro and other symbols-\else % if luatex or xetex-$if(mathspec)$-  \ifXeTeX-    \usepackage{mathspec} % this also loads fontspec-  \else-    \usepackage{unicode-math} % this also loads fontspec-  \fi-$else$-  \usepackage{unicode-math} % this also loads fontspec-$endif$-  \defaultfontfeatures{Scale=MatchLowercase}$-- must come before Beamer theme-  \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1}-\fi-$if(fontfamily)$-$else$-$-- Set default font before Beamer theme so the theme can override it-\usepackage{lmodern}-$endif$-$-- Set Beamer theme before user font settings so they can override theme-$if(beamer)$-$if(theme)$-\usetheme[$for(themeoptions)$$themeoptions$$sep$,$endfor$]{$theme$}-$endif$-$if(colortheme)$-\usecolortheme{$colortheme$}-$endif$-$if(fonttheme)$-\usefonttheme{$fonttheme$}-$endif$-$if(mainfont)$-\usefonttheme{serif} % use mainfont rather than sansfont for slide text-$endif$-$if(innertheme)$-\useinnertheme{$innertheme$}-$endif$-$if(outertheme)$-\useoutertheme{$outertheme$}-$endif$-$endif$-$-- User font settings (must come after default font and Beamer theme)-$if(fontfamily)$-\usepackage[$for(fontfamilyoptions)$$fontfamilyoptions$$sep$,$endfor$]{$fontfamily$}-$endif$-\ifPDFTeX\else-  % xetex/luatex font selection-$if(mainfont)$-  $if(mainfontfallback)$-    \ifLuaTeX-      \usepackage{luaotfload}-      \directlua{luaotfload.add_fallback("mainfontfallback",{-        $for(mainfontfallback)$"$mainfontfallback$"$sep$,$endfor$-      })}-    \fi-  $endif$-  \setmainfont[$for(mainfontoptions)$$mainfontoptions$$sep$,$endfor$$if(mainfontfallback)$,RawFeature={fallback=mainfontfallback}$endif$]{$mainfont$}-$endif$-$if(sansfont)$-  $if(sansfontfallback)$-    \ifLuaTeX-      \usepackage{luaotfload}-      \directlua{luaotfload.add_fallback("sansfontfallback",{-        $for(sansfontfallback)$"$sansfontfallback$"$sep$,$endfor$-      })}-    \fi-  $endif$-  \setsansfont[$for(sansfontoptions)$$sansfontoptions$$sep$,$endfor$$if(sansfontfallback)$,RawFeature={fallback=sansfontfallback}$endif$]{$sansfont$}-$endif$-$if(monofont)$-  $if(monofontfallback)$-    \ifLuaTeX-      \usepackage{luaotfload}-      \directlua{luaotfload.add_fallback("monofontfallback",{-        $for(monofontfallback)$"$monofontfallback$"$sep$,$endfor$-      })}-    \fi-  $endif$-  \setmonofont[$for(monofontoptions)$$monofontoptions$$sep$,$endfor$$if(monofontfallback)$,RawFeature={fallback=monofontfallback}$endif$]{$monofont$}-$endif$-$for(fontfamilies)$-  \newfontfamily{$fontfamilies.name$}[$for(fontfamilies.options)$$fontfamilies.options$$sep$,$endfor$]{$fontfamilies.font$}-$endfor$-$if(mathfont)$-$if(mathspec)$-  \ifXeTeX-    \setmathfont(Digits,Latin,Greek)[$for(mathfontoptions)$$mathfontoptions$$sep$,$endfor$]{$mathfont$}-  \else-    \setmathfont[$for(mathfontoptions)$$mathfontoptions$$sep$,$endfor$]{$mathfont$}-  \fi-$else$-  \setmathfont[$for(mathfontoptions)$$mathfontoptions$$sep$,$endfor$]{$mathfont$}-$endif$-$endif$-$if(CJKmainfont)$-  \ifXeTeX-    \usepackage{xeCJK}-    \setCJKmainfont[$for(CJKoptions)$$CJKoptions$$sep$,$endfor$]{$CJKmainfont$}-    $if(CJKsansfont)$-      \setCJKsansfont[$for(CJKoptions)$$CJKoptions$$sep$,$endfor$]{$CJKsansfont$}-    $endif$-    $if(CJKmonofont)$-      \setCJKmonofont[$for(CJKoptions)$$CJKoptions$$sep$,$endfor$]{$CJKmonofont$}-    $endif$-  \fi-$endif$-$if(luatexjapresetoptions)$-  \ifLuaTeX-    \usepackage[$for(luatexjapresetoptions)$$luatexjapresetoptions$$sep$,$endfor$]{luatexja-preset}-  \fi-$endif$-$if(CJKmainfont)$-  \ifLuaTeX-    \usepackage[$for(luatexjafontspecoptions)$$luatexjafontspecoptions$$sep$,$endfor$]{luatexja-fontspec}-    \setmainjfont[$for(CJKoptions)$$CJKoptions$$sep$,$endfor$]{$CJKmainfont$}-  \fi-$endif$-\fi-$if(zero-width-non-joiner)$-%% Support for zero-width non-joiner characters.-\makeatletter-\def\zerowidthnonjoiner{%-  % Prevent ligatures and adjust kerning, but still support hyphenating.-  \texorpdfstring{%-    \TextOrMath{\nobreak\discretionary{-}{}{\kern.03em}%-      \ifvmode\else\nobreak\hskip\z@skip\fi}{}%-  }{}%-}-\makeatother-\ifPDFTeX-  \DeclareUnicodeCharacter{200C}{\zerowidthnonjoiner}-\else-  \catcode`^^^^200c=\active-  \protected\def ^^^^200c{\zerowidthnonjoiner}-\fi-%% End of ZWNJ support-$endif$-% Use upquote if available, for straight quotes in verbatim environments-\IfFileExists{upquote.sty}{\usepackage{upquote}}{}-\IfFileExists{microtype.sty}{% use microtype if available-  \usepackage[$for(microtypeoptions)$$microtypeoptions$$sep$,$endfor$]{microtype}-  \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts-}{}-$if(indent)$-$else$-\makeatletter-\@ifundefined{KOMAClassName}{% if non-KOMA class-  \IfFileExists{parskip.sty}{%-    \usepackage{parskip}-  }{% else-    \setlength{\parindent}{0pt}-    \setlength{\parskip}{6pt plus 2pt minus 1pt}}-}{% if KOMA class-  \KOMAoptions{parskip=half}}-\makeatother-$endif$-$if(verbatim-in-note)$-\usepackage{fancyvrb}-$endif$ \usepackage{xcolor} $if(geometry)$-$if(beamer)$-\geometry{$for(geometry)$$geometry$$sep$,$endfor$}-$else$ \usepackage[$for(geometry)$$geometry$$sep$,$endfor$]{geometry} $endif$-$endif$-$if(beamer)$-\newif\ifbibliography-$endif$-$if(listings)$-\usepackage{listings}-\newcommand{\passthrough}[1]{#1}-\lstset{defaultdialect=[5.3]Lua}-\lstset{defaultdialect=[x86masm]Assembler}-$endif$-$if(lhs)$-\lstnewenvironment{code}{\lstset{language=Haskell,basicstyle=\small\ttfamily}}{}-$endif$-$if(highlighting-macros)$-$highlighting-macros$-$endif$-$if(tables)$-\usepackage{longtable,booktabs,array}-$if(multirow)$-\usepackage{multirow}-$endif$-\usepackage{calc} % for calculating minipage widths-$if(beamer)$-\usepackage{caption}-% Make caption package work with longtable-\makeatletter-\def\fnum@table{\tablename~\thetable}-\makeatother-$else$-% Correct order of tables after \paragraph or \subparagraph-\usepackage{etoolbox}-\makeatletter-\patchcmd\longtable{\par}{\if@noskipsec\mbox{}\fi\par}{}{}-\makeatother-% Allow footnotes in longtable head/foot-\IfFileExists{footnotehyper.sty}{\usepackage{footnotehyper}}{\usepackage{footnote}}-\makesavenoteenv{longtable}-$endif$-$endif$-$if(graphics)$-\usepackage{graphicx}-\makeatletter-\def\maxwidth{\ifdim\Gin@nat@width>\linewidth\linewidth\else\Gin@nat@width\fi}-\def\maxheight{\ifdim\Gin@nat@height>\textheight\textheight\else\Gin@nat@height\fi}-\makeatother-% Scale images if necessary, so that they will not overflow the page-% margins by default, and it is still possible to overwrite the defaults-% using explicit options in \includegraphics[width, height, ...]{}-\setkeys{Gin}{width=\maxwidth,height=\maxheight,keepaspectratio}-% Set default figure placement to htbp-\makeatletter-\def\fps@figure{htbp}-\makeatother-$endif$-$if(svg)$-\usepackage{svg}-$endif$-$if(strikeout)$-$-- also used for underline-\ifLuaTeX-  \usepackage{luacolor}-  \usepackage[soul]{lua-ul}-\else-  \usepackage{soul}-$if(beamer)$-  \makeatletter-  \let\HL\hl-  \renewcommand\hl{% fix for beamer highlighting-    \let\set@color\beamerorig@set@color-    \let\reset@color\beamerorig@reset@color-    \HL}-  \makeatother-$endif$-$if(CJKmainfont)$-  \ifXeTeX-    % soul's \st doesn't work for CJK:-    \usepackage{xeCJKfntef}-    \renewcommand{\st}[1]{\sout{#1}}-  \fi-$endif$-\fi+\usepackage{amsmath,amssymb}+$if(cancel)$+\usepackage{cancel} $endif$-\setlength{\emergencystretch}{3em} % prevent overfull lines-\providecommand{\tightlist}{%-  \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}+$--+$-- section numbering+$-- $if(numbersections)$ \setcounter{secnumdepth}{$if(secnumdepth)$$secnumdepth$$else$5$endif$} $else$ \setcounter{secnumdepth}{-\maxdimen} % remove section numbering $endif$-$if(subfigure)$-\usepackage{subcaption}-$endif$-$if(beamer)$-$else$-$if(block-headings)$-% Make \paragraph and \subparagraph free-standing-\makeatletter-\ifx\paragraph\undefined\else-  \let\oldparagraph\paragraph-  \renewcommand{\paragraph}{-    \@ifstar-      \xxxParagraphStar-      \xxxParagraphNoStar-  }-  \newcommand{\xxxParagraphStar}[1]{\oldparagraph*{#1}\mbox{}}-  \newcommand{\xxxParagraphNoStar}[1]{\oldparagraph{#1}\mbox{}}-\fi-\ifx\subparagraph\undefined\else-  \let\oldsubparagraph\subparagraph-  \renewcommand{\subparagraph}{-    \@ifstar-      \xxxSubParagraphStar-      \xxxSubParagraphNoStar-  }-  \newcommand{\xxxSubParagraphStar}[1]{\oldsubparagraph*{#1}\mbox{}}-  \newcommand{\xxxSubParagraphNoStar}[1]{\oldsubparagraph{#1}\mbox{}}-\fi-\makeatother-$endif$-$endif$-$if(pagestyle)$-\pagestyle{$pagestyle$}-$endif$-$if(csl-refs)$-% definitions for citeproc citations-\NewDocumentCommand\citeproctext{}{}-\NewDocumentCommand\citeproc{mm}{%-  \begingroup\def\citeproctext{#2}\cite{#1}\endgroup}-\makeatletter- % allow citations to break across lines- \let\@cite@ofmt\@firstofone- % avoid brackets around text for \cite:- \def\@biblabel#1{}- \def\@cite#1#2{{#1\if@tempswa , #2\fi}}-\makeatother-\newlength{\cslhangindent}-\setlength{\cslhangindent}{1.5em}-\newlength{\csllabelwidth}-\setlength{\csllabelwidth}{3em}-\newenvironment{CSLReferences}[2] % #1 hanging-indent, #2 entry-spacing- {\begin{list}{}{%-  \setlength{\itemindent}{0pt}-  \setlength{\leftmargin}{0pt}-  \setlength{\parsep}{0pt}-  % turn on hanging indent if param 1 is 1-  \ifodd #1-   \setlength{\leftmargin}{\cslhangindent}-   \setlength{\itemindent}{-1\cslhangindent}-  \fi-  % set entry spacing-  \setlength{\itemsep}{#2\baselineskip}}}- {\end{list}}-\usepackage{calc}-\newcommand{\CSLBlock}[1]{\hfill\break\parbox[t]{\linewidth}{\strut\ignorespaces#1\strut}}-\newcommand{\CSLLeftMargin}[1]{\parbox[t]{\csllabelwidth}{\strut#1\strut}}-\newcommand{\CSLRightInline}[1]{\parbox[t]{\linewidth - \csllabelwidth}{\strut#1\strut}}-\newcommand{\CSLIndent}[1]{\hspace{\cslhangindent}#1}-$endif$-$if(lang)$-\ifLuaTeX-\usepackage[bidi=basic]{babel}-\else-\usepackage[bidi=default]{babel}-\fi-$if(babel-lang)$-\babelprovide[main,import]{$babel-lang$}-$if(mainfont)$-\ifPDFTeX-\else-\babelfont{rm}[$for(mainfontoptions)$$mainfontoptions$$sep$,$endfor$$if(mainfontfallback)$,RawFeature={fallback=mainfontfallback}$endif$]{$mainfont$}-\fi-$endif$-$endif$-$for(babel-otherlangs)$-\babelprovide[import]{$babel-otherlangs$}-$endfor$-$for(babelfonts/pairs)$-\babelfont[$babelfonts.key$]{rm}{$babelfonts.value$}-$endfor$-% get rid of language-specific shorthands (see #6817):-\let\LanguageShortHands\languageshorthands-\def\languageshorthands#1{}-$endif$+$fonts.latex()$+$font-settings.latex()$+$common.latex()$ $for(header-includes)$ $header-includes$ $endfor$-\ifLuaTeX-  \usepackage{selnolig}  % disable illegal ligatures+$after-header-includes.latex()$+$hypersetup.latex()$+$if(pdf-trailer-id)$++\ifXeTeX+\special{pdf:trailerid [ $pdf-trailer-id$ ]} \fi-$if(dir)$ \ifPDFTeX-  \TeXXeTstate=1-  \newcommand{\RL}[1]{\beginR #1\endR}-  \newcommand{\LR}[1]{\beginL #1\endL}-  \newenvironment{RTL}{\beginR}{\endR}-  \newenvironment{LTR}{\beginL}{\endL}+\pdftrailerid{}+\pdftrailer{/ID [ $pdf-trailer-id$ ]} \fi-$endif$-$if(natbib)$-\usepackage[$natbiboptions$]{natbib}-\bibliographystyle{$if(biblio-style)$$biblio-style$$else$plainnat$endif$}-$endif$-$if(biblatex)$-\usepackage[$if(biblio-style)$style=$biblio-style$,$endif$$for(biblatexoptions)$$biblatexoptions$$sep$,$endfor$]{biblatex}-$for(bibliography)$-\addbibresource{$bibliography$}-$endfor$-$endif$-$if(nocite-ids)$-\nocite{$for(nocite-ids)$$it$$sep$, $endfor$}-$endif$-$if(csquotes)$-\usepackage{csquotes}-$endif$-\usepackage{bookmark}-\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available-\urlstyle{$if(urlstyle)$$urlstyle$$else$same$endif$}-$if(links-as-notes)$-% Make links footnotes instead of hotlinks:-\DeclareRobustCommand{\href}[2]{#2\footnote{\url{#1}}}-$endif$-$if(verbatim-in-note)$-\VerbatimFootnotes % allow verbatim text in footnotes-$endif$-\hypersetup{-$if(title-meta)$-  pdftitle={$title-meta$},-$endif$-$if(author-meta)$-  pdfauthor={$author-meta$},-$endif$-$if(lang)$-  pdflang={$lang$},-$endif$-$if(subject)$-  pdfsubject={$subject$},-$endif$-$if(keywords)$-  pdfkeywords={$for(keywords)$$keywords$$sep$, $endfor$},-$endif$-$if(colorlinks)$-  colorlinks=true,-  linkcolor={$if(linkcolor)$$linkcolor$$else$Maroon$endif$},-  filecolor={$if(filecolor)$$filecolor$$else$Maroon$endif$},-  citecolor={$if(citecolor)$$citecolor$$else$Blue$endif$},-  urlcolor={$if(urlcolor)$$urlcolor$$else$Blue$endif$},-$else$-$if(boxlinks)$-$else$-  hidelinks,-$endif$+\ifLuaTeX+\pdfvariable trailerid {[ $pdf-trailer-id$ ]}+\fi $endif$-  pdfcreator={LaTeX via pandoc}}  $if(title)$ \title{$title$$if(thanks)$\thanks{$thanks$}$endif$} $endif$ $if(subtitle)$-$if(beamer)$-$else$ \usepackage{etoolbox} \makeatletter \providecommand{\subtitle}[1]{% add subtitle to \maketitle   \apptocmd{\@title}{\par {\large #1 \par}}{}{} } \makeatother-$endif$ \subtitle{$subtitle$} $endif$ \author{$for(author)$$author$$sep$ \and $endfor$} \date{$date$}-$if(beamer)$-$if(institute)$-\institute{$for(institute)$$institute$$sep$ \and $endfor$}-$endif$-$if(titlegraphic)$-\titlegraphic{\includegraphics{$titlegraphic$}}-$endif$-$if(logo)$-\logo{\includegraphics{$logo$}}-$endif$-$endif$  \begin{document} $if(has-frontmatter)$ \frontmatter $endif$ $if(title)$-$if(beamer)$-\frame{\titlepage}-$else$ \maketitle-$endif$ $if(abstract)$ \begin{abstract} $abstract$@@ -566,23 +94,16 @@ $if(toc-title)$ \renewcommand*\contentsname{$toc-title$} $endif$-$if(beamer)$-\begin{frame}[allowframebreaks]-$if(toc-title)$-  \frametitle{$toc-title$}-$endif$-  \tableofcontents[hideallsubsections]-\end{frame}-$else$ { $if(colorlinks)$-\hypersetup{linkcolor=$if(toccolor)$$toccolor$$else$$endif$}+$if(toccolor)$+\hypersetup{linkcolor=$toccolor$} $endif$+$endif$ \setcounter{tocdepth}{$toc-depth$} \tableofcontents } $endif$-$endif$ $if(lof)$ \listoffigures $endif$@@ -600,6 +121,9 @@ $if(has-frontmatter)$ \backmatter $endif$+$if(nocite-ids)$+\nocite{$for(nocite-ids)$$it$$sep$, $endfor$}+$endif$ $if(natbib)$ $if(bibliography)$ $if(biblio-title)$@@ -609,26 +133,12 @@ \renewcommand\refname{$biblio-title$} $endif$ $endif$-$if(beamer)$-\begin{frame}[allowframebreaks]{$biblio-title$}-  \bibliographytrue-$endif$-  \bibliography{$for(bibliography)$$bibliography$$sep$,$endfor$}-$if(beamer)$-\end{frame}-$endif$+\bibliography{$for(bibliography)$$bibliography$$sep$,$endfor$}  $endif$ $endif$ $if(biblatex)$-$if(beamer)$-\begin{frame}[allowframebreaks]{$biblio-title$}-  \bibliographytrue-  \printbibliography[heading=none]-\end{frame}-$else$ \printbibliography$if(biblio-title)$[title=$biblio-title$]$endif$-$endif$  $endif$ $for(include-after)$
data/templates/default.man view
@@ -8,7 +8,7 @@ $if(adjusting)$ .ad $adjusting$ $endif$-.TH "$title/nowrap$" "$section/nowrap$" "$date/nowrap$" "$footer/nowrap$" "$header/nowrap$"+.TH "$title/nowrap$" "$section/nowrap$" "$date/nowrap$" "$footer/nowrap$"$if(header)$ "$header/nowrap$"$endif$ $for(header-includes)$ $header-includes$ $endfor$
data/templates/default.ms view
@@ -35,7 +35,7 @@ .\" line height .nr VS $if(lineheight)$$lineheight$$else$12p$endif$ .\" font family: A, BM, H, HN, N, P, T, ZCM-.fam $if(fontfamily)$$fontfamily$$else$P$endif$+.fam $if(fontfamily)$$fontfamily$$else$T$endif$ .\" paragraph indent .nr PI $if(indent)$$indent$$else$0m$endif$ .\" interparagraph space@@ -50,10 +50,6 @@ $endif$ .\" color used for strikeout .defcolor strikecolor rgb 0.7 0.7 0.7-.\" color for links (rgb)-.ds PDFHREF.COLOUR   0.35 0.00 0.60-.\" border for links (default none)-.ds PDFHREF.BORDER   0 0 0 .\" point size difference between heading levels .nr PSINCR 1p .\" heading level above which point size no longer changes@@ -64,14 +60,6 @@ .\" page numbers in footer, centered .ds CH .ds CF %-.\" pdf outline fold level-.nr PDFOUTLINE.FOLDLEVEL 3-.\" start out in outline view-.pdfview /PageMode /UseOutlines-.\" ***************************************************************-.\" PDF metadata-.pdfinfo /Title "$title-meta$"-.pdfinfo /Author "$author-meta$" $if(adjusting)$ .ad $adjusting$ $endif$@@ -84,6 +72,20 @@ .EQ delim @@ .EN+$endif$+$if(pdf-engine)$+.\" color for links (rgb)+.ds PDFHREF.COLOUR   0.35 0.00 0.60+.\" border for links (default none)+.ds PDFHREF.BORDER   0 0 0+.\" pdf outline fold level+.nr PDFOUTLINE.FOLDLEVEL 3+.\" start out in outline view+.pdfview /PageMode /UseOutlines+.\" ***************************************************************+.\" PDF metadata+.pdfinfo /Title "$title-meta$"+.pdfinfo /Author "$author-meta$" $endif$ $for(header-includes)$ $header-includes$
+ data/templates/default.openxml view
@@ -0,0 +1,65 @@+<?xml version="1.0" encoding="UTF-8"?>+<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing">+<w:body>+$if(title)$+    <w:p>+      <w:pPr>+        <w:pStyle w:val="$title-style-id$" />+      </w:pPr>+      $title$+    </w:p>+$endif$+$if(subtitle)$+    <w:p>+      <w:pPr>+        <w:pStyle w:val="$subtitle-style-id$" />+      </w:pPr>+      $subtitle$+    </w:p>+$endif$+$for(author)$+    <w:p>+      <w:pPr>+        <w:pStyle w:val="$author-style-id$" />+      </w:pPr>+      $author$+    </w:p>+$endfor$+$if(date)$+    <w:p>+      <w:pPr>+        <w:pStyle w:val="$date-style-id$" />+      </w:pPr>+      $date$+    </w:p>+$endif$+$if(abstract)$+$if(abstract-title)$+    <w:p>+      <w:pPr>+        <w:pStyle w:val="$abstract-title-style-id$" />+      </w:pPr>+      <w:r><w:t xml:space="preserve">$abstract-title$</w:t></w:r>+    </w:p>+$endif$+    $abstract$+$endif$+$for(include-before)$+    $include-before$+$endfor$+$if(toc)$+    $toc$+$endif$+$if(lof)$+    $lof$+$endif$+$if(lot)$+    $lot$+$endif$+    $body$+$for(include-after)$+    $include-after$+$endfor$+    $sectpr$+  </w:body>+</w:document>
data/templates/default.org view
@@ -9,6 +9,12 @@ #+date: $date$  $endif$+$if(options/pairs)$+$for(options/pairs)$+#+options: ${it.key}:${it.value}+$endfor$++$endif$ $for(header-includes)$ $header-includes$ 
data/templates/default.revealjs view
@@ -29,6 +29,9 @@ $else$   <link rel="stylesheet" href="$revealjs-url$/dist/theme/black.css" id="theme"> $endif$+$if(highlight-js)$+  <link rel="stylesheet" href="$revealjs-url$/plugin/highlight/$highlightjs-theme$.css">+$endif$ $for(css)$   <link rel="stylesheet" href="$css$"/> $endfor$@@ -87,6 +90,9 @@ $if(mathjax)$   <script src="$revealjs-url$/plugin/math/math.js"></script> $endif$+$if(highlight-js)$+  <script src="$revealjs-url$/plugin/highlight/highlight.js"></script>+$endif$    <script> @@ -232,6 +238,29 @@         // devices. It is advisable to set this to a lower number than         // viewDistance in order to save resources.         mobileViewDistance: $mobileViewDistance$,+$if(view)$++        // 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$,+        // see https://revealjs.com/scroll-view/#scroll-snapping+$if(scrollSnap)$+        scrollSnap: '$scrollSnap/nowrap$',+$else$+        scrollSnap: false,+$endif$+        // Experimental. see https://revealjs.com/scroll-view/#scroll-snapping+        scrollLayout: '$scrollLayout/nowrap$',+$endif$ $if(parallaxBackgroundImage)$          // Parallax background image@@ -307,6 +336,9 @@         plugins: [ $if(mathjax)$           RevealMath,+$endif$+$if(highlight-js)$+          RevealHighlight, $endif$           RevealNotes,           RevealSearch,
data/templates/default.texinfo view
@@ -1,4 +1,11 @@-\input texinfo+\input texinfo  @c -*-texinfo-*-+$if(filename)$+@setfilename $filename$+$endif$+$if(title)$+@settitle $title$$if(version)$ $version$$endif$+$endif$+ @documentencoding UTF-8 $for(header-includes)$ $header-includes$@@ -16,6 +23,9 @@ $if(titlepage)$ @titlepage @title $title$+$if(version)$+@subtitle $version$+$endif$ $for(author)$ @author $author$ $endfor$
data/templates/default.typst view
@@ -1,38 +1,59 @@-$definitions.typst()$+#let horizontalrule = line(start: (25%,0%), end: (75%,0%)) -#show terms: it => {-  it.children-    .map(child => [-      #strong[#child.term]-      #block(inset: (left: 1.5em, top: -0.4em))[#child.description]-      ])-    .join()-}+#show terms.item: it => block(breakable: false)[+  #text(weight: "bold")[#it.term]+  #block(inset: (left: 1.5em, top: -0.4em))[#it.description]+]  #set table(   inset: 6pt,   stroke: none ) +#show figure.where(+  kind: table+): set figure.caption(position: $if(table-caption-position)$$table-caption-position$$else$top$endif$)++#show figure.where(+  kind: image+): set figure.caption(position: $if(figure-caption-position)$$figure-caption-position$$else$bottom$endif$)++$if(highlighting-definitions)$+// syntax highlighting functions from skylighting:+$highlighting-definitions$++$endif$ $if(template)$ #import "$template$": conf $else$ $template.typst()$ $endif$ +$if(smart)$+$else$+#set smartquote(enabled: false)++$endif$+$for(header-includes)$+$header-includes$++$endfor$ #show: doc => conf( $if(title)$   title: [$title$], $endif$+$if(subtitle)$+  subtitle: [$subtitle$],+$endif$ $if(author)$   authors: ( $for(author)$ $if(author.name)$-    ( name: "$author.name$",-      affiliation: "$author.affiliation$",-      email: "$author.email$" ),+    ( name: [$author.name$],+      affiliation: [$author.affiliation$],+      email: [$author.email$] ), $else$-    ( name: "$author$",+    ( name: [$author$],       affiliation: "",       email: "" ), $endif$@@ -40,10 +61,10 @@     ), $endif$ $if(keywords)$-  keywords: ($for(keywords)$$keyword$$sep$,$endfor$),+  keywords: ($for(keywords)$$keywords$$sep$,$endfor$), $endif$ $if(date)$-  date: "$date$",+  date: [$date$], $endif$ $if(lang)$   lang: "$lang$",@@ -51,9 +72,15 @@ $if(region)$   region: "$region$", $endif$+$if(abstract-title)$+  abstract-title: [$abstract-title$],+$endif$ $if(abstract)$   abstract: [$abstract$], $endif$+$if(thanks)$+  thanks: [$thanks$],+$endif$ $if(margin)$   margin: ($for(margin/pairs)$$margin.key$: $margin.value$,$endfor$), $endif$@@ -66,17 +93,32 @@ $if(fontsize)$   fontsize: $fontsize$, $endif$+$if(mathfont)$+  mathfont: ($for(mathfont)$"$mathfont$",$endfor$),+$endif$+$if(codefont)$+  codefont: ($for(codefont)$"$codefont$",$endfor$),+$endif$+$if(linestretch)$+  linestretch: $linestretch$,+$endif$ $if(section-numbering)$   sectionnumbering: "$section-numbering$", $endif$+  pagenumbering: $if(page-numbering)$"$page-numbering$"$else$none$endif$,+$if(linkcolor)$+  linkcolor: [$linkcolor$],+$endif$+$if(citecolor)$+  citecolor: [$citecolor$],+$endif$+$if(filecolor)$+  filecolor: [$filecolor$],+$endif$   cols: $if(columns)$$columns$$else$1$endif$,   doc, ) -$for(header-includes)$-$header-includes$--$endfor$ $for(include-before)$ $include-before$ @@ -91,6 +133,9 @@ $body$  $if(citations)$+$for(nocite-ids)$+#cite(label("${it}"), form: none)+$endfor$ $if(csl)$  #set bibliography(style: "$csl$")@@ -100,7 +145,7 @@ $endif$ $if(bibliography)$ -#bibliography($for(bibliography)$"$bibliography$"$sep$,$endfor$)+#bibliography(($for(bibliography)$"$bibliography$"$sep$,$endfor$)$if(full-bibliography)$, full: true$endif$) $endif$ $endif$ $for(include-after)$
+ data/templates/default.vimdoc view
@@ -0,0 +1,16 @@+$if(filename)$*${filename}*	$endif$$if(abstract)$${abstract}$endif$$if(filename)$+++$endif$$if(combined-title)$${combined-title}+++$endif$$toc-reminder$++$if(toc)$+$toc$++$endif$++$body$++ $modeline$
− data/templates/definitions.typst
@@ -1,8 +0,0 @@-// Some definitions presupposed by pandoc's typst output.-#let horizontalrule = [-  #line(start: (25%,0%), end: (75%,0%))-]--#let endnote(num, contents) = [-  #stack(dir: ltr, spacing: 3pt, super[#num], contents)-]
+ data/templates/document-metadata.latex view
@@ -0,0 +1,20 @@+$--+$-- PDF standard support (PDF/A, PDF/UA, PDF/X)+$-- Requires LuaLaTeX and recent LaTeX (2023+)+$--+$if(pdfstandard)$+\DocumentMetadata{+$if(pdfstandard.version)$+  pdfversion=$pdfstandard.version$,+$endif$+$if(pdfstandard.standards)$+  pdfstandard={$for(pdfstandard.standards)$$it$$sep$,$endfor$},+$endif$+$if(pdfstandard.tagging)$+  tagging=on,+$endif$+$if(lang)$+  lang=$lang$,+$endif$+  xmp=true}+$endif$
+ data/templates/font-settings.latex view
@@ -0,0 +1,103 @@+$-- User font settings (must come after default font and Beamer theme)+$if(fontfamily)$+\usepackage[$for(fontfamilyoptions)$$fontfamilyoptions$$sep$,$endfor$]{$fontfamily$}+$endif$+\ifPDFTeX\else+  % xetex/luatex font selection+$if(mainfont)$+$if(mainfontfallback)$+  \ifLuaTeX+    \usepackage{luaotfload}+    \directlua{luaotfload.add_fallback("mainfontfallback",{+      $for(mainfontfallback)$"$mainfontfallback$"$sep$,$endfor$+    })}+  \fi+$endif$+  \setmainfont[$for(mainfontoptions)$$mainfontoptions$$sep$,$endfor$$if(mainfontfallback)$,RawFeature={fallback=mainfontfallback}$endif$]{$mainfont$}+$endif$+$if(sansfont)$+$if(sansfontfallback)$+  \ifLuaTeX+    \usepackage{luaotfload}+    \directlua{luaotfload.add_fallback("sansfontfallback",{+      $for(sansfontfallback)$"$sansfontfallback$"$sep$,$endfor$+    })}+  \fi+$endif$+  \setsansfont[$for(sansfontoptions)$$sansfontoptions$$sep$,$endfor$$if(sansfontfallback)$,RawFeature={fallback=sansfontfallback}$endif$]{$sansfont$}+$endif$+$if(monofont)$+$if(monofontfallback)$+  \ifLuaTeX+    \usepackage{luaotfload}+    \directlua{luaotfload.add_fallback("monofontfallback",{+      $for(monofontfallback)$"$monofontfallback$"$sep$,$endfor$+    })}+  \fi+$endif$+  \setmonofont[$for(monofontoptions)$$monofontoptions$$sep$,$endfor$$if(monofontfallback)$,RawFeature={fallback=monofontfallback}$endif$]{$monofont$}+$endif$+$for(fontfamilies)$+  \newfontfamily{$fontfamilies.name$}[$for(fontfamilies.options)$$fontfamilies.options$$sep$,$endfor$]{$fontfamilies.font$}+$endfor$+$if(mathfont)$+$if(mathspec)$+  \ifXeTeX+    \setmathfont(Digits,Latin,Greek)[$for(mathfontoptions)$$mathfontoptions$$sep$,$endfor$]{$mathfont$}+  \else+    \setmathfont[$for(mathfontoptions)$$mathfontoptions$$sep$,$endfor$]{$mathfont$}+  \fi+$else$+  \setmathfont[$for(mathfontoptions)$$mathfontoptions$$sep$,$endfor$]{$mathfont$}+$endif$+$endif$+$if(CJKmainfont)$+  \ifXeTeX+    \usepackage{xeCJK}+    \setCJKmainfont[$for(CJKoptions)$$CJKoptions$$sep$,$endfor$]{$CJKmainfont$}+$if(CJKsansfont)$+    \setCJKsansfont[$for(CJKoptions)$$CJKoptions$$sep$,$endfor$]{$CJKsansfont$}+$endif$+$if(CJKmonofont)$+    \setCJKmonofont[$for(CJKoptions)$$CJKoptions$$sep$,$endfor$]{$CJKmonofont$}+$endif$+  \fi+$endif$+$if(luatexjapresetoptions)$+  \ifLuaTeX+    \usepackage[$for(luatexjapresetoptions)$$luatexjapresetoptions$$sep$,$endfor$]{luatexja-preset}+  \fi+$endif$+$if(CJKmainfont)$+  \ifLuaTeX+    \usepackage[$for(luatexjafontspecoptions)$$luatexjafontspecoptions$$sep$,$endfor$]{luatexja-fontspec}+    \setmainjfont[$for(CJKoptions)$$CJKoptions$$sep$,$endfor$]{$CJKmainfont$}+  \fi+$endif$+\fi+$if(zero-width-non-joiner)$+%% Support for zero-width non-joiner characters.+\makeatletter+\def\zerowidthnonjoiner{%+  % Prevent ligatures and adjust kerning, but still support hyphenating.+  \texorpdfstring{%+    \TextOrMath{\nobreak\discretionary{-}{}{\kern.03em}%+      \ifvmode\else\nobreak\hskip\z@skip\fi}{}%+  }{}%+}+\makeatother+\ifPDFTeX+  \DeclareUnicodeCharacter{200C}{\zerowidthnonjoiner}+\else+  \catcode`^^^^200c=\active+  \protected\def ^^^^200c{\zerowidthnonjoiner}+\fi+%% End of ZWNJ support+$endif$+% Use upquote if available, for straight quotes in verbatim environments+\IfFileExists{upquote.sty}{\usepackage{upquote}}{}+\IfFileExists{microtype.sty}{% use microtype if available+  \usepackage[$for(microtypeoptions)$$microtypeoptions$$sep$,$endfor$]{microtype}+  \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts+}{}+
+ data/templates/fonts.latex view
@@ -0,0 +1,23 @@+\usepackage{iftex}+\ifPDFTeX+  \usepackage[$if(fontenc)$$fontenc$$else$T1$endif$]{fontenc}+  \usepackage[utf8]{inputenc}+  \usepackage{textcomp} % provide euro and other symbols+\else % if luatex or xetex+$if(mathspec)$+  \ifXeTeX+    \usepackage{mathspec} % this also loads fontspec+  \else+    \usepackage{unicode-math} % this also loads fontspec+  \fi+$else$+  \usepackage{unicode-math} % this also loads fontspec+$endif$+  \defaultfontfeatures{Scale=MatchLowercase}$-- must come before Beamer theme+  \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1}+\fi+$if(fontfamily)$+$else$+$-- Set default font before Beamer theme so the theme can override it+\usepackage{lmodern}+$endif$
+ data/templates/hypersetup.latex view
@@ -0,0 +1,34 @@+% fallback for those not using the hyperref driver hyperxmp:+\makeatletter+\@ifundefined{xmpquote}{\newcommand{\xmpquote}[1]{#1}}{}+\makeatother+\hypersetup{+$if(title-meta)$+  pdftitle={$title-meta$},+$endif$+$if(author-meta)$+  pdfauthor={$author-meta$},+$endif$+$if(lang)$+  pdflang={$lang$},+$endif$+$if(subject)$+  pdfsubject={$subject$},+$endif$+$if(keywords)$+  pdfkeywords={$for(keywords)$\xmpquote{$keywords$}$sep$, $endfor$},+$endif$+$if(colorlinks)$+  colorlinks=true,+  linkcolor={$if(linkcolor)$$linkcolor$$else$Maroon$endif$},+  filecolor={$if(filecolor)$$filecolor$$else$Maroon$endif$},+  citecolor={$if(citecolor)$$citecolor$$else$Blue$endif$},+  urlcolor={$if(urlcolor)$$urlcolor$$else$Blue$endif$},+$else$+$if(boxlinks)$+$else$+  hidelinks,+$endif$+$endif$+  pdfcreator={LaTeX via pandoc}}+
+ data/templates/passoptions.latex view
@@ -0,0 +1,9 @@+% Options for packages loaded elsewhere+\PassOptionsToPackage{unicode$for(hyperrefoptions)$,$hyperrefoptions$$endfor$}{hyperref}+\PassOptionsToPackage{hyphens}{url}+$if(colorlinks)$+\PassOptionsToPackage{dvipsnames,svgnames,x11names}{xcolor}+$endif$+$if(CJKmainfont)$+\PassOptionsToPackage{space}{xeCJK}+$endif$
data/templates/styles.html view
@@ -1,3 +1,6 @@+/* Default styles provided by pandoc.+** See https://pandoc.org/MANUAL.html#variables-for-html for config info.+*/ $if(document-css)$ html { $if(mainfont)$@@ -103,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$;@@ -130,8 +134,8 @@  overflow: visible; } hr {-  background-color: #1a1a1a;   border: none;+  border-top: 1px solid #1a1a1a;   height: 1px;   margin: 1em 0; }@@ -144,7 +148,12 @@   font-variant-numeric: lining-nums tabular-nums; } table caption {+$if(table-caption-below)$+  caption-side: bottom;+  margin-top: 0.75em;+$else$   margin-bottom: 0.75em;+$endif$ } tbody {   margin-top: 0.5em;@@ -175,10 +184,13 @@   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;}+div.columns{display: flex; gap: 1.5em;}+div.column{flex: auto;}+@media screen {+div.columns{gap: min(4vw, 1.5em);}+div.column{overflow-x: auto;}+} div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;} /* The extra [class] is a hack that increases specificity enough to    override a similar rule in reveal.js */
data/templates/template.typst view
@@ -1,73 +1,120 @@+#let content-to-string(content) = {+  if content.has("text") {+    content.text+  } else if content.has("children") {+    content.children.map(content-to-string).join("")+  } else if content.has("body") {+    content-to-string(content.body)+  } else if content == [ ] {+    " "+  }+} #let conf(   title: none,+  subtitle: none,   authors: (),   keywords: (),   date: none,+  abstract-title: none,   abstract: none,+  thanks: none,   cols: 1,   margin: (x: 1.25in, y: 1.25in),   paper: "us-letter",   lang: "en",   region: "US",-  font: (),+  font: none,   fontsize: 11pt,+  mathfont: none,+  codefont: none,+  linestretch: 1,   sectionnumbering: none,+  linkcolor: none,+  citecolor: none,+  filecolor: none,+  pagenumbering: "1",   doc, ) = {   set document(     title: title,-    author: authors.map(author => author.name),     keywords: keywords,   )+  set document(+      author: authors.map(author => content-to-string(author.name)).join(", ", last: " & "),+  ) if authors != none and authors != ()   set page(     paper: paper,     margin: margin,-    numbering: "1",+    numbering: pagenumbering,+    columns: cols   )-  set par(justify: true)++  set par(+    justify: true,+    leading: linestretch * 0.65em+  )   set text(lang: lang,            region: region,-           font: font,            size: fontsize)++  set text(font: font) if font != none+  show math.equation: set text(font: mathfont) if mathfont != none+  show raw: set text(font: codefont) if codefont != none+   set heading(numbering: sectionnumbering) -  if title != none {-    align(center)[#block(inset: 2em)[-      #text(weight: "bold", size: 1.5em)[#title]-    ]]+  show link: set text(fill: rgb(content-to-string(linkcolor))) if linkcolor != none+  show ref: set text(fill: rgb(content-to-string(citecolor))) if citecolor != none+  show link: this => {+    if filecolor != none and type(this.dest) == label {+      text(this, fill: rgb(content-to-string(filecolor)))+    } else {+      text(this)+    }   } -  if authors != none and authors != [] {-    let count = authors.len()-    let ncols = calc.min(count, 3)-    grid(-      columns: (1fr,) * ncols,-      row-gutter: 1.5em,-      ..authors.map(author =>-          align(center)[+  if title != none {+    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 {+                footnote(thanks, numbering: "*")+                counter(footnote).update(n => n - 1)+              }]+            #(+              if subtitle != none {+                parbreak()+                text(weight: "bold", size: 1.25em, hyphenate: false)[#subtitle]+              }+             )])+      }++      #if authors != none and authors != [] {+        let count = authors.len()+        let ncols = calc.min(count, 3)+        grid(+          columns: (1fr,) * ncols,+          row-gutter: 1.5em,+          ..authors.map(author => align(center)[             #author.name \             #author.affiliation \             #author.email-          ]-      )-    )-  }--  if date != none {-    align(center)[#block(inset: 1em)[-      #date-    ]]-  }+          ])+        )+      } -  if abstract != none {-    block(inset: 2em)[-    #text(weight: "semibold")[Abstract] #h(1em) #abstract-    ]-  }+      #if date != none {+        align(center)[#block(inset: 1em)[+            #date+          ]]+      } -  if cols == 1 {-    doc-  } else {-    columns(cols, doc)+      #if abstract != none {+        block(inset: 2em)[+          #text(weight: "semibold")[#abstract-title] #h(1em) #abstract+        ]+      }+    ])   }+  doc }
+ data/translations/af.yaml view
@@ -0,0 +1,20 @@+Abstract: Samevatting+Appendix: Bylae+Bibliography: Bibliografie+Cc: a.a.+Chapter: Hoofstuk+Contents: Inhoudsopgawe+Encl: Bylae(n)+Figure: Figuur+Index: Inhoud+ListOfFigures: Lys van figure+ListOfTables: Lys van tabelle+Page: Bladsy+Part: Deel+Preface: Voorwoord+Proof: Bewys+References: Verwysings+See: sien+SeeAlso: sien ook+Table: Tabel+To: Aan
+ data/translations/alt.yaml view
@@ -0,0 +1,5 @@+Chapter: Бажалык+Contents: Бажалыктар+Figure: Јурук+Glossary: Сӧзлик+Preface: Сӧс бажы
data/translations/ar.yaml view
@@ -1,20 +1,21 @@-Preface: ﻡﺪﺨﻟ-References: ﺎﻠﻣﺭﺎﺠﻋ-Abstract: ﻢﻠﺨﺻ-Bibliography: ﺎﻠﻤﺻﺍﺩﺭ-Chapter: ﺏﺎﺑ-Appendix: ﺎﻠﻣﻼﺤﻗ-Contents: ﺎﻠﻤﺤﺗﻮﻳﺎﺗ-ListOfFigures: ﻕﺎﺌﻣﺓ ﺍﻸﺸﻛﺎﻟ-ListOfTables: ﻕﺎﺌﻣﺓ ﺎﻠﺟﺩﺍﻮﻟ-Index: ﺎﻠﻔﻫﺮﺳ-Figure: ﺶﻜﻟ-Table: ﺝﺩﻮﻟ-Part: ﺎﻠﻘﺴﻣ-Encl: ﺎﻠﻣﺮﻔﻗﺎﺗ-To: ﺈﻟﻯ-Page: ﺺﻔﺣﺓ-See: ﺭﺎﺠﻋ-SeeAlso: ﺭﺎﺠﻋ ﺄﻴﺿًﺍ-Proof: ﺏﺮﻫﺎﻧ-Glossary: ﻕﺎﻣﻮﺳ+Abstract: ملخص+Appendix: الملاحق+Bibliography: المصادر+Cc: نسخة ل‬+Chapter: باب+Contents: المحتويات+Encl: المرفقات+Figure: شكل+Glossary: قاموس+Index: الفهرس+ListOfFigures: قائمة الأشكال+ListOfTables: قائمة الجداول+Page: صفحة+Part: القسم+Preface: مدخل+Proof: برهان+References: المراجع+See: راجع+SeeAlso: راجع أيضًا+Table: جدول+To: إلى
+ data/translations/as.yaml view
@@ -0,0 +1,21 @@+Abstract: মূলভাৱ+Appendix: পৰিশিষ্ট+Bibliography: তথ্যসূত্ৰ+Cc: প্ৰতিলিপি+Chapter: অধ্যায়+Contents: সমল+Encl: সংযোজিত+Figure: চিত্ৰ+Glossary: অৰ্থকোষ+Index: বিষয়সূচী+ListOfFigures: চিত্ৰসূচী+ListOfTables: তালিকাসূচী+Page: পৃষ্ঠা+Part: অংশ+Preface: পাতনি+Proof: প্ৰমাণ+References: প্ৰসংগ+See: চাওক+SeeAlso: ও+Table: তালিকা+To: মুখে
+ data/translations/ast.yaml view
@@ -0,0 +1,21 @@+Abstract: Sumariu+Appendix: Apéndiz+Bibliography: Bibliografía+Cc: cc+Chapter: Capítulu+Contents: Conteníu+Encl: incl.+Figure: Figura+Glossary: Glosariu+Index: Índiz+ListOfFigures: Llista de figures+ListOfTables: Llista de tables+Page: Páxina+Part: Parte+Preface: Entamu+Proof: Demostración+References: Referencies+See: ver+SeeAlso: ver tamién+Table: Tabla+To: Pa
+ data/translations/az.yaml view
@@ -0,0 +1,21 @@+Abstract: Annotasiya+Appendix: Əlavə+Bibliography: Ədəbiyyat+Cc: cc+Chapter: Fəsil+Contents: Mündəricat+Encl: encl+Figure: Şəkil+Glossary: Terminlər lüğəti+Index: Mövzu göstəricisi+ListOfFigures: Şəkillərin siyahısı+ListOfTables: Cədvəllərin siyahısı+Page: səh.+Part: Hissə+Preface: Ön söz+Proof: İsbatı+References: Ədəbiyyat+See: baxın+SeeAlso: həmçinin baxın+Table: Cədvəl+To: To
+ data/translations/be.yaml view
@@ -0,0 +1,21 @@+Abstract: Анатацыя+Appendix: Дадатак+Bibliography: Літаратура+Cc: зых.+Chapter: Глава+Contents: Зьмест+Encl: укл.+Figure: Рыс.+Glossary: Слоўнік тэрмінаў+Index: Прадметны паказальнік+ListOfFigures: Сьпіс ілюстрацый+ListOfTables: Сьпіс табліц+Page: с.+Part: Частка+Preface: Прадмова+Proof: Доказ+References: Сьпіс літаратуры+See: гл.+SeeAlso: гл. таксама+Table: Табліца+To: вх.
data/translations/bg.yaml view
@@ -6,14 +6,16 @@ Contents: Съдържание Encl: Приложения Figure: Фигура-Glossary: Glossary+Glossary: Притурка Index: Азбучен указател ListOfFigures: Списък на фигурите ListOfTables: Списък на таблиците Page: Стр.+Part: Част Preface: Предговор-Proof: Proof+Proof: Доказателство References: Литература See: вж.-SeeAlso: вж. също и+SeeAlso: вж. също и Table: Таблица+To: За
+ data/translations/bo.yaml view
@@ -0,0 +1,14 @@+Abstract: གནད་བསྡུས།+Appendix: ཞར་བྱུང་།+Bibliography: དཔེ་ཆའི་ཐོ་གཞུང་།+Cc: འདྲ་བཤུས་ལེན་མཁན་+Chapter: ལེའུ་+Contents: དཀར་ཆག།+Figure: པར་རིས་+Glossary: མིང་ཚིག་རེའུ་མིག།+Index: གསུལ་བྱང་།+Page: ཤོག་+Part: ཆ་ཤས་+Preface: དཔེ་དེབ་ཀྱི་གླེང་བརྗོད།+Proof: བདེན་དཔང་།+Table: རེའུ་མིག་
+ data/translations/br.yaml view
@@ -0,0 +1,21 @@+Abstract: Dvierrañ+Appendix: Stagadenn+Bibliography: Lennadurezh+Cc: Eilskrid da+Chapter: Pennad+Contents: Taolenn+Encl: Dielloù kevret+Figure: Figurenn+Glossary: Glossary+Index: Meneger+ListOfFigures: Listenn ar Figurennoù+ListOfTables: Listenn an taolennoù+Page: Pajenn+Part: Lodenn+Preface: Rakskrid+Proof: Proof+References: Daveennoù+See: Gwelout+SeeAlso: Gwelout ivez+Table: Taolenn+To: evit
+ data/translations/bs.yaml view
@@ -0,0 +1,21 @@+Abstract: Sažetak+Appendix: Dodatak+Bibliography: Bibliografija+Cc: Kopija+Chapter: Poglavlje+Contents: Sadržaj+Encl: Prilozi+Figure: Slika+Glossary: Rječnik+Index: Indeks+ListOfFigures: Popis slika+ListOfTables: Popis tabela+Page: Stranica+Part: Dio+Preface: Predgovor+Proof: Dokaz+References: Literatura+See: Vidjeti+SeeAlso: Također vidjeti+Table: Tabela+To: Prima
+ data/translations/bua.yaml view
@@ -0,0 +1,17 @@+Abstract: Тобшолол+Appendix: Хабсаралта+Bibliography: Ном зүй+Chapter: Бүлэг+Contents: Гаршаг+Encl: Оруулаха+Figure: Зураг+Index: Бүгэд хэлхээс+ListOfFigures: Зурагай жагсаалт+ListOfTables: Хүснэгэтэй жагсаалт+Page: Хуудаһан+Part: Бүлэг+Preface: Оршол+References: Ашаглаһан ном+See: Үз+SeeAlso: Mүн үз+Table: Хүсэнэгт
+ data/translations/ckb-Arab.yaml view
@@ -0,0 +1,21 @@+Abstract: پوختە+Appendix: پاشکۆ+Bibliography: کتێبنامە+Cc: ڕوونووس+Chapter: بەندی+Contents: نێوەڕۆک+Encl: هاوپێچ+Figure: وێنەی+Glossary: فەرهەنگۆک+Index: پێنوێن+ListOfFigures: لیستی وێنەکان+ListOfTables: لیستی خشتەکان+Page: لاپەڕە+Part: بەشی+Preface: پێشەكی+Proof: سەلماندن+References: سەرچاوەکان+See: چاو لێکەن+SeeAlso: هەروەها چاو لێکەن+Table: خشتەی+To: بۆ
+ data/translations/ckb-Latn.yaml view
@@ -0,0 +1,21 @@+Abstract: Puxte+Appendix: Paşko+Bibliography: Kitêbname+Cc: Rûnûs+Chapter: Bendî+Contents: Nêwerrok+Encl: Hawpêç+Figure: Wêney+Glossary: Ferhengok+Index: Pêrrist+ListOfFigures: Lîstî Wênekan+ListOfTables: Lîstî Xiştekan+Page: Laperre+Part: Beşî+Preface: Pêşekî+Proof: Selmandin+References: Serçawekan+See: Çaw lêken+SeeAlso: Herweha çaw lêken+Table: Xiştey+To: Bo
data/translations/cs.yaml view
@@ -1,13 +1,13 @@ Abstract: Abstrakt-Appendix: Dodatek+Appendix: Příloha Bibliography: Literatura-Cc: 'Na vědomí:'+Cc: Na vědomí Chapter: Kapitola Contents: Obsah Encl: Příloha Figure: Obrázek Glossary: Slovník-Index: Index+Index: Rejstřík ListOfFigures: Seznam obrázků ListOfTables: Seznam tabulek Page: Strana@@ -16,6 +16,6 @@ Proof: Důkaz References: Reference See: viz-SeeAlso: viz+SeeAlso: viz také Table: Tabulka To: Komu
+ data/translations/cu.yaml view
@@ -0,0 +1,21 @@+Abstract: Аннотация+Appendix: Приложение+Bibliography: Литература+Cc: исх.+Chapter: Глава+Contents: Содержание+Encl: вкл.+Figure: Рис.+Glossary: Словарь терминов+Index: Предметный указатель+ListOfFigures: Список иллюстраций+ListOfTables: Список таблиц+Page: с.+Part: Часть+Preface: Предисловие+Proof: Доказательство+References: Список литературы+See: см.+SeeAlso: см. также+Table: Таблица+To: вх.
+ data/translations/cy.yaml view
@@ -0,0 +1,21 @@+Abstract: Crynodeb+Appendix: Atodiad+Bibliography: Llyfryddiaeth+Cc: copïau+Chapter: Pennod+Contents: Cynnwys+Encl: amgaeëdig+Figure: Darlun+Glossary: Rhestr termau+Index: Mynegai+ListOfFigures: Rhestr Ddarluniau+ListOfTables: Rhestr Dablau+Page: tudalen+Part: Rhan+Preface: Rhagair+Proof: Prawf+References: Cyfeiriadau+See: gweler+SeeAlso: gweler hefyd+Table: Taflen+To: At
+ data/translations/cz.yaml view
@@ -0,0 +1,21 @@+Abstract: Abstrakt+Appendix: Dodatek+Bibliography: Literatura+Cc: Na vědomí+Chapter: Kapitola+Contents: Obsah+Encl: Příloha+Figure: Obrázek+Glossary: Slovník+Index: Index+ListOfFigures: Seznam obrázků+ListOfTables: Seznam tabulek+Page: Strana+Part: Část+Preface: Předmluva+Proof: Důkaz+References: Reference+See: viz+SeeAlso: viz+Table: Tabulka+To: Komu
data/translations/da.yaml view
@@ -1,7 +1,7 @@ Abstract: Resumé Appendix: Bilag Bibliography: Litteratur-Cc: Kopi til}+Cc: Kopi til Chapter: Kapitel Contents: Indhold Encl: Vedlagt@@ -18,4 +18,4 @@ See: Se SeeAlso: Se også Table: Tabel-To: Til}+To: Til
+ data/translations/dsb.yaml view
@@ -0,0 +1,21 @@+Abstract: Abstrakt+Appendix: Dodawki+Bibliography: Literatura+Cc: CC+Chapter: Kapitl+Contents: Wopśimjeśe+Encl: Pśiłoga+Figure: Wobraz+Glossary: Glossary+Index: Indeks+ListOfFigures: Zapis wobrazow+ListOfTables: Zapis tabulkow+Page: Strona+Part: Źěl+Preface: Zawod+Proof: Proof+References: Referency+See: gl.+SeeAlso: gl.~teke+Table: Tabulka+To: Komu
data/translations/el.yaml view
@@ -8,8 +8,8 @@ Figure: Σχήμα Glossary: Γλωσσάρι Index: Ευρετήριο-ListOfFigures: Κατάλογος σχημάτων-ListOfTables: Κατάλογος πινάκων+ListOfFigures: Κατάλογος Σχημάτων+ListOfTables: Κατάλογος Πινάκων Page: Σελίδα Part: Μέρος Preface: Πρόλογος
data/translations/en.yaml view
@@ -9,8 +9,8 @@ Glossary: Glossary Index: Index Listing: Listing-ListOfFigures: ListOfFigures-ListOfTables: ListOfTables+ListOfFigures: List of Figures+ListOfTables: List of Tables Page: page Part: Part Preface: Preface
data/translations/eo.yaml view
@@ -11,10 +11,11 @@ ListOfFigures: Listo de figuroj ListOfTables: Listo de tabeloj Page: Paĝo+Part: Parto Preface: Antaŭparolo Proof: Pruvo References: Citaĵoj See: vidu-SeeAlso: Parto+SeeAlso: vidu ankaŭ Table: Tabelo To: Al
+ data/translations/es-ES.yaml view
@@ -0,0 +1,21 @@+Abstract: Resumen+Appendix: Apéndice+Bibliography: Bibliografía+Cc: Copia a+Chapter: Capítulo+Contents: Índice general+Encl: Adjunto(s)+Figure: Figura+Glossary: Glosario+Index: Índice alfabético+ListOfFigures: Índice de figuras+ListOfTables: Índice de cuadros+Page: Página+Part: Parte+Preface: Prefacio+Proof: Prueba+References: Referencias+See: véase+SeeAlso: véase también+Table: Cuadro+To: A
+ data/translations/es-MX.yaml view
@@ -0,0 +1,21 @@+Abstract: Resumen+Appendix: Apéndice+Bibliography: Bibliografía+Cc: Copia a+Chapter: Capítulo+Contents: Índice+Encl: Anexo+Figure: Figura+Glossary: Glosario+Index: Índice Alfabético+ListOfFigures: Índice de Figuras+ListOfTables: Índice de Cuadros+Page: Página+Part: Parte+Preface: Prefacio+Proof: Demostración+References: Referencias+See: véase+SeeAlso: véase también+Table: Cuadro+To: A
data/translations/es.yaml view
@@ -3,17 +3,17 @@ Bibliography: Bibliografía Cc: Copia a Chapter: Capítulo-Contents: Índice general-Encl: Adjunto(s)+Contents: Índice+Encl: Adjunto Figure: Figura Glossary: Glosario Index: Índice alfabético ListOfFigures: Índice de figuras ListOfTables: Índice de cuadros-Page: Página+Page: página Part: Parte Preface: Prefacio-Proof: Prueba+Proof: Demostración References: Referencias See: véase SeeAlso: véase también
data/translations/fa.yaml view
@@ -1,21 +1,21 @@-Abstract: چکیﺪﻫ-Appendix: پیﻮﺴﺗ-Bibliography: کﺕﺎﺑc>ﻧﺎﻤﻫ-Cc: ﺭﻮﻧﻮﺸﺗ-Chapter: ﻒﺼﻟ-Contents: ﻒﻫﺮﺴﺗ ﻢﻃﺎﻠﺑ-Encl: پیﻮﺴﺗ-Figure: ﺶﻜﻟ-Glossary: ﺩﺎﻨﺷc>ﻧﺎﻤﻫ-Index: ﻦﻣﺍیﻩ-ListOfFigures: ﻝیﺲﺗ ﺖﺻﺍﻭیﺭ-ListOfTables: ﻝیﺲﺗ ﺝﺩﺍﻮﻟ-Page: ﺺﻔﺣﺓ-Part: ﺐﺨﺷ-Preface: پیﺵگﻒﺗﺍﺭ-Proof: ﺏﺮﻫﺎﻧ-References: ﻡﺭﺎﺠﻋ-See: ﺐﺑیﻥیﺩ-SeeAlso: ﻥیﺯ ﺐﺑیﻥیﺩ-Table: ﺝﺩﻮﻟ-To: ﺐﻫ+Abstract: چکیده+Appendix: پیوست+Bibliography: کتاب‌نامه+Cc: رونوشت+Chapter: فصل+Contents: فهرست+Encl: پیوست+Figure: شكل+Glossary: فرهنگ‌نامه+Index: نمایه+ListOfFigures: فهرست شکل‌ها+ListOfTables: فهرست جدول‌ها+Page: صفحه+Part: بخش+Preface: پیش‌گفتار+Proof: اثبات+References: مرجع‌ها+See: ببینید+SeeAlso: نیز ببینید+Table: جدول+To: به
data/translations/fi.yaml view
@@ -3,7 +3,7 @@ Bibliography: Kirjallisuutta Cc: Jakelu Chapter: Luku-Contents: Sisältö+Contents: Sisällys Encl: Liitteet Figure: Kuva Glossary: Sanasto
+ data/translations/fil.yaml view
@@ -0,0 +1,18 @@+Abstract: Abstrak+Appendix: Hugpong+Bibliography: Talaaklatan+Chapter: Kabanata+Contents: Talalamanan+Figure: Laraw+Glossary: Glosaryo+Index: Talatuntunan+ListOfFigures: Talalarawan+ListOfTables: Talatalayan+Page: Pahina+Part: Bahagi+Preface: Paunang Salita+Proof: Patunay+References: Talasanggunian+See: tignan ang+SeeAlso: tignan din+Table: Talay
+ data/translations/fur.yaml view
@@ -0,0 +1,21 @@+Abstract: Somari+Appendix: Zonte+Bibliography: Bibliografie+Cc: Cun copie a+Chapter: Cjapitul+Contents: Tabele gjenerâl+Encl: Zonte(is)+Figure: Figure+Glossary: Glossari+Index: Tabele analitiche+ListOfFigures: Liste des figuris+ListOfTables: Liste des tabelis+Page: Pagjine+Part: Part+Preface: Prefazion+Proof: Dimostrazion+References: Riferiments+See: cjale+SeeAlso: cjale ancje+Table: Tabele+To: Par
+ data/translations/ga.yaml view
@@ -0,0 +1,21 @@+Abstract: Achoimre+Appendix: Aguisín+Bibliography: Leabharliosta+Cc: cc+Chapter: Caibidil+Contents: Clár Ábhair+Encl: faoi iamh+Figure: Léaráid+Glossary: Glossary+Index: Innéacs+ListOfFigures: Léaráidí+ListOfTables: Táblaí+Page: Leathanach+Part: Cuid+Preface: Réamhrá+Proof: Cruthúnas+References: Tagairtí+See: féach+SeeAlso: féach freisin+Table: Tábla+To: Go
+ data/translations/gd.yaml view
@@ -0,0 +1,21 @@+Abstract: Brìgh+Appendix: Ath-sgr`ıobhadh+Bibliography: Leabhraichean+Cc: lethbhreac gu+Chapter: Caibideil+Contents: Clàr-obrach+Encl: a-staigh+Figure: Dealbh+Glossary: Glossary+Index: Clàr-innse+ListOfFigures: Liosta Dhealbh+ListOfTables: Liosta Chlàr+Page: t.d.+Part: Cuid+Preface: Preface+Proof: Proof+References: Iomraidh+See: see+SeeAlso: see also+Table: Clàr+To: gu
+ data/translations/gl.yaml view
@@ -0,0 +1,21 @@+Abstract: Resumo+Appendix: Apéndice+Bibliography: Bibliografía+Cc: Copia a+Chapter: Capítulo+Contents: Índice+Encl: Adxunto+Figure: Figura+Glossary: Glosario+Index: Índice alfabético+ListOfFigures: Índice de figuras+ListOfTables: Índice de cadros+Page: Páxina+Part: Parte+Preface: Prefacio+Proof: Demostración+References: Referencias+See: véxase+SeeAlso: véxase tamén+Table: Cadro+To: A
+ data/translations/grc.yaml view
@@ -0,0 +1,21 @@+Abstract: Περίληψις+Appendix: Παράρτημα+Bibliography: Βιβλιογραφία+Cc: Κοινοποίησις+Chapter: Κεφάλαιον+Contents: Περιεχόμενα+Encl: Συνημμένως+Figure: Σχῆμα+Glossary: Γλωσσάριον+Index: Εὑρετήριον+ListOfFigures: Κατάλογος σχημάτων+ListOfTables: Κατάλογος πινάκων+Page: Σελὶς+Part: Μέρος+Preface: Προοίμιον+Proof: Ἀπόδειξις+References: Ἀναφοραὶ+See: ὃρα+SeeAlso: ὃρα ὡσαύτως+Table: Πίναξ+To: Πρὸς
+ data/translations/gu.yaml view
@@ -0,0 +1,9 @@+Appendix: અનુસૂચિ+Chapter: પ્રકરણ+Index: અનુક્રમણિકા+Page: પાનુ+Part: ભાગ+Proof: પુરાવો+See: જુવો+SeeAlso: ઉપરાંત+Table: ટેબલ
+ data/translations/ha.yaml view
@@ -0,0 +1,21 @@+Abstract: Taƙaitawa+Appendix: Ƙarin bayani+Bibliography: Fahirinsa+Cc: cc+Chapter: Babi+Contents: Abin da ke ciki+Encl: saƙe+Figure: Addadi+Glossary: Ƙamus+Index: Fihirinsa+ListOfFigures: Tsarin Addadi+ListOfTables: Tsarin tabili+Page: Shafi+Part: Kashi+Preface: Gabatarwa+Proof: Shaida+References: Nassoshi+See: duba+SeeAlso: kuma+Table: tabili+To: je
data/translations/he.yaml view
@@ -6,17 +6,16 @@ Contents: תוכן העניינים Encl: רצ"ב Figure: איור-Glossary: מילון מונחים}+Glossary: מילון מונחים Index: מפתח ListOfFigures: רשימת האיורים ListOfTables: רשימת הטבלאות Page: עמוד Part: חלק Preface: מבוא-Proof: הוכחה}-Ps: נ.ב.+Proof: הוכחה References: מקורות See: ראה-SeeAlso: ראה גם}+SeeAlso: ראה גם Table: טבלה To: אל
data/translations/hi.yaml view
@@ -1,20 +1,18 @@ Abstract: सारांश Appendix: परिशिष्ट-Bibliography: संदर ग्रन्थ}-Cc: +Bibliography: संदर्भ-ग्रन्थ Chapter: अध्याय-Contents: विषय सूची-Encl: -Figure: चित्र}-Headpage: पृषठ+Contents: अनुक्रम+Figure: चित्र+Glossary: शब्दार्थ सूची Index: सूची ListOfFigures: चित्रों की सूची ListOfTables: तालिकाओं की सूची-Page: पृषठ-Part: खणड-Preface: प्रस्तावना}+Page: पृष्ठ+Part: खण्ड+Preface: प्रस्तावना+Proof: प्रमाण References: हवाले See: देखिए SeeAlso: और देखिए Table: तालिका-To: 
+ data/translations/hsb.yaml view
@@ -0,0 +1,21 @@+Abstract: Abstrakt+Appendix: Dodawki+Bibliography: Literatura+Cc: CC+Chapter: Kapitl+Contents: Wobsah+Encl: Přłoha+Figure: Wobraz+Glossary: Glossary+Index: Indeks+ListOfFigures: Zapis wobrazow+ListOfTables: Zapis tabulkow+Page: Strona+Part: Dźěl+Preface: Zawod+Proof: Proof+References: Referency+See: hl.+SeeAlso: hl.~tež+Table: Tabulka+To: Komu
data/translations/hu.yaml view
@@ -1,5 +1,5 @@ Abstract: Kivonat-Appendix: Függelék+Appendix: függelék Bibliography: Irodalomjegyzék Cc: Körlevél–címzettek Chapter: fejezet
+ data/translations/hy.yaml view
@@ -0,0 +1,20 @@+Abstract: Սեղմագիր+Appendix: Հավելված+Bibliography: Գրականություն+Cc: Կրկնօրինակը՝+Chapter: Գլուխ+Contents: Բովանդակություն+Encl: Կից՝+Figure: Նկար+Glossary: Տերմինների ցանկ+Index: Առարկայական ցանկ+ListOfFigures: Նկարների ցանկ+ListOfTables: Աղյուսակների ցանկ+Page: էջ+Part: Մաս+Preface: Նախաբան+Proof: Ապացույց+References: Հղումներ+See: տե՛ս+SeeAlso: տե՛ս նաև+Table: Աղյուսակ
+ data/translations/ia.yaml view
@@ -0,0 +1,21 @@+Abstract: Summario+Appendix: Appendice+Bibliography: Bibliographia+Cc: Copia+Chapter: Capitulo+Contents: Contento+Encl: Incluso+Figure: Figura+Glossary: Glossario+Index: Indice+ListOfFigures: Lista de figuras+ListOfTables: Lista de tabellas+Page: Pagina+Part: Parte+Preface: Prefacio+Proof: Prova+References: Referentias+See: vide+SeeAlso: vide etiam+Table: Tabella+To: A
+ data/translations/id.yaml view
@@ -0,0 +1,21 @@+Abstract: Ringkasan+Appendix: Lampiran+Bibliography: Bibliografi+Cc: cc+Chapter: Bab+Contents: Daftar Isi+Encl: Lampiran+Figure: Gambar+Glossary: Daftar Istilah+Index: Indeks+ListOfFigures: Daftar Gambar+ListOfTables: Daftar Tabel+Page: Halaman+Part: Bagian+Preface: Pendahuluan+Proof: Bukti+References: Pustaka+See: lihat+SeeAlso: lihat juga+Table: Tabel+To: Kepada
data/translations/is.yaml view
@@ -18,4 +18,4 @@ See: Sjá SeeAlso: Sjá einnig Table: Tafla-To: Til:+To: Til
data/translations/it.yaml view
@@ -1,7 +1,7 @@ Abstract: Sommario Appendix: Appendice Bibliography: Bibliografia-Cc: e p. c.+Cc: e~p.~c. Chapter: Capitolo Contents: Indice Encl: Allegati
+ data/translations/ja.yaml view
@@ -0,0 +1,21 @@+Abstract: 概要+Appendix: 付録+Bibliography: 文献目録+Cc: 同報+Chapter: 章+Contents: 目次+Encl: 添付+Figure: 図+Glossary: 用語集+Index: 索引+ListOfFigures: 図目次+ListOfTables: 表目次+Page: 頁+Part: 部+Preface: 端書き+Proof: 証明+References: 参考文献+See: 参照+SeeAlso: 参照+Table: 表+To: 宛先
+ data/translations/ka.yaml view
@@ -0,0 +1,21 @@+Abstract: ანოტაცია+Appendix: დანართი+Bibliography: ლიტერატურა+Cc: წყარ.+Chapter: თავი+Contents: შინაარსი+Encl: ჩათვ.+Figure: სურ.+Glossary: ტერმინები+Index: საძიებელი+ListOfFigures: სურათი+ListOfTables: ცხრილი+Page: გვ.+Part: ნაწილი+Preface: წინასიტყვაობა+Proof: დამტკიცება+References: ლიტერატურა+See: იხ.+SeeAlso: იხ. ასევე+Table: ცხრ.+To: შ.
+ data/translations/kmr-Arab.yaml view
@@ -0,0 +1,21 @@+Abstract: کورتەبیر+Appendix: پاشکۆ+Bibliography: چاڤکانییا پرتووکان+Cc: بەلاڤکەر+Chapter: سەرێ+Contents: ناڤێرۆک+Encl: دوماهک+Figure: دیمەنێ+Glossary: چاڤکانییا لێکۆلینێ+Index: پێرست+ListOfFigures: هەژمارا دیمەنا+ListOfTables: هەژمارا کەڤالێن+Page: رووپەلێ+Part: بەشا+Preface: پێشگۆتن+Proof: دەلیل+References: پرتووکێن بژارتی+See: بنێرا+SeeAlso: لە ڤێیا ژ بنێرا+Table: کەڤالا+To: ژ بۆ
+ data/translations/kmr-Latn.yaml view
@@ -0,0 +1,21 @@+Abstract: Kurtebîr+Appendix: Tebînîya+Bibliography: Çavkanîya Pirtukan+Cc: Belavker+Chapter: Serê+Contents: Navêrok+Encl: Dumahik+Figure: Dimenê+Glossary: Çavkanîya lêkolînê+Index: Endeks+ListOfFigures: Hejmara Dimena+ListOfTables: Hejmara Kevalen+Page: Rûpelê+Part: Bêşa+Preface: Peşgotin+Proof: Delîl+References: Pirtuken bijartî+See: binêra+SeeAlso: le vêya ji binêra+Table: Kevala+To: Ji bo
+ data/translations/kn.yaml view
@@ -0,0 +1,20 @@+Abstract: ಸಾರಾಂಶ+Appendix: ಅನುಬಂಧ+Bibliography: ಗ್ರಂಥಸೂಚಿ+Cc: cc+Chapter: ಅಧ್ಯಾಯ+Contents: ವಿಷಯಗಳು+Encl: encl+Figure: ಚಿತ್ರ+Index: ಸೂಚಿ+ListOfFigures: ಚಿತ್ರಗಳ ಪಟ್ಟಿ+ListOfTables: ಕೋಷ್ಟಕಗಳ ಪಟ್ಟಿ+Page: ಪುಟ+Part: ಭಾಗ+Preface: ಮುನ್ನುಡಿ+Proof: ಕರಡುಪ್ರತಿ+References: ಉಲ್ಲೇಖಗಳು+See: ನೋಡು+SeeAlso: ಇದನ್ನೂ ಸಹ ನೋಡು+Table: ಕೋಷ್ಟಕ+To: ಗೆ
+ data/translations/la.yaml view
@@ -0,0 +1,20 @@+Abstract: Summarium+Appendix: Additamentum+Bibliography: Conspectus librorum+Cc: Exemplar+Chapter: Caput+Contents: Index+Encl: Additur+Figure: Descriptio+Glossary: Glossarium+Index: Index rerum notabilium+ListOfFigures: Conspectus descriptionum+ListOfTables: Conspectus tabularum+Page: charta+Part: Pars+Preface: Praefatio+Proof: Demonstratio+References: Conspectus librorum+See: cfr.+SeeAlso: cfr.+Table: Tabula
+ data/translations/lb.yaml view
@@ -0,0 +1,21 @@+Abstract: Resümee+Appendix: Annex+Bibliography: Bibliographie+Cc: Distributeur+Chapter: Kapitel+Contents: Contenue+Encl: Annex(en)+Figure: Bild+Glossary: Glossär+Index: Index+ListOfFigures: Lëscht vun de Biller+ListOfTables: Lëscht vun den Tabellen+Page: Säit+Part: Deel+Preface: Virwuert+Proof: Beweis+References: Literatur+See: kuck+SeeAlso: kuck och+Table: Tabell+To: Un
data/translations/lv.yaml view
@@ -1,12 +1,12 @@ Abstract: Anotācija Appendix: Pielikums Bibliography: Literatūra-Cc: cc+Cc: Kopija(s) Chapter: Nodaļa Contents: Saturs-Encl: encl+Encl: Pielikumā Figure: Att.-Index: Index+Index: Priekšmetu rādītājs ListOfFigures: Attēlu saraksts ListOfTables: Tabulu saraksts Page: lpp.
+ data/translations/mk.yaml view
@@ -0,0 +1,21 @@+Abstract: Апстракт+Appendix: Прилог+Bibliography: Библиографиjа+Cc: копиjа+Chapter: Глава+Contents: Содржина+Encl: Прилози+Figure: Слика+Glossary: Речник+Index: Индекс на термини+ListOfFigures: Листа на слики+ListOfTables: Листа на табели+Page: стр.+Part: Дел+Preface: Предговор+Proof: доказ+References: Литература+See: види+SeeAlso: види исто така+Table: Табела+To: За
+ data/translations/ml.yaml view
@@ -0,0 +1,12 @@+Abstract: സാരാംശം+Appendix: ശിഷ്ടം+Chapter: അദ്ധ്യായം+Contents: ഉള്ളടക്കം+Figure: ചിത്രം+Index: സൂചിക+ListOfFigures: ചിത്രസൂചിക+ListOfTables: പട്ടികകളുടെ സൂചിക+Part: ഭാഗം+See: കാണുക+SeeAlso: ഇതും കാണുക+Table: പട്ടിക
+ data/translations/mn.yaml view
@@ -0,0 +1,19 @@+Abstract: Удиртгал+Appendix: Хавсралт+Bibliography: Номзүй+Cc: э.с.+Chapter: Бүлэг+Contents: Гарчиг+Encl: Ишлэл+Figure: Зураг+Index: Товъёг+ListOfFigures: Зургийн жагсаалт+ListOfTables: Хүснэгтийн жагсаалт+Page: тал+Part: Хэсэг+Preface: Өмнөх үг+Proof: Баталгаа+References: Ашигласан ном+See: талд үз+SeeAlso: мөн талд үз+Table: Хүснэгт
+ data/translations/mr.yaml view
@@ -0,0 +1,21 @@+Abstract: सारांश+Appendix: परिशिष्ट+Bibliography: संदर्भसूची+Cc: प्रत+Chapter: प्रकरण+Contents: अनुक्रमणिका+Encl: समाविष्ट+Figure: आकृती+Glossary: संज्ञासूची+Index: सूची+ListOfFigures: आकृत्यांची सूची+ListOfTables: कोष्टकसूची+Page: पृष्ठ+Part: खंड+Preface: प्रस्तावना+Proof: सिद्धता+References: संदर्भ+See: पाहा+SeeAlso: हेदेखील पाहा+Table: कोष्टक+To: प्रति
+ data/translations/ms.yaml view
@@ -0,0 +1,21 @@+Abstract: Abstrak+Appendix: Lampiran+Bibliography: Bibliografi+Cc: sk+Chapter: Bab+Contents: Kandungan+Encl: Lampiran+Figure: Gambar+Glossary: Istilah+Index: Indeks+ListOfFigures: Senarai Gambar+ListOfTables: Senarai Jadual+Page: Halaman+Part: Bahagian+Preface: Prakata+Proof: Bukti+References: Rujukan+See: sila rujuk+SeeAlso: rujuk juga+Table: Jadual+To: Kepada
+ data/translations/nko.yaml view
@@ -0,0 +1,21 @@+Abstract: ߓߊߕߐߡߐ߲+Appendix: ߘߋ߬ߙߋ+Bibliography: ߟߍߙߊߥߙߍߟߐ߲߲+Cc: ߓߊ ߘߏ߫ ߘߌ߫+Chapter: ߛߌ߰ߘߊ+Contents: ߞߣߐߘߐ+Encl: ߝߍ߬ߕߊ+Figure: ߢߊ+Glossary: ߞߘߐߝߐߟߊ߲+Index: ߛߙߍߘߍ+ListOfFigures: ߢߊ ߟߎ߬ ߛߙߍߘߍ+ListOfTables: ߦߌ߬ߘߊ߬ߥߟߊ ߟߎ߬ ߛߙߍߘߍ+Page: ߞߐߜߍ+Part: ߛߌ߰ߘߊ߬ߙߋ߲+Preface: ߢߍߛߓߍ+Proof: ߦߌ߬ߘߊ߬ߞߏ+References: ߞߐߡߊߛߙߋ+See: ߡߊߝߟߍ߫+SeeAlso: ߝߟߍߡߊߛߊ߬ߦߌ߬+Table: ߦߌ߬ߘߊ߬ߥߟߊ+To: ߞߊߕߙߍ߬
data/translations/nl.yaml view
@@ -1,19 +1,19 @@ Abstract: Samenvatting-Appendix: Bijlage+Appendix: Bijlage Bibliography: Bibliografie Cc: cc Chapter: Hoofdstuk Contents: Inhoudsopgave-Encl: Bijlage(n)+Encl: Bijlage(n) Figure: Figuur-Glossary: Verklarende woordenlijst+Glossary: Verklarende Woordenlijst Index: Index-ListOfFigures: Lijst van figuren-ListOfTables: Lijst van tabellen+ListOfFigures: Lijst van figuren+ListOfTables: Lijst van tabellen Page: Pagina Part: Deel Preface: Voorwoord-Proof: Bewijs+Proof: Bewijs References: Referenties See: zie SeeAlso: zie ook
data/translations/nn.yaml view
@@ -1,7 +1,7 @@ Abstract: Samandrag Appendix: Tillegg-Bibliography: Bibliografi-Cc: Kopi sendt+Bibliography: Litteratur+Cc: Kopi til Chapter: Kapittel Contents: Innhald Encl: Vedlegg
+ data/translations/oc.yaml view
@@ -0,0 +1,21 @@+Abstract: Resumit+Appendix: Annèx+Bibliography: Bibliografia+Cc: còpia a+Chapter: Capítol+Contents: Ensenhador+Encl: Pèça junta+Figure: Figura+Glossary: Glossari+Index: Indèx+ListOfFigures: Taula de las figuras+ListOfTables: Taula dels tablèus+Page: Pagina+Part: Partida+Preface: Prefàcia+Proof: Demostracion+References: Referéncias+See: vejatz+SeeAlso: vejatz tanben+Table: Tablèu+To: A
+ data/translations/or.yaml view
@@ -0,0 +1,21 @@+Abstract: ସାରାଂଶ+Appendix: ପରିଶିଷ୍ଟ+Bibliography: ସୂଚନା+Cc: କପି କରନ୍ତୁ+Chapter: ଅଧ୍ୟାୟ+Contents: ସୁଚୀ ପତ୍ର+Encl: ସଂଲଗ୍ନ+Figure: ପ୍ରତିଛବି+Glossary: ଶବ୍ଦର ଶବ୍ଦକୋଷ+Index: ସୂଚକାଙ୍କ+ListOfFigures: ପ୍ରତିଛବି ତାଲିକା+ListOfTables: ଟେବୁଲ ତାଲିକା+Page: ପୃଷ୍ଠା+Part: ବିଭାଗ+Preface: ପ୍ରାରମ୍ଭ+Proof: ପ୍ରମାଣ+References: ସନ୍ଦର୍ଭ+See: ଦେଖନ୍ତୁ+SeeAlso: ଅଧିକ ଦେଖନ୍ତୁ+Table: ଟେବୁଲ୍+To: ପ୍ରତି
+ data/translations/pa.yaml view
@@ -0,0 +1,20 @@+Abstract: ਨਿਚੋੜ+Appendix: ਲੜੀਵਾਰ+Bibliography: ਸੰਬੰਧਤ ਹਵਾਲੇ+Cc: ਕਾਪੀ+Chapter: ਪਾਠ+Contents: ਸਮਗਰੀ+Encl: ਨੱਥੀ+Figure: ਸ਼ਕਲ+Glossary: ਕੁੰਜੀ+Index: ਸੂਚੀ+ListOfFigures: ਸ਼ਕਲਾਂ ਦੀ ਲੜੀ+ListOfTables: ਲੜੀਆਂ ਦਾ ਲੇਖਾ+Page: ਵਰਕਾ+Part: ਹਿੱਸਾ+Preface: ਮੁੱਖਬੰਦ+Proof: ਪਰਮਾਣ+References: ਹਵਾਲਾ+See: ਵੇਖੋ+SeeAlso: ਹੋਰ+Table: ਲੇਖਾ
data/translations/pl.yaml view
@@ -1,7 +1,7 @@ Abstract: Streszczenie Appendix: Dodatek Bibliography: Bibliografia-Cc: 'Kopie:'+Cc: Kopie Chapter: Rozdział Contents: Spis treści Encl: Załącznik
+ data/translations/pms.yaml view
@@ -0,0 +1,21 @@+Abstract: Somari+Appendix: Gionta+Bibliography: Bibliografìa+Cc: Con còpia a+Chapter: Capìtol+Contents: Tàula+Encl: Gionta/e+Figure: Figura+Glossary: Glossari+Index: Tàula analìtica+ListOfFigures: Lista dle figure+ListOfTables: Lista dle tabele+Page: Pàgina+Part: Part+Preface: Prefassion+Proof: Dimostrassion+References: Riferiment+See: vëd+SeeAlso: vëd anche+Table: Tabela+To: Për
+ data/translations/pt-BR.yaml view
@@ -0,0 +1,21 @@+Abstract: Resumo+Appendix: Apêndice+Bibliography: Referências Bibliográficas+Cc: Cópia para+Chapter: Capítulo+Contents: Sumário+Encl: Anexo+Figure: Figura+Glossary: Glossário+Index: Índice Remissivo+ListOfFigures: Lista de Figuras+ListOfTables: Lista de Tabelas+Page: Página+Part: Parte+Preface: Prefácio+Proof: Demonstração+References: Referências+See: veja+SeeAlso: veja também+Table: Tabela+To: Para
+ data/translations/pt-PT.yaml view
@@ -0,0 +1,21 @@+Abstract: Resumo+Appendix: Apêndice+Bibliography: Bibliografia+Cc: Com cópia a+Chapter: Capítulo+Contents: Conteúdo+Encl: Anexo+Figure: Figura+Glossary: Glossário+Index: Índice+ListOfFigures: Lista de Figuras+ListOfTables: Lista de Tabelas+Page: Página+Part: Parte+Preface: Prefácio+Proof: Demonstração+References: Referências+See: ver+SeeAlso: ver também+Table: Tabela+To: Para
data/translations/ro.yaml view
@@ -12,8 +12,8 @@ ListOfTables: Listă de tabele Page: Pagina Part: Partea-Preface: Prefață-Proof: Demonstrație+Preface: Prefaţă+Proof: Demonstraţie References: Bibliografie See: Vezi SeeAlso: Vezi de asemenea
data/translations/ru.yaml view
@@ -3,9 +3,10 @@ Bibliography: Литература Cc: исх. Chapter: Глава-Contents: Оглавление+Contents: Содержание Encl: вкл. Figure: Рис.+Glossary: Словарь терминов Index: Предметный указатель ListOfFigures: Список иллюстраций ListOfTables: Список таблиц@@ -15,6 +16,6 @@ Proof: Доказательство References: Список литературы See: см.-SeeAlso: см. также+SeeAlso: см. также Table: Таблица To: вх.
+ data/translations/se.yaml view
@@ -0,0 +1,21 @@+Abstract: Čoahkkáigeassu+Appendix: Čuovus+Bibliography: Girjjálašvuohta+Cc: Kopia sáddejuvvon+Chapter: Kapihttal+Contents: Sisdoallu+Encl: Mielddus+Figure: Govus+Glossary: Sátnelistu+Index: Registtar+ListOfFigures: Govvosat+ListOfTables: Tabeallat+Page: Siidu+Part: Oassi+Preface: Ovdasátni+Proof: Duođaštus+References: Čujuhusat+See: geahča+SeeAlso: geahča maiddái+Table: Tabealla+To: Vuostáiváldi
+ data/translations/si.yaml view
@@ -0,0 +1,21 @@+Abstract: සංක්ෂෙපය+Appendix: උපග්‍රන්ථය+Bibliography: ග්‍රන්ථ නාමාවලිය+Cc: පිටපත්+Chapter: පරිච්ඡේදය+Contents: පටුන+Encl: ඇමුණුම+Figure: සටහන+Glossary: පදමාලාව+Index: සූචිය+ListOfFigures: සටහන් ලේඛනය+ListOfTables: වගු ලේඛනය+Page: පිට+Part: කොටස+Preface: පෙරවදන+Proof: සාධනය+References: යොමුව+See: බලනු+SeeAlso: තවද+Table: වගුව+To: වෙත
data/translations/sk.yaml view
@@ -4,17 +4,17 @@ Cc: cc. Chapter: Kapitola Contents: Obsah-Encl: Prílohy-Figure: Obrázok+Encl: Príloha+Figure: Obr. Glossary: Slovník-Index: Index+Index: Register ListOfFigures: Zoznam obrázkov ListOfTables: Zoznam tabuliek-Page: Strana+Page: Str. Part: Časť-Preface: Úvod+Preface: Predhovor Proof: Dôkaz-References: Referencie+References: Literatúra See: viď SeeAlso: viď tiež Table: Tabuľka
data/translations/sq.yaml view
@@ -1,8 +1,10 @@ Abstract: Përmbledhja Appendix: Shtesa Bibliography: Bibliografia+Cc: Kopja Chapter: Kapitulli-Contents: Përmbajta+Contents: Përmbajtja+Encl: Lidhja Figure: Figura Glossary: Përhasja e Fjalëve Index: Indeksi@@ -16,3 +18,4 @@ See: shiko SeeAlso: shiko dhe Table: Tabela+To: Për
+ data/translations/sr-Cyrl.yaml view
@@ -0,0 +1,21 @@+Abstract: Сажетак+Appendix: Додатак+Bibliography: Библиографиjа+Cc: Копиjе+Chapter: Глава+Contents: Садржаj+Encl: Прилози+Figure: Слика+Glossary: Речник+Index: Индекс+ListOfFigures: Списак слика+ListOfTables: Списак табела+Page: страна+Part: Део+Preface: Предговор+Proof: Доказ+References: Литература+See: види+SeeAlso: видитакође+Table: Табела+To: Прима
+ data/translations/sr-Latn.yaml view
@@ -0,0 +1,21 @@+Abstract: Sažetak+Appendix: Dodatak+Bibliography: Bibliografija+Cc: Kopije+Chapter: Glava+Contents: Sadržaj+Encl: Prilozi+Figure: Slika+Glossary: Rečnik+Index: Indeks+ListOfFigures: Spisak slika+ListOfTables: Spisak tabela+Page: strana+Part: Deo+Preface: Predgovor+Proof: Dokaz+References: Literatura+See: vidi+SeeAlso: vidi takođe+Table: Tabela+To: Prima
− data/translations/sr-cyrl.yaml
@@ -1,21 +0,0 @@-Abstract: Сажетак-Appendix: Додатак-Bibliography: Литература-Cc: Копије-Chapter: Глава-Contents: Садржај-Encl: Прилози-Figure: Слика-Glossary: Речник непознатих речи-Index: Регистар-ListOfFigures: Списак слика-ListOfTables: Списак табела-Page: Страна-Part: Део-Preface: Предговор-Proof: Доказ-References: Библиографија-See: Види-SeeAlso: Види такође-Table: Табела-To: Прима
data/translations/sr.yaml view
@@ -1,21 +1,21 @@-Abstract: Sažetak-Appendix: Dodatak-Bibliography: Literatura-Cc: Kopije-Chapter: Glava-Contents: Sadržaj-Encl: Prilozi-Figure: Slika-Glossary: Rečnik nepoznatih reči-Index: Registar-ListOfFigures: Spisak slika-ListOfTables: Spisak tabela-Page: Strana-Part: Deo-Preface: Predgovor-Proof: Dokaz-References: Bibliografija-See: Vidi-SeeAlso: Vidi takođe-Table: Tabela-To: Prima+Abstract: Сажетак+Appendix: Додатак+Bibliography: Библиографиjа+Cc: Копиjе+Chapter: Глава+Contents: Садржаj+Encl: Прилози+Figure: Слика+Glossary: Речник+Index: Индекс+ListOfFigures: Списак слика+ListOfTables: Списак табела+Page: страна+Part: Део+Preface: Предговор+Proof: Доказ+References: Литература+See: види+SeeAlso: видитакође+Table: Табела+To: Прима
+ data/translations/ta.yaml view
@@ -0,0 +1,11 @@+Abstract: சாராம்சம்+Appendix: பிற்சேர்க்கை+Chapter: அத்தியாயம்+Contents: உள்ளே+Figure: படம்+Index: சுட்டி+ListOfFigures: படங்களின் பட்டியல்+ListOfTables: அட்டவணை பட்டியல்+Part: பகுதி+See: பார்க்க+Table: அட்டவணை
+ data/translations/te.yaml view
@@ -0,0 +1,21 @@+Abstract: సారాంశం+Appendix: అదనంగా+Bibliography: గ్రంథాల జాబితా+Cc: సిసి+Chapter: అధ్యాయము+Contents: విషయాలు+Encl: ఎంక్లోజర్*+Figure: ఆకృతి+Glossary: నిఘంటువు+Index: విషయ సూచిక+ListOfFigures: ఆకృతుల జాబితా+ListOfTables: పట్టికల జాబితా+Page: పేజి+Part: భాగం+Preface: ముందుమాట+Proof: రుజువు+References: ఆధారాలు+See: చూడండి+SeeAlso: కూడా చూడండి+Table: పట్టిక+To: కి
data/translations/th.yaml view
@@ -11,7 +11,7 @@ ListOfTables: สารบัญตาราง Page: หน้า Part: ภาค-Preface: คำนำ+Preface: บทนำ Proof: พิสูจน์ References: หนังสืออ้างอิง See: ดู
+ data/translations/tk.yaml view
@@ -0,0 +1,21 @@+Abstract: Gysgaça manysy+Appendix: Goşmaça+Bibliography: Çeşmeler+Cc: Iberilenler+Chapter: Bap+Contents: Mazmuny+Encl: Goşmaça+Figure: Surat+Glossary: Sözlük+Index: Indeks+ListOfFigures: Suratlaryň sanawy+ListOfTables: Tablisalaryň sanawy+Page: Sahypa+Part: Bölüm+Preface: Sözbaşy+Proof: Delil+References: Çeşmeler+See: ser.+SeeAlso: şuňa-da ser.+Table: Tablisa+To: Kime
+ data/translations/ua.yaml view
@@ -0,0 +1,22 @@+Abstract: Резюме+Appendix: Додаток+Bibliography: Бібліографія+Cc: Розповсюджувач+Chapter: Розділ+Contents: Зміст+Encl: Додаток(и)+Figure: Ілюстрація+Glossary: Глосарій+Index: Індекс+Listing: Список+ListOfFigures: Список рисунків+ListOfTables: Список таблиць+Page: Сторінка+Part: Частина+Preface: Передмова+Proof: Докази+References: Література+See: див.+SeeAlso: див. також+Table: Таблиця+To: До
+ data/translations/ug.yaml view
@@ -0,0 +1,21 @@+Abstract: ئابستراكت+Appendix: قوشۇمچە+Bibliography: پايدىلانما+Cc: باشقا تاپشۇرۇۋالغۇچى+Chapter: باب+Contents: مۇندەرىجە+Encl: قوشۇمچە ھۆججەت+Figure: رەسىم+Glossary: لۇغەت+Index: ئىندېكىس+ListOfFigures: رەسىملەر+ListOfTables: جەدۋەللەر+Page: بەت+Part: قىسىم+Preface: كىرىش سۆز+Proof: ئىسپات+References: پايدىلانما+See: قاراڭ+SeeAlso: ئايرىم قاراڭ+Table: جەدۋەل+To: تاپشۇرۇۋالغۇچى
data/translations/uk.yaml view
@@ -16,6 +16,6 @@ Proof: Доведення References: Література See: див.-SeeAlso: див. також+SeeAlso: див. також Table: Табл. To: До
data/translations/ur.yaml view
@@ -1,22 +1,21 @@-Abstract: ﻢﻠﺨّﺻ-Appendix: ﺾﻣیﻡہ-Bibliography: کﺕﺎﺑیﺎﺗ-Cc: ﻦﻘﻟ-Chapter: ﺏﺎﺑ-Contents: ﻑہﺮﺴﺗ ﻊﻧﻭﺎﻧﺎﺗ-Encl: ﻢﻨﺴﻟک-Figure: ﺶﻜﻟ-Glossary: ﻞﻐﺗ-Index: ﺎﺷﺍﺭیہ-ListOfFigures: ﻑہﺮﺴﺗ ﺎﺷکﺎﻟ-ListOfTables: ﻑہﺮﺴﺗ ﺝﺩﺍﻮﻟ-Page: ﺺﻔﺣہ-Part: ﺢﺻّہ-Preface: ﺩیﺏﺍچہ-Proof: ﺚﺑﻮﺗ-References: ﺡﻭﺎﻟہ ﺝﺎﺗ-Section: ﻒﺼﻟ-See: ﻡﻼﺤﻇہ ہﻭ-SeeAlso: ﺍیﺽﺍً-Table: ﺝﺩﻮﻟ-To: ﺐﻣﻼﺤﻇہ+Abstract: ملخّص+Appendix: ضمیمہ+Bibliography: کتابیات+Cc: نقل+Chapter: باب+Contents: فہرست عنوانات+Encl: منسلک+Figure: شكل+Glossary: لغت+Index: اشاریہ+ListOfFigures: فہرست اشکال+ListOfTables: فہرست جداول+Page: صفحہ+Part: حصّہ+Preface: دیباچہ+Proof: ثبوت+References: حوالہ جات+See: ملاحظہ ہو+SeeAlso: ایضاً+Table: جدول+To: بملاحظہ
data/translations/vi.yaml view
@@ -1,21 +1,21 @@ Abstract: Tóm tắt nội dung-Also: Xem thêm Appendix: Phụ lục-Bib: Tài liệu tham khảo+Bibliography: Tài liệu tham khảo Cc: Cùng gửi Chapter: Chương Contents: Mục lục Encl: Kèm theo Figure: Hình Glossary: Từ điển chú giải-Headto: Gửi Index: Chỉ mục-Listfigure: Danh sách hình vẽ-Listtable: Danh sách bẳng+ListOfFigures: Danh sách hình vẽ+ListOfTables: Danh sách bảng Page: Trang Part: Phần Preface: Lời nói đầu Proof: Chứng minh References: Tài liệu See: Xem-Table: Bẳng+SeeAlso: Xem thêm+Table: Bảng+To: Gửi
pandoc.cabal view
@@ -1,18 +1,17 @@ cabal-version:   2.4 name:            pandoc-version:         3.1.13+version:         3.10 build-type:      Simple license:         GPL-2.0-or-later license-file:    COPYING.md-copyright:       (c) 2006-2023 John MacFarlane+copyright:       (c) 2006-2024 John MacFarlane author:          John MacFarlane <jgm@berkeley.edu> maintainer:      John MacFarlane <jgm@berkeley.edu> bug-reports:     https://github.com/jgm/pandoc/issues stability:       alpha homepage:        https://pandoc.org category:        Text-tested-with:     GHC == 8.10.7, GHC == 9.0.2,-                 GHC == 9.2.5, GHC == 9.4.4, GHC == 9.6.3+tested-with:     GHC == 9.6.7, GHC == 9.8.4, GHC == 9.10.3, GHC == 9.12.2 synopsis:        Conversion between markup formats description:     Pandoc is a Haskell library for converting from one markup                  format to another.  The formats it can handle include@@ -22,7 +21,7 @@                    txt2tags, djot)                  - HTML formats (HTML 4 and 5)                  - Ebook formats (EPUB v2 and v3, FB2)-                 - Documentation formats (GNU TexInfo, Haddock)+                 - Documentation formats (GNU TexInfo, Haddock, Vimdoc)                  - Roff formats (man, ms)                  - TeX formats (LaTeX, ConTeXt)                  - Typst@@ -37,7 +36,7 @@                    Vimwiki, XWiki, ZimWiki, Jira wiki, Creole)                  - Slide show formats (LaTeX Beamer, PowerPoint, Slidy,                    reveal.js, Slideous, S5, DZSlides)-                 - Data formats (CSV and TSV tables)+                 - Data formats (CSV and TSV tables, Excel spreadsheets)                  - PDF (via external programs such as pdflatex or wkhtmltopdf)                  .                  Pandoc can convert mathematical content in documents@@ -64,8 +63,10 @@                  data/templates/default.jats_publishing                  data/templates/default.tei                  data/templates/default.opendocument+                 data/templates/default.openxml                  data/templates/default.icml                  data/templates/default.opml+                 data/templates/default.beamer                  data/templates/default.latex                  data/templates/default.bibtex                  data/templates/default.biblatex@@ -95,12 +96,22 @@                  data/templates/default.org                  data/templates/default.epub2                  data/templates/default.epub3+                 data/templates/default.ansi                  data/templates/article.jats_publishing                  data/templates/affiliations.jats                  data/templates/default.markua                  data/templates/default.typst-                 data/templates/definitions.typst+                 data/templates/document-metadata.latex                  data/templates/template.typst+                 data/templates/common.latex+                 data/templates/hypersetup.latex+                 data/templates/passoptions.latex+                 data/templates/fonts.latex+                 data/templates/font-settings.latex+                 data/templates/after-header-includes.latex+                 data/templates/default.vimdoc+                 data/templates/default.bbcode+                  -- translations                  data/translations/*.yaml                  -- entities@@ -196,17 +207,25 @@                  citeproc/biblatex-localization/*.lbx.strings                  -- documentation                  MANUAL.txt, COPYRIGHT+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, changelog.md,                  -- tests                  test/bodybg.gif                  test/*.native                  test/command/*.md                  test/command/*.csl                  test/command/*.svg+                 test/command/7691.docx+                 test/command/9391.docx+                 test/command/9358.docx                  test/command/9002.docx+                 test/command/9603.docx+                 test/command/11113.docx                  test/command/biblio.bib                  test/command/averroes.bib                  test/command/A.txt@@ -216,6 +235,7 @@                  test/command/file1.txt                  test/command/file2.txt                  test/command/three.txt+                 test/command/11090/ch1.typ                  test/command/01.csv                  test/command/chap1/spider.png                  test/command/chap2/spider.png@@ -230,6 +250,8 @@                  test/command/defaults7.yaml                  test/command/defaults8.yaml                  test/command/defaults9.yaml+                 test/command/8024a.yaml+                 test/command/8024b.yaml                  test/command/3533-rst-csv-tables.csv                  test/command/3880.txt                  test/command/5182.txt@@ -255,6 +277,12 @@                  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+                 test/asciidoc-reader-include.adoc                  test/docbook-chapter.docbook                  test/docbook-reader.docbook                  test/docbook-xref.docbook@@ -322,6 +350,8 @@                  test/tables.txt                  test/tables.fb2                  test/tables.muse+                 test/tables.vimdoc+                 test/tables.bbcode                  test/tables.xwiki                  test/tables/*.html4                  test/tables/*.html5@@ -330,7 +360,9 @@                  test/tables/*.native                  test/tables/*.mediawiki                  test/tables/*.jats_archiving+                 test/tables/*.markdown                  test/testsuite.txt+                 test/ansi-test.txt                  test/writer.latex                  test/writer.context                  test/writer.djot@@ -366,6 +398,9 @@                  test/writer.zimwiki                  test/writer.xwiki                  test/writer.muse+                 test/writer.vimdoc+                 test/writer.bbcode+                 test/ansi-test.ansi                  test/writers-lang-and-dir.latex                  test/writers-lang-and-dir.context                  test/dokuwiki_inline_formatting.dokuwiki@@ -399,6 +434,8 @@                  test/pptx/*.pptx                  test/pptx/**/*.pptx                  test/pptx/**/*.native+                 test/pptx-reader/basic.pptx+                 test/pptx-reader/basic.native                  test/ipynb/*.native                  test/ipynb/*.in.native                  test/ipynb/*.out.native@@ -411,17 +448,26 @@                  test/odt/odt/*.odt                  test/odt/markdown/*.md                  test/odt/native/*.native+                 test/xlsx-reader/*.xlsx+                 test/xlsx-reader/*.native+                 test/pod-reader.pod+                 test/vimdoc/*.markdown+                 test/vimdoc/*.vimdoc source-repository head   type:          git-  location:      git://github.com/jgm/pandoc.git+  location:      https://github.com/jgm/pandoc.git  flag embed_data_files   Description:   Embed data files in binary for relocatable executable.   Default:       False +flag http+  Description:   Support for fetching resources using HTTP.+  Default:       True+ common common-options   default-language: Haskell2010-  build-depends:    base         >= 4.12 && < 5+  build-depends:    base         >= 4.18 && < 5   ghc-options:      -Wall -fno-warn-unused-do-bind                     -Wincomplete-record-updates                     -Wnoncanonical-monad-instances@@ -431,13 +477,12 @@                     -Wpartial-fields                     -Wmissing-signatures                     -fhide-source-paths-                    -- -Wmissing-export-lists--  if impl(ghc >= 8.10)-    ghc-options:    -Wunused-packages+                    -Wmissing-export-lists+                    -Wunused-packages+                    -Winvalid-haddock -  if impl(ghc >= 9.0)-    ghc-options:    -Winvalid-haddock+  if impl(ghc >= 9.12)+    ghc-options:    -Wno-deriving-typeable    if os(windows)     cpp-options:      -D_WINDOWS@@ -450,9 +495,9 @@ library xml-light   import:        common-options   build-depends: xml                   >= 1.3.12   && < 1.4,-                 xml-conduit           >= 1.9.1.1  && < 1.10,+                 xml-conduit           >= 1.9.1.1  && < 1.11,                  xml-types             >= 0.3      && < 0.4,-                 containers            >= 0.6.0.1  && < 0.8,+                 containers            >= 0.6.0.1  && < 0.9,                  text                  >= 1.1.1.0  && < 2.2    hs-source-dirs:  xml-light@@ -466,8 +511,7 @@   build-depends: xml-light,                  Glob                  >= 0.7      && < 0.11,                  JuicyPixels           >= 3.1.6.1  && < 3.4,-                 SHA                   >= 1.6      && < 1.7,-                 aeson                 >= 2.0.1.0  && < 2.3,+                 aeson                 >= 2.0.1.0  && < 2.4,                  aeson-pretty          >= 0.8.9    && < 0.9,                  array                 >= 0.5      && < 0.6,                  attoparsec            >= 0.12     && < 0.15,@@ -477,67 +521,74 @@                  blaze-markup          >= 0.8      && < 0.9,                  bytestring            >= 0.9      && < 0.13,                  case-insensitive      >= 1.2      && < 1.3,-                 citeproc              >= 0.8.1    && < 0.9,-                 commonmark            >= 0.2.6    && < 0.3,-                 commonmark-extensions >= 0.2.5.4  && < 0.3,-                 commonmark-pandoc     >= 0.2.2.1  && < 0.3,-                 containers            >= 0.6.0.1  && < 0.8,-                 crypton-connection    >= 0.3.1    && < 0.4,-                 data-default          >= 0.4      && < 0.8,+                 citeproc              >= 0.13.0.1 && < 0.14,+                 commonmark            >= 0.3      && < 0.4,+                 commonmark-extensions >= 0.2.7    && < 0.3,+                 commonmark-pandoc     >= 0.3      && < 0.4,+                 containers            >= 0.6.0.1  && < 0.9,+                 crypton               >= 0.30     && < 1.2,+                 data-default          >= 0.4      && < 0.9,                  deepseq               >= 1.3      && < 1.6,                  directory             >= 1.2.3    && < 1.4,-                 doclayout             >= 0.4.0.1  && < 0.5,+                 doclayout             >= 0.5.0.1  && < 0.6,                  doctemplates          >= 0.11     && < 0.12,-                 emojis                >= 0.1      && < 0.2,+                 emojis                >= 0.1.4.1  && < 0.2,                  exceptions            >= 0.8      && < 0.11,                  file-embed            >= 0.0      && < 0.1,                  filepath              >= 1.1      && < 1.6,                  gridtables            >= 0.1      && < 0.2,                  haddock-library       >= 1.10     && < 1.12,-                 http-client           >= 0.4.30   && < 0.8,-                 http-client-tls       >= 0.2.4    && < 0.4,                  http-types            >= 0.8      && < 0.13,                  ipynb                 >= 0.2      && < 0.3,                  jira-wiki-markup      >= 1.5.1    && < 1.6,                  mime-types            >= 0.1.1    && < 0.2,                  mtl                   >= 2.2      && < 2.4,-                 network               >= 2.6      && < 3.2,                  network-uri           >= 2.6      && < 2.8,                  pandoc-types          >= 1.23.1   && < 1.24,                  parsec                >= 3.1      && < 3.2,                  pretty                >= 1.1      && < 1.2,                  pretty-show           >= 1.10     && < 1.11,                  process               >= 1.2.3    && < 1.7,-                 random                >= 1        && < 1.3,+                 random                >= 1.2      && < 1.4,                  safe                  >= 0.3.18   && < 0.4,                  scientific            >= 0.3      && < 0.4,-                 skylighting           >= 0.14.1.1 && < 0.15,-                 skylighting-core      >= 0.14.1.1 && < 0.15,+                 skylighting           >= 0.14.7   && < 0.15,+                 skylighting-core      >= 0.14.7   && < 0.15,                  split                 >= 0.2      && < 0.3,                  syb                   >= 0.1      && < 0.8,                  tagsoup               >= 0.14.6   && < 0.15,                  temporary             >= 1.1      && < 1.4,-                 texmath               >= 0.12.8.8 && < 0.13,+                 texmath               >= 0.13.1.2 && < 0.14,                  text                  >= 1.1.1.0  && < 2.2,                  text-conversions      >= 0.3      && < 0.4,-                 time                  >= 1.5      && < 1.14,+                 time                  >= 1.5      && < 1.17,                  unicode-collation     >= 0.1.1    && < 0.2,+                 unicode-data          >= 0.6      && < 0.9,                  unicode-transforms    >= 0.3      && < 0.5,                  yaml                  >= 0.11     && < 0.12,+                 libyaml               >= 0.1.4    && < 0.2,                  zip-archive           >= 0.4.3.1  && < 0.5,                  zlib                  >= 0.5      && < 0.8,                  xml                   >= 1.3.12   && < 1.4,-                 typst                 >= 0.5.0.3  && < 0.5.1,+                 typst                 >= 0.10     && < 0.11,                  vector                >= 0.12     && < 0.14,-                 djot                  >= 0.1.1.3  && < 0.2,-                 tls                   >= 2.0.1    && < 2.1,-                 crypton-x509-system   >= 1.6.7    && < 1.7+                 djot                  >= 0.1.4    && < 0.2,+                 asciidoc              >= 0.1.0.3  && < 0.2    if !os(windows)     build-depends:  unix >= 2.4 && < 2.9   if flag(embed_data_files)      cpp-options:   -DEMBED_DATA_FILES      other-modules: Text.Pandoc.Data.BakedIn+  if flag(http)+     cpp-options:   -DPANDOC_HTTP_SUPPORT+     build-depends:+                 crypton-connection    >= 0.3.1    && < 0.5,+                 crypton-x509-system   >= 1.6.7    && < 1.10,+                 http-client           >= 0.4.30   && < 0.8,+                 http-client-tls       >= 0.2.4    && < 0.5,+                 network               >= 2.6      && < 3.3,+                 tls                   >= 2.0.1    && < 2.5   hs-source-dirs:  src    exposed-modules: Text.Pandoc,@@ -554,6 +605,7 @@                    Text.Pandoc.Translations,                    Text.Pandoc.Translations.Types,                    Text.Pandoc.Readers,+                   Text.Pandoc.Readers.AsciiDoc,                    Text.Pandoc.Readers.HTML,                    Text.Pandoc.Readers.LaTeX,                    Text.Pandoc.Readers.Markdown,@@ -578,10 +630,13 @@                    Text.Pandoc.Readers.TikiWiki,                    Text.Pandoc.Readers.Txt2Tags,                    Text.Pandoc.Readers.Docx,+                   Text.Pandoc.Readers.Pptx,+                   Text.Pandoc.Readers.Xlsx,                    Text.Pandoc.Readers.ODT,                    Text.Pandoc.Readers.EPUB,                    Text.Pandoc.Readers.Muse,                    Text.Pandoc.Readers.Man,+                   Text.Pandoc.Readers.Mdoc,                    Text.Pandoc.Readers.FB2,                    Text.Pandoc.Readers.DokuWiki,                    Text.Pandoc.Readers.Ipynb,@@ -589,8 +644,10 @@                    Text.Pandoc.Readers.RTF,                    Text.Pandoc.Readers.Typst,                    Text.Pandoc.Readers.Djot,+                   Text.Pandoc.Readers.Pod,                    Text.Pandoc.Writers,                    Text.Pandoc.Writers.Native,+                   Text.Pandoc.Writers.XML,                    Text.Pandoc.Writers.DocBook,                    Text.Pandoc.Writers.JATS,                    Text.Pandoc.Writers.OPML,@@ -632,6 +689,9 @@                    Text.Pandoc.Writers.OOXML,                    Text.Pandoc.Writers.AnnotatedTable,                    Text.Pandoc.Writers.BibTeX,+                   Text.Pandoc.Writers.ANSI,+                   Text.Pandoc.Writers.Vimdoc,+                   Text.Pandoc.Writers.BBCode,                    Text.Pandoc.PDF,                    Text.Pandoc.UTF8,                    Text.Pandoc.Scripting,@@ -651,6 +711,7 @@                    Text.Pandoc.Class.IO,                    Text.Pandoc.Citeproc,                    Text.Pandoc.Chunks,+                   Text.Pandoc.Transforms,                    Text.Pandoc.Version   other-modules:   Text.Pandoc.App.CommandLineOptions,                    Text.Pandoc.App.Input,@@ -679,6 +740,14 @@                    Text.Pandoc.Readers.Docx.Util,                    Text.Pandoc.Readers.Docx.Symbols,                    Text.Pandoc.Readers.Docx.Fields,+                   Text.Pandoc.Readers.OOXML.Shared,+                   Text.Pandoc.Readers.Pptx.Parse,+                   Text.Pandoc.Readers.Pptx.Shapes,+                   Text.Pandoc.Readers.Pptx.Slides,+                   Text.Pandoc.Readers.Pptx.SmartArt,+                   Text.Pandoc.Readers.Xlsx.Parse,+                   Text.Pandoc.Readers.Xlsx.Cells,+                   Text.Pandoc.Readers.Xlsx.Sheets,                    Text.Pandoc.Readers.HTML.Parsing,                    Text.Pandoc.Readers.HTML.Table,                    Text.Pandoc.Readers.HTML.TagCategories,@@ -691,6 +760,9 @@                    Text.Pandoc.Readers.LaTeX.Parsing,                    Text.Pandoc.Readers.LaTeX.SIunitx,                    Text.Pandoc.Readers.LaTeX.Table,+                   Text.Pandoc.Readers.Mdoc.Lex,+                   Text.Pandoc.Readers.Mdoc.Macros,+                   Text.Pandoc.Readers.Mdoc.Standards,                    Text.Pandoc.Readers.Typst.Parsing,                    Text.Pandoc.Readers.Typst.Math,                    Text.Pandoc.Readers.ODT.Base,@@ -715,6 +787,9 @@                    Text.Pandoc.Readers.Org.Shared,                    Text.Pandoc.Readers.Metadata,                    Text.Pandoc.Readers.Roff,+                   Text.Pandoc.Readers.Roff.Escape,+                   Text.Pandoc.Readers.XML,+                   Text.Pandoc.Writers.Docx.OpenXML,                    Text.Pandoc.Writers.Docx.StyleMap,                    Text.Pandoc.Writers.Docx.Table,                    Text.Pandoc.Writers.Docx.Types,@@ -736,8 +811,10 @@                    Text.Pandoc.Writers.Blaze,                    Text.Pandoc.Writers.Powerpoint.Presentation,                    Text.Pandoc.Writers.Powerpoint.Output,+                   Text.Pandoc.Char,                    Text.Pandoc.TeX,                    Text.Pandoc.URI,+                   Text.Pandoc.XMLFormat,                    Text.Pandoc.CSS,                    Text.Pandoc.CSV,                    Text.Pandoc.RoffChar,@@ -760,10 +837,10 @@   main-is:        test-pandoc.hs   hs-source-dirs: test   build-depends:  pandoc,-                  Diff              >= 0.2     && < 0.6,+                  Diff              >= 0.2     && < 1.1,                   Glob              >= 0.7     && < 0.11,                   bytestring        >= 0.9     && < 0.13,-                  containers        >= 0.4.2.1 && < 0.8,+                  containers        >= 0.4.2.1 && < 0.9,                   directory         >= 1.2.3   && < 1.4,                   doctemplates      >= 0.11    && < 0.12,                   filepath          >= 1.1     && < 1.6,@@ -773,10 +850,10 @@                   tasty             >= 0.11    && < 1.6,                   tasty-golden      >= 2.3     && < 2.4,                   tasty-hunit       >= 0.9     && < 0.11,-                  tasty-quickcheck  >= 0.8     && < 0.11,+                  tasty-quickcheck  >= 0.8     && < 0.12,                   text              >= 1.1.1.0 && < 2.2,                   temporary         >= 1.1     && < 1.4,-                  time              >= 1.5     && < 1.14,+                  time              >= 1.5     && < 1.17,                   xml               >= 1.3.12  && < 1.4,                   zip-archive       >= 0.4.3   && < 0.5   other-modules:  Tests.Old@@ -784,6 +861,7 @@                   Tests.Helpers                   Tests.Shared                   Tests.MediaBag+                  Tests.XML                   Tests.Readers.LaTeX                   Tests.Readers.HTML                   Tests.Readers.JATS@@ -806,13 +884,17 @@                   Tests.Readers.RST                   Tests.Readers.RTF                   Tests.Readers.Docx+                  Tests.Readers.Pptx+                  Tests.Readers.Xlsx                   Tests.Readers.ODT                   Tests.Readers.Txt2Tags                   Tests.Readers.EPUB                   Tests.Readers.Muse                   Tests.Readers.Creole                   Tests.Readers.Man+                  Tests.Readers.Mdoc                   Tests.Readers.FB2+                  Tests.Readers.Pod                   Tests.Readers.DokuWiki                   Tests.Writers.Native                   Tests.Writers.ConTeXt@@ -835,6 +917,7 @@                   Tests.Writers.OOXML                   Tests.Writers.Ms                   Tests.Writers.AnnotatedTable+                  Tests.Writers.BBCode  benchmark benchmark-pandoc   import:          common-executable@@ -842,7 +925,7 @@   main-is:         benchmark-pandoc.hs   hs-source-dirs:  benchmark   build-depends:   bytestring,-                   tasty-bench >= 0.2     && <= 0.4,+                   tasty-bench >= 0.4     && <= 0.5,                    mtl         >= 2.2     && < 2.4,                    text        >= 1.1.1.0 && < 2.2,                    deepseq
src/Text/Pandoc.hs view
@@ -3,7 +3,7 @@ {-# LANGUAGE ScopedTypeVariables #-} {- |    Module      : Text.Pandoc-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>
src/Text/Pandoc/App.hs view
@@ -4,7 +4,7 @@ {-# LANGUAGE ScopedTypeVariables #-} {- |    Module      : Text.Pandoc.App-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley@edu>@@ -26,6 +26,7 @@           , parseOptionsFromArgs           , options           , applyFilters+          , versionInfo           ) where import qualified Control.Exception as E import Control.Monad ( (>=>), when, forM, forM_ )@@ -40,13 +41,16 @@ import qualified Data.Text.Lazy as TL import qualified Data.Text.Lazy.Encoding as TE import qualified Data.Text.Encoding.Error as TE-import System.Directory (doesDirectoryExist, createDirectory)+import Data.Char (toLower)+import System.Directory (doesDirectoryExist, createDirectory,+                         createDirectoryIfMissing) import Codec.Archive.Zip (toArchiveOrFail,                           extractFilesFromArchive, ZipOption(..)) import System.Exit (exitSuccess)-import System.FilePath ( takeBaseName, takeExtension)+import System.FilePath ( takeBaseName, takeExtension, takeDirectory) import System.IO (nativeNewline, stdout) import qualified System.IO as IO (Newline (..))+import Data.Version (showVersion) import Text.Pandoc import Text.Pandoc.Builder (setMeta) import Text.Pandoc.MediaBag (mediaItems)@@ -54,9 +58,12 @@ import Text.Pandoc.App.Opt (Opt (..), LineEnding (..), defaultOpts,                             IpynbOutput (..), OptInfo(..)) import Text.Pandoc.App.CommandLineOptions (parseOptions, parseOptionsFromArgs,-                                           options, handleOptInfo)+                                           options, handleOptInfo, versionInfo) import Text.Pandoc.App.Input (InputParameters (..), readInput)-import Text.Pandoc.App.OutputSettings (OutputSettings (..), optToOutputSettings)+import Text.Pandoc.App.OutputSettings (OutputSettings (..), optToOutputSettings,+                                       sandbox')+import Text.Pandoc.Transforms (applyTransforms, filterIpynbOutput,+                               headerShift, eastAsianLineBreakFilter) import Text.Collate.Lang (Lang (..), parseLang) import Text.Pandoc.Filter (Filter (JSONFilter, LuaFilter), Environment (..),                            applyFilters)@@ -64,9 +71,7 @@ import Text.Pandoc.PDF (makePDF) import Text.Pandoc.Scripting (ScriptingEngine (..), CustomComponents(..)) import Text.Pandoc.SelfContained (makeSelfContained)-import Text.Pandoc.Shared (eastAsianLineBreakFilter,-         headerShift, filterIpynbOutput, tshow)-import Text.Pandoc.URI (isURI)+import Text.Pandoc.Shared (tshow) import Text.Pandoc.Writers.Shared (lookupMetaString) import Text.Pandoc.Readers.Markdown (yamlToMeta) import qualified Text.Pandoc.UTF8 as UTF8@@ -113,11 +118,14 @@                      CRLF   -> IO.CRLF                      LF     -> IO.LF                      Native -> nativeNewline+      let outputFileDir = takeDirectory outputFile+      createDirectoryIfMissing True outputFileDir       case output of         TextOutput t    -> writerFn eol outputFile t         BinaryOutput bs -> writeFnBinary outputFile bs         ZipOutput bs-          | null (takeExtension outputFile) -> do+          | null (takeExtension outputFile)+          , outputFile /= "-" -> do              -- create directory and unzip              createDirectory outputFile -- will fail if directory exists              let zipopts = [OptRecursive, OptDestination outputFile] ++@@ -149,24 +157,17 @@       Nothing -> case Format.formatFromFilePaths sources of         Just f' -> return f'         Nothing | sources == ["-"] -> return $ defFlavor "markdown"-                | any (isURI . T.pack) sources -> return $ defFlavor "html"                 | otherwise -> do                     report $ CouldNotDeduceFormat                       (map (T.pack . takeExtension) sources) "markdown"                     return $ defFlavor "markdown"    let makeSandboxed pureReader =-        let files = maybe id (:) (optReferenceDoc opts) .-                    maybe id (:) (optEpubMetadata opts) .-                    maybe id (:) (optEpubCoverImage opts) .-                    maybe id (:) (optCSL opts) .-                    maybe id (:) (optCitationAbbreviations opts) $-                    optEpubFonts opts ++-                    optBibliography opts-         in  case pureReader of-               TextReader r -> TextReader $ \o t -> sandbox files (r o t)-               ByteStringReader r-                          -> ByteStringReader $ \o t -> sandbox files (r o t)+       case pureReader of+            TextReader r+              -> TextReader $ \o t -> sandbox' opts (r o t)+            ByteStringReader r+              -> ByteStringReader $ \o t -> sandbox' opts (r o t)    (reader, readerExts) <-     if ".lua" `T.isSuffixOf` readerNameBase@@ -192,7 +193,8 @@   let writerOptions = outputWriterOptions outputSettings    -- whether we are targeting PDF.-  let pdfOutput = isJust $ outputPdfProgram outputSettings+  let pdfOutput = map toLower (takeExtension outputFile) == ".pdf" ||+                  optTo opts == Just "pdf"   -- whether standalone output should be produced.   let bibOutput = format `elem` ["bibtex", "biblatex", "csljson"]   let standalone = isJust (writerTemplate writerOptions) || bibOutput@@ -236,6 +238,7 @@         , readerAbbreviations = abbrevs         , readerExtensions = readerExts         , readerStripComments = optStripComments opts+        , readerTypstInputs = optTypstInputs opts         }    metadataFromFile <- getMetadataFromFiles readerNameBase readerOpts@@ -297,8 +300,8 @@           >>= ( return . adjustMetadata (metadataFromFile <>)             >=> return . adjustMetadata (<> optMetadata opts)             >=> return . adjustMetadata (<> cslMetadata)-            >=> applyTransforms transforms             >=> applyFilters scriptingEngine filterEnv filters [T.unpack format]+            >=> applyTransforms transforms             >=> (if not (optSandbox opts) &&                     (isJust (optExtractMedia opts)                      || format == "docx") -- for fallback pngs@@ -315,7 +318,7 @@       | format == "chunkedhtml" -> ZipOutput <$> f writerOptions doc       | otherwise -> BinaryOutput <$> f writerOptions doc     TextWriter f -> case outputPdfProgram outputSettings of-      Just pdfProg -> do+      Just pdfProg | pdfOutput -> do               res <- makePDF pdfProg (optPdfEngineOpts opts) f                       writerOptions doc               case res of@@ -323,14 +326,18 @@                    Left err' -> throwError $ PandocPDFError $                                    TL.toStrict (TE.decodeUtf8With TE.lenientDecode err') -      Nothing -> do+      _ -> do               let ensureNl t                     | standalone = t                     | T.null t || T.last t /= '\n' = t <> T.singleton '\n'                     | otherwise = t               textOutput <- ensureNl <$> f writerOptions doc-              if (optSelfContained opts || optEmbedResources opts) && htmlFormat format-                 then TextOutput <$> makeSelfContained textOutput+              if htmlFormat format &&+                  (optSelfContained opts || optEmbedResources opts)+                 then if optSandbox opts+                         then sandbox' opts $+                              TextOutput <$> makeSelfContained textOutput+                         else TextOutput <$> makeSelfContained textOutput                  else return $ TextOutput textOutput   reports <- getLog   return (output, reports)@@ -341,8 +348,6 @@     | ZipOutput BL.ByteString   deriving (Show) -type Transform = Pandoc -> Pandoc- -- | Configure the common state configureCommonState :: PandocMonad m => Maybe FilePath -> Opt -> m () configureCommonState datadir opts = do@@ -354,6 +359,7 @@   setOutputFile (optOutputFile opts)   setNoCheckCertificate (optNoCheckCertificate opts) +  setRequestHeader "User-Agent" ("pandoc/" <> T.pack (showVersion pandocVersion))   mapM_ (uncurry setRequestHeader) (optRequestHeaders opts)    case lookupMetaString "lang" (optMetadata opts) of@@ -411,11 +417,6 @@  adjustMetadata :: (Meta -> Meta) -> Pandoc -> Pandoc adjustMetadata f (Pandoc meta bs) = Pandoc (f meta) bs---- Transformations of a Pandoc document post-parsing:--applyTransforms :: Monad m => [Transform] -> Pandoc -> m Pandoc-applyTransforms transforms d = return $ foldr ($) d transforms  writeFnBinary :: FilePath -> BL.ByteString -> IO () writeFnBinary "-" = BL.putStr
src/Text/Pandoc/App/CommandLineOptions.hs view
@@ -1,12 +1,11 @@ {-# LANGUAGE CPP                 #-}-{-# LANGUAGE LambdaCase          #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TupleSections       #-} {-# LANGUAGE OverloadedStrings   #-} {-# LANGUAGE FlexibleContexts    #-} {- |    Module      : Text.Pandoc.App.CommandLineOptions-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley@edu>@@ -22,15 +21,18 @@           , options           , engines           , setVariable+          , versionInfo           ) where import Control.Monad.Trans import Control.Monad.State.Strict import Data.Containers.ListUtils (nubOrd)+import Data.Aeson (eitherDecode) import Data.Aeson.Encode.Pretty (encodePretty', Config(..), keyOrder,          defConfig, Indent(..), NumberFormat(..)) import Data.Bifunctor (second) import Data.Char (toLower)-import Data.List (intercalate, sort, foldl')+import Data.List (intercalate, sort)+import qualified Data.List as L #ifdef _WINDOWS import Data.List (isPrefixOf) #endif@@ -46,6 +48,7 @@ import Text.DocTemplates (Context (..), ToContext (toVal), Val (..)) import Text.Pandoc import Text.Pandoc.Builder (setMeta)+import Data.Version (showVersion) import Text.Pandoc.App.Opt (Opt (..), LineEnding (..), IpynbOutput (..),                             DefaultsState (..), applyDefaults,                             fullDefaultsPath, OptInfo(..))@@ -98,7 +101,7 @@    if (null errors && null unknownOptionErrors)      then -- thread option data structure through all supplied option actions-       runExceptT $ adjustOpts <$> (foldl' (>>=) (return defaults) actions)+       runExceptT $ adjustOpts <$> (L.foldl' (>>=) (return defaults) actions)      else return $ Left $ OptError $ PandocOptionError $ T.pack $              concat errors ++ unlines unknownOptionErrors ++              ("Try " ++ prg ++ " --help for more information.")@@ -193,37 +196,32 @@                      ,"text-styles"])                   ,confNumFormat = Generic                   ,confTrailingNewline = True} sty-    VersionInfo -> do-      prg <- getProgName-      defaultDatadir <- defaultUserDataDir-      UTF8.hPutStrLn stdout-       $ T.pack-       $ prg ++ " " ++ T.unpack pandocVersionText ++-         compileInfo ++-         "\nUser data directory: " ++ defaultDatadir ++-         ('\n':copyrightMessage)+    VersionInfo -> versionInfo [] Nothing ""     Help -> do       prg <- getProgName-      UTF8.hPutStr stdout (T.pack $ usageMessage prg options)+      mapM_ (UTF8.hPutStrLn stdout . T.stripEnd . T.pack) $+        lines $ usageMessage prg options     OptError e -> E.throwIO e   exitSuccess  -- | Supported LaTeX engines; the first item is used as default engine -- when going through LaTeX. latexEngines :: [String]-latexEngines  = ["pdflatex", "lualatex", "xelatex", "latexmk", "tectonic"]+latexEngines  = [ "pdflatex", "lualatex", "xelatex", "latexmk", "tectonic"+                , "pdflatex-dev", "lualatex-dev" ]  -- | Supported HTML PDF engines; the first item is used as default -- engine when going through HTML. htmlEngines :: [String]-htmlEngines  = ["wkhtmltopdf", "weasyprint", "pagedjs-cli", "prince"]+htmlEngines  = ["weasyprint", "wkhtmltopdf", "pagedjs-cli", "prince"]  engines :: [(Text, String)] engines = map ("html",) htmlEngines ++           map ("html5",) htmlEngines ++           map ("latex",) latexEngines ++           map ("beamer",) latexEngines ++-          [ ("ms", "pdfroff")+          [ ("ms", "groff")+          , ("ms", "pdfroff")           , ("typst", "typst")           , ("context", "context")           ]@@ -306,7 +304,7 @@                      let (key, val) = splitField arg                      return opt{ optMetadata = addMeta key val $                                                  optMetadata opt })-                  "KEY[:VALUE]")+                  "KEY[=VALUE]")                  ""      , Option "" ["metadata-file"]@@ -348,7 +346,7 @@                   "true|false")                  "" -    , Option "s" ["standalone"]+     , Option "s" ["standalone"]                  (OptArg                   (\arg opt -> do                         boolValue <- readBoolFromOptArg "--standalone/-s" arg@@ -370,9 +368,26 @@                      return opt{ optVariables =                                   setVariable (T.pack key) (T.pack val) $                                     optVariables opt })-                  "KEY[:VALUE]")+                  "KEY[=VALUE]")                  "" +    , Option "" ["variable-json"]+                 (ReqArg+                  (\arg opt -> do+                     let (key, json) = splitField arg+                     case eitherDecode (B.fromStrict . UTF8.fromString $ json) of+                       Right (val :: Val Text) ->+                         return opt{ optVariables =+                                      let Context m = optVariables opt+                                       in Context $ M.insert (T.pack key) val m }+                           -- note that this replaces any existing value, which+                           -- is different from what --variable does+                       Left err'  -> optError $ PandocOptionError $+                          "Could not parse '" <> T.pack json <> "' as JSON:\n" <>+                           T.pack err')+                  "KEY[:JSON]")+                 ""+     , Option "" ["wrap"]                  (ReqArg                   (\arg opt ->@@ -412,9 +427,28 @@                  "NUMBER")                  "" -- "Number of levels to include in TOC" +    , Option "" ["lof", "list-of-figures"]+                (OptArg+                 (\arg opt -> do+                        boolValue <- readBoolFromOptArg "--lof/--list-of-figures" arg+                        return opt { optListOfFigures = boolValue })+                 "true|false")+               "" -- "Include list of figures"++    , Option "" ["lot", "list-of-tables"]+                (OptArg+                 (\arg opt -> do+                        boolValue <- readBoolFromOptArg "--lot/--list-of-tables" arg+                        return opt { optListOfTables = boolValue })+                 "true|false")+               "" -- "Include list of tables"+     , Option "N" ["number-sections"]-                 (NoArg-                  (\opt -> return opt { optNumberSections = True }))+                  (OptArg+                   (\arg opt -> do+                        boolValue <- readBoolFromOptArg "--number-sections/-N" arg+                        return opt { optNumberSections = boolValue })+                  "true|false")                  "" -- "Number sections"      , Option "" ["number-offset"]@@ -488,13 +522,18 @@      , Option "" ["no-highlight"]                 (NoArg-                 (\opt -> return opt { optHighlightStyle = Nothing }))+                 (\opt -> do+                     deprecatedOption "--no-highlight"+                       "Use --syntax-highlighting=none instead."+                     return opt { optSyntaxHighlighting = NoHighlightingString }))                  "" -- "Don't highlight source code"      , Option "" ["highlight-style"]                 (ReqArg-                 (\arg opt ->-                     return opt{ optHighlightStyle = Just $+                 (\arg opt -> do+                     deprecatedOption "--highlight-style"+                       "Use --syntax-highlighting instead."+                     return opt{ optSyntaxHighlighting =                                  T.pack $ normalizePath arg })                  "STYLE|FILE")                  "" -- "Style for highlighted code"@@ -507,6 +546,14 @@                  "FILE")                 "" -- "Syntax definition (xml) file" +    , Option "" ["syntax-highlighting"]+                (ReqArg+                 (\arg opt -> return opt{ optSyntaxHighlighting =+                                 T.pack $ normalizePath arg })+                 "none|default|idiomatic|<stylename>|<themepath>")+                 "" -- "syntax highlighting method for code"++     , Option "" ["dpi"]                  (ReqArg                   (\arg opt ->@@ -566,8 +613,8 @@                         then return opt { optPdfEngine = Just arg }                         else optError $                               PandocOptionError $ T.pack $-                              "Argument of --pdf-engine must be one of "-                               ++ intercalate ", " pdfEngines)+                              "Argument of --pdf-engine must be one of\n"+                               ++ concatMap (\e -> "\t" <> e <> "\n") pdfEngines)                   "PROGRAM")                  "" -- "Name of program to use in generating PDF" @@ -603,13 +650,21 @@                   "true|false")                  "" -- "Make slide shows include all the needed js and css" +    , Option "" ["link-images"] -- maybe True (\argStr -> argStr == "true") arg+                 (OptArg+                  (\arg opt -> do+                        boolValue <- readBoolFromOptArg "--link-images" arg+                        return opt { optLinkImages =  boolValue })+                  "true|false")+                 "" -- "Link images in ODT rather than embedding them"+     , Option "" ["request-header"]                  (ReqArg                   (\arg opt -> do                      let (key, val) = splitField arg                      return opt{ optRequestHeaders =                        (T.pack key, T.pack val) : optRequestHeaders opt })-                  "NAME:VALUE")+                  "NAME=VALUE")                  ""      , Option "" ["no-check-certificate"]@@ -627,6 +682,14 @@                 "FILE")                 "" -- "Specify file for custom abbreviations" +    , Option "" ["typst-input"]+                 (ReqArg+                  (\arg opt -> do+                     let (key, val) = splitField arg+                     return opt{ optTypstInputs = (T.pack key, T.pack val) : optTypstInputs opt })+                  "KEY=VALUE")+                 ""+     , Option "" ["indented-code-classes"]                   (ReqArg                    (\arg opt -> return opt { optIndentedCodeClasses = T.words $@@ -719,8 +782,32 @@                                "Argument of --reference-location must be block, section, or document"                      return opt { optReferenceLocation = action })                   "block|section|document")-                 "" -- "Accepting or reject MS Word track-changes.""+                 "" -- "Specify where reference links and footnotes go" +    , Option "" ["figure-caption-position"]+                 (ReqArg+                  (\arg opt -> do+                     pos <- case arg of+                            "above"  -> return CaptionAbove+                            "below"  -> return CaptionBelow+                            _        -> optError $ PandocOptionError $ T.pack+                               "Argument of --figure-caption-position must be above or below"+                     return opt { optFigureCaptionPosition = pos })+                  "above|below")+                 "" -- "Specify where figure captions go"++    , Option "" ["table-caption-position"]+                 (ReqArg+                  (\arg opt -> do+                     pos <- case arg of+                            "above"  -> return CaptionAbove+                            "below"  -> return CaptionBelow+                            _        -> optError $ PandocOptionError $ T.pack+                               "Argument of --table-caption-position must be above or below"+                     return opt { optTableCaptionPosition = pos })+                  "above|below")+                 "" -- "Specify where table captions go"+     , Option "" ["markdown-headings"]                   (ReqArg                     (\arg opt -> do@@ -745,8 +832,14 @@     , Option "" ["listings"]                  (OptArg                   (\arg opt -> do-                        boolValue <- readBoolFromOptArg "--listings" arg-                        return opt { optListings = boolValue })+                      deprecatedOption "--listings"+                        "Use --syntax-highlighting=idiomatic instead."+                      boolValue <- readBoolFromOptArg "--listings" arg+                      return $+                        if boolValue+                        then opt { optSyntaxHighlighting =+                                   IdiomaticHighlightingString }+                        else opt)                   "true|false")                  "" -- "Use listings package for LaTeX code blocks" @@ -959,8 +1052,8 @@     , Option "" ["webtex"]                  (OptArg                   (\arg opt -> do-                      let url' = fromMaybe "https://latex.codecogs.com/png.latex?" arg-                      return opt { optHTMLMathMethod = WebTeX $ T.pack url' })+                      let url' = maybe defaultWebTeXURL T.pack arg+                      return opt { optHTMLMathMethod = WebTeX url' })                   "URL")                  "" -- "Use web service for HTML math" @@ -1104,17 +1197,10 @@  copyrightMessage :: String copyrightMessage = intercalate "\n" [- "Copyright (C) 2006-2023 John MacFarlane. Web:  https://pandoc.org",+ "Copyright (C) 2006-2025 John MacFarlane. Web:  https://pandoc.org",  "This is free software; see the source for copying conditions. There is no",  "warranty, not even for merchantability or fitness for a particular purpose." ] -compileInfo :: String-compileInfo =-  "\nCompiled with pandoc-types " ++ VERSION_pandoc_types ++-  ", texmath " ++ VERSION_texmath ++ ", skylighting " ++-  VERSION_skylighting ++ ",\nciteproc " ++ VERSION_citeproc ++-  ", ipynb " ++ VERSION_ipynb- handleUnrecognizedOption :: String -> [String] -> [String] handleUnrecognizedOption "--smart" =   (("--smart/-S has been removed.  Use +smart or -smart extension instead.\n" ++@@ -1209,3 +1295,21 @@ #else normalizePath = id #endif++-- | Print version information with customizable features and scripting engine+versionInfo :: [String] -> Maybe String -> String -> IO ()+versionInfo features mbScriptingEngineName suffix = do+  defaultDatadir <- defaultUserDataDir+  let featuresLine = if null features+                       then []+                       else ["Features: " ++ unwords features]+  let scriptingLine = case mbScriptingEngineName of+                        Nothing -> []+                        Just name -> ["Scripting engine: " ++ name]+  UTF8.putStr $ T.unlines $ map T.pack $+    ["pandoc " ++ showVersion pandocVersion ++ suffix] +++    featuresLine +++    scriptingLine +++    ["User data directory: " ++ defaultDatadir,+     copyrightMessage]+  exitSuccess
src/Text/Pandoc/App/Input.hs view
@@ -3,7 +3,7 @@ {-# LANGUAGE TupleSections       #-} {- |    Module      : Text.Pandoc.App.Input-   Copyright   : © 2006-2023 John MacFarlane+   Copyright   : © 2006-2024 John MacFarlane    License     : GPL-2.0-or-later    Maintainer  : John MacFarlane <jgm@berkeley@edu> @@ -14,21 +14,21 @@   , readInput   ) where -import Control.Monad ((>=>))+import Control.Monad ((>=>), when) import Control.Monad.Except (throwError, catchError) import Data.Text (Text)-import Network.URI (URI (..), parseURI, unEscapeString)+import Network.URI (URI (..), parseURI)+import Text.Pandoc.Transforms (adjustLinksAndIds) import Text.Pandoc.Class ( PandocMonad, openURL, toTextM                          , readFileStrict, readStdinStrict, report)-import Text.Pandoc.Definition (Pandoc (..), Attr, Block (..), Inline (..))+import Text.Pandoc.Definition (Pandoc) import Text.Pandoc.Error (PandocError (..)) import Text.Pandoc.Logging (LogMessage (..)) import Text.Pandoc.MIME (getCharset, MimeType)-import Text.Pandoc.Options (Extensions, ReaderOptions (..))+import Text.Pandoc.Options (ReaderOptions (..)) import Text.Pandoc.Readers (Reader (..))-import Text.Pandoc.Shared (tabFilter, textToIdentifier)+import Text.Pandoc.Shared (tabFilter) import Text.Pandoc.URI (uriPathToPath)-import Text.Pandoc.Walk (walk) import qualified Data.ByteString as BS import qualified Data.ByteString.Char8 as B8 import qualified Data.ByteString.Lazy as BL@@ -109,67 +109,30 @@                            (toTextM fp bs)                            (\case                               PandocUTF8DecodingError{} -> do+                                when (hasKnownSignature bs) $+                                  throwError $+                                    PandocInputNotTextError (T.pack fp)                                 report $ NotUTF8Encoded                                   (if null fp                                       then "input"                                       else fp)                                 return $ T.pack $ B8.unpack bs                               e -> throwError e)+ where+  -- "50 4B 03 04" is zip file signature+  isZip bs' = "\x50\x4B\x03\x04" `BS.isPrefixOf` bs'+  -- "25 50 44 46 2D" is PDF file signature+  isPDF bs' = "\x25\x50\x44\x46\x2D" `BS.isPrefixOf` bs'+  -- "D0 CF 11 E0 A1 B1 1A E1" is Compound File Binary Format signature used in+  -- variety of old Microsoft formats (.doc and .xls among others)+  isCFBF bs' = "\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1" `BS.isPrefixOf` bs'+  -- "41 54 26 54 46 4F 52 4D ?? ?? ?? ?? 44 4A 56" is DjVu signature+  isDjVu bs' = case BS.stripPrefix "\x41\x54\x26\x54\x46\x4F\x52\x4D" bs' of+    Nothing -> False+    Just x -> BS.isPrefixOf "\x44\x4A\x56" $ BS.drop 4 x +  hasKnownSignature bs' = any ($ bs') [isZip, isPDF, isCFBF, isDjVu]+ inputToLazyByteString :: (FilePath, (BS.ByteString, Maybe MimeType))                       -> BL.ByteString inputToLazyByteString (_, (bs,_)) = BL.fromStrict bs--adjustLinksAndIds :: Extensions -> Text -> [Text] -> Pandoc -> Pandoc-adjustLinksAndIds exts thisfile allfiles-  | length allfiles > 1 = addDiv . walk fixInline . walk fixBlock-  | otherwise           = id- where-  toIdent :: Text -> Text-  toIdent = textToIdentifier exts . T.intercalate "__" .-            T.split (\c -> c == '/' || c == '\\')--  addDiv :: Pandoc -> Pandoc-  addDiv (Pandoc m bs)-    | T.null thisfile = Pandoc m bs-    | otherwise = Pandoc m [Div (toIdent thisfile,[],[]) bs]--  fixBlock :: Block -> Block-  fixBlock (CodeBlock attr t) = CodeBlock (fixAttrs attr) t-  fixBlock (Header lev attr ils) = Header lev (fixAttrs attr) ils-  fixBlock (Table attr cap cols th tbs tf) =-     Table (fixAttrs attr) cap cols th tbs tf-  fixBlock (Div attr bs) = Div (fixAttrs attr) bs-  fixBlock x = x--  -- add thisfile as prefix of identifier-  fixAttrs :: Attr -> Attr-  fixAttrs (i,cs,kvs)-    | T.null i = (i,cs,kvs)-    | otherwise =-        (T.intercalate "__"-          (filter (not . T.null) [toIdent thisfile, i]),-        cs, kvs)--  -- if URL begins with file from allfiles, convert to-  -- an internal link with the appropriate identifier-  fixURL :: Text -> Text-  fixURL u =-    let (a,b) = T.break (== '#') $ T.pack . unEscapeString . T.unpack $ u-        filepart = if T.null a-                      then toIdent thisfile-                      else toIdent a-        fragpart = T.dropWhile (== '#') b-     in if T.null a || a `elem` allfiles-           then "#" <> T.intercalate "__"-                         (filter (not . T.null) [filepart, fragpart])-           else u--  fixInline :: Inline -> Inline-  fixInline (Code attr t) = Code (fixAttrs attr) t-  fixInline (Link attr ils (url,tit)) =-    Link (fixAttrs attr) ils (fixURL url,tit)-  fixInline (Image attr ils (url,tit)) =-    Image (fixAttrs attr) ils (fixURL url,tit)-  fixInline (Span attr ils) = Span (fixAttrs attr) ils-  fixInline x = x
src/Text/Pandoc/App/Opt.hs view
@@ -2,12 +2,13 @@ {-# LANGUAGE OverloadedStrings   #-} {-# LANGUAGE CPP                 #-} {-# LANGUAGE DeriveGeneric       #-}+{-# LANGUAGE PatternSynonyms     #-} {-# LANGUAGE TemplateHaskell     #-} {-# LANGUAGE FlexibleInstances   #-} {-# LANGUAGE FlexibleContexts    #-} {- |    Module      : Text.Pandoc.App.Opt-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley@edu>@@ -27,12 +28,12 @@           , fullDefaultsPath           ) where import Control.Monad.Except (throwError)-import Control.Monad.Trans (MonadIO, liftIO)+import Control.Monad.Trans (MonadIO, liftIO, lift) import Control.Monad ((>=>), foldM) import Control.Monad.State.Strict (StateT, modify, gets) import System.FilePath ( addExtension, (</>), takeExtension, takeDirectory ) import System.Directory ( canonicalizePath )-import Data.Char (toLower)+import Data.Char (toLower, isSpace) import Data.Maybe (fromMaybe) import GHC.Generics hiding (Meta) import Text.Pandoc.Filter (Filter (..))@@ -41,8 +42,10 @@                             TrackChanges (AcceptChanges),                             WrapOption (WrapAuto), HTMLMathMethod (PlainMath),                             ReferenceLocation (EndOfDocument),+                            CaptionPosition (..),                             ObfuscationMethod (NoObfuscation),-                            CiteMethod (Citeproc))+                            CiteMethod (Citeproc),+                            pattern DefaultHighlightingString) import Text.Pandoc.Class (readFileStrict, fileExists, setVerbosity, report,                           PandocMonad(lookupEnv), getUserDataDir) import Text.Pandoc.Error (PandocError (PandocParseError, PandocSomeError))@@ -59,7 +62,7 @@ import qualified Data.ByteString.Char8 as B8 import Text.Pandoc.Definition (Meta(..), MetaValue(..)) import Data.Aeson (defaultOptions, Options(..), Result(..),-                   genericToJSON, fromJSON, camelTo2)+                   genericToJSON, fromJSON, camelTo2, eitherDecodeStrict) import Data.Aeson.TH (deriveJSON) import Control.Applicative ((<|>)) import Data.Yaml@@ -106,6 +109,8 @@     , optFrom                  :: Maybe Text  -- ^ Reader format     , optTo                    :: Maybe Text  -- ^ Writer format     , optTableOfContents       :: Bool    -- ^ Include table of contents+    , optListOfFigures         :: Bool    -- ^ Include list of figures+    , optListOfTables          :: Bool    -- ^ Include list of tables     , optShiftHeadingLevelBy   :: Int     -- ^ Shift heading level by     , optTemplate              :: Maybe FilePath  -- ^ Custom template     , optVariables             :: Context Text    -- ^ Template variables to set@@ -119,9 +124,10 @@     , optIncremental           :: Bool    -- ^ Use incremental lists in Slidy/Slideous/S5     , optSelfContained         :: Bool    -- ^ Make HTML accessible offline (deprecated)     , optEmbedResources        :: Bool    -- ^ Make HTML accessible offline+    , optLinkImages            :: Bool    -- ^ Link ODT images rather than embedding     , optHtmlQTags             :: Bool    -- ^ Use <q> tags in HTML-    , optHighlightStyle        :: Maybe Text -- ^ Style to use for highlighted code     , optSyntaxDefinitions     :: [FilePath]  -- ^ xml syntax defs to load+    , optSyntaxHighlighting    :: Text -- ^ Syntax highlighting method for code     , optTopLevelDivision      :: TopLevelDivision -- ^ Type of the top-level divisions     , optHTMLMathMethod        :: HTMLMathMethod -- ^ Method to print HTML math     , optAbbreviations         :: Maybe FilePath -- ^ Path to abbrevs file@@ -142,6 +148,8 @@     , optFailIfWarnings        :: Bool    -- ^ Fail on warnings     , optReferenceLinks        :: Bool    -- ^ Use reference links in writing markdown, rst     , optReferenceLocation     :: ReferenceLocation -- ^ location for footnotes and link references in markdown output+    , optFigureCaptionPosition :: CaptionPosition -- ^ position for figure caption+    , optTableCaptionPosition  :: CaptionPosition -- ^ position for table caption     , optDpi                   :: Int     -- ^ Dpi     , optWrap                  :: WrapOption  -- ^ Options for wrapping text     , optColumns               :: Int     -- ^ Line length in characters@@ -151,7 +159,6 @@     , optIndentedCodeClasses   :: [Text] -- ^ Default classes for indented code blocks     , optDataDir               :: Maybe FilePath     , optCiteMethod            :: CiteMethod -- ^ Method to output cites-    , optListings              :: Bool       -- ^ Use listings package for code blocks     , optPdfEngine             :: Maybe String -- ^ Program to use for latex/html -> pdf     , optPdfEngineOpts         :: [String]   -- ^ Flags to pass to the engine     , optSlideLevel            :: Maybe Int  -- ^ Header level that creates slides@@ -177,6 +184,7 @@     , optBibliography          :: [FilePath]  -- ^ Bibliography files     , optCitationAbbreviations :: Maybe FilePath -- ^ Citation abbreviations     , optSandbox               :: Bool+    , optTypstInputs           :: [(Text, Text)] -- ^ List of parameter values for typst     } deriving (Generic, Show)  instance FromJSON Opt where@@ -188,6 +196,8 @@        <*> o .:? "from"        <*> o .:? "to"        <*> o .:? "table-of-contents" .!= optTableOfContents defaultOpts+       <*> o .:? "list-of-figures" .!= optListOfFigures defaultOpts+       <*> o .:? "list-of-tables" .!= optListOfTables defaultOpts        <*> o .:? "shift-heading-level-by" .!= optShiftHeadingLevelBy defaultOpts        <*> o .:? "template"        <*> o .:? "variables" .!= optVariables defaultOpts@@ -201,9 +211,10 @@        <*> o .:? "incremental" .!= optIncremental defaultOpts        <*> o .:? "self-contained" .!= optSelfContained defaultOpts        <*> o .:? "embed-resources" .!= optEmbedResources defaultOpts+       <*> o .:? "link-images" .!= optLinkImages defaultOpts        <*> o .:? "html-q-tags" .!= optHtmlQTags defaultOpts-       <*> o .:? "highlight-style"        <*> o .:? "syntax-definitions" .!= optSyntaxDefinitions defaultOpts+       <*> o .:? "syntax-highlighting" .!= optSyntaxHighlighting defaultOpts        <*> o .:? "top-level-division" .!= optTopLevelDivision defaultOpts        <*> o .:? "html-math-method" .!= optHTMLMathMethod defaultOpts        <*> o .:? "abbreviations"@@ -225,6 +236,8 @@        <*> o .:? "fail-if-warnings" .!= optFailIfWarnings defaultOpts        <*> o .:? "reference-links" .!= optReferenceLinks defaultOpts        <*> o .:? "reference-location" .!= optReferenceLocation defaultOpts+       <*> o .:? "figure-caption-position" .!= optFigureCaptionPosition defaultOpts+       <*> o .:? "table-caption-position" .!= optTableCaptionPosition defaultOpts        <*> o .:? "dpi" .!= optDpi defaultOpts        <*> o .:? "wrap" .!= optWrap defaultOpts        <*> o .:? "columns" .!= optColumns defaultOpts@@ -234,7 +247,6 @@        <*> o .:? "indented-code-classes" .!= optIndentedCodeClasses defaultOpts        <*> o .:? "data-dir"        <*> o .:? "cite-method" .!= optCiteMethod defaultOpts-       <*> o .:? "listings" .!= optListings defaultOpts        <*> o .:? "pdf-engine"        <*> o .:? "pdf-engine-opts" .!= optPdfEngineOpts defaultOpts        <*> o .:? "slide-level"@@ -260,6 +272,7 @@        <*> o .:? "bibliography" .!= optBibliography defaultOpts        <*> o .:? "citation-abbreviations"        <*> o .:? "sandbox" .!= optSandbox defaultOpts+       <*> o .:? "typst-inputs" .!= optTypstInputs defaultOpts  instance ToJSON Opt where  toJSON = genericToJSON defaultOptions{@@ -301,11 +314,14 @@                  => Opt -> StateT DefaultsState m Opt resolveVarsInOpt     opt@Opt-    { optTemplate              = oTemplate+    { optTo                    = oTo+    , optFrom                  = oFrom+    , optTemplate              = oTemplate     , optMetadataFiles         = oMetadataFiles     , optOutputFile            = oOutputFile     , optInputFiles            = oInputFiles     , optSyntaxDefinitions     = oSyntaxDefinitions+    , optSyntaxHighlighting    = oSyntaxHighlighting     , optAbbreviations         = oAbbreviations     , optReferenceDoc          = oReferenceDoc     , optEpubMetadata          = oEpubMetadata@@ -324,9 +340,10 @@     , optBibliography          = oBibliography     , optCitationAbbreviations = oCitationAbbreviations     , optPdfEngine             = oPdfEngine-    , optHighlightStyle        = oHighlightStyle     }   = do+      oTo' <- mapM (fmap T.pack . resolveVars . T.unpack) oTo+      oFrom' <- mapM (fmap T.pack . resolveVars . T.unpack) oFrom       oTemplate' <- mapM resolveVars oTemplate       oMetadataFiles' <- mapM resolveVars oMetadataFiles       oOutputFile' <- mapM resolveVars oOutputFile@@ -350,12 +367,15 @@       oBibliography' <- mapM resolveVars oBibliography       oCitationAbbreviations' <- mapM resolveVars oCitationAbbreviations       oPdfEngine' <- mapM resolveVars oPdfEngine-      oHighlightStyle' <- mapM (fmap T.pack . resolveVars . T.unpack) oHighlightStyle-      return opt{ optTemplate              = oTemplate'+      oSyntaxHighlighting' <- T.pack <$> resolveVars (T.unpack oSyntaxHighlighting)+      return opt{ optTo                    = oTo'+                , optFrom                  = oFrom'+                , optTemplate              = oTemplate'                 , optMetadataFiles         = oMetadataFiles'                 , optOutputFile            = oOutputFile'                 , optInputFiles            = oInputFiles'                 , optSyntaxDefinitions     = oSyntaxDefinitions'+                , optSyntaxHighlighting    = oSyntaxHighlighting'                 , optAbbreviations         = oAbbreviations'                 , optReferenceDoc          = oReferenceDoc'                 , optEpubMetadata          = oEpubMetadata'@@ -374,43 +394,52 @@                 , optBibliography          = oBibliography'                 , optCitationAbbreviations = oCitationAbbreviations'                 , optPdfEngine             = oPdfEngine'-                , optHighlightStyle        = oHighlightStyle'                 }   where-  resolveVars :: FilePath -> StateT DefaultsState m FilePath-  resolveVars [] = return []-  resolveVars ('$':'{':xs) =+  resolveVars = expandVars (optDataDir opt)+  resolveVarsInFilter (JSONFilter fp) =+    JSONFilter <$> resolveVars fp+  resolveVarsInFilter (LuaFilter fp) =+    LuaFilter <$> resolveVars fp+  resolveVarsInFilter CiteprocFilter = return CiteprocFilter+++expandVars :: (PandocMonad m, MonadIO m)+           => Maybe FilePath+           -> FilePath+           -> StateT DefaultsState m FilePath+expandVars _ [] = return []+expandVars mbDataDir ('$':'{':xs) =     let (ys, zs) = break (=='}') xs      in if null zs            then return $ '$':'{':xs            else do-             val <- lookupEnv' ys-             (val ++) <$> resolveVars (drop 1 zs)-  resolveVars (c:cs) = (c:) <$> resolveVars cs-  lookupEnv' :: String -> StateT DefaultsState m String-  lookupEnv' "." = do+             val <- expandEnv mbDataDir ys+             (val ++) <$> expandVars mbDataDir (drop 1 zs)+expandVars mbDataDir (c:cs) = (c:) <$> expandVars mbDataDir cs++expandEnv :: (PandocMonad m, MonadIO m)+          => Maybe FilePath+          -> String+          -> StateT DefaultsState m String+expandEnv _ "." = do     mbCurDefaults <- gets curDefaults     maybe (return "")           (fmap takeDirectory . liftIO . canonicalizePath)           mbCurDefaults-  lookupEnv' "USERDATA" = do-    mbodatadir <- mapM resolveVars oDataDir-    mbdatadir  <- getUserDataDir+expandEnv mbDataDir "USERDATA" = do+    mbodatadir <- mapM (expandVars mbDataDir) mbDataDir+    mbdatadir'  <- getUserDataDir     defdatadir <- liftIO defaultUserDataDir-    return $ fromMaybe defdatadir (mbodatadir <|> mbdatadir)-  lookupEnv' v = do+    return $ fromMaybe defdatadir (mbodatadir <|> mbdatadir')+expandEnv _ v = do     mbval <- fmap T.unpack <$> lookupEnv (T.pack v)     case mbval of       Nothing -> do         report $ EnvironmentVariableUndefined (T.pack v)         return mempty       Just x  -> return x-  resolveVarsInFilter (JSONFilter fp) =-    JSONFilter <$> resolveVars fp-  resolveVarsInFilter (LuaFilter fp) =-    LuaFilter <$> resolveVars fp-  resolveVarsInFilter CiteprocFilter = return CiteprocFilter   @@ -421,8 +450,9 @@ parseDefaults n dataDir = parseDefsNames n >>= \ds -> return $ \o -> do   -- get parent defaults:   defsParent <- gets $ fromMaybe "" . curDefaults+  expandedDataDir <- mapM (expandVars dataDir) dataDir   -- get child defaults:-  defsChildren <- mapM (fullDefaultsPath dataDir) ds+  defsChildren <- mapM (\d -> expandVars expandedDataDir d >>= lift . fullDefaultsPath expandedDataDir) ds   -- expand parent in defaults inheritance graph by children:   defsGraph <- gets inheritanceGraph   let defsGraphExp = expand defsGraph defsChildren defsParent@@ -467,6 +497,14 @@       parseJSON v >>= \x -> return (\o -> o{ optTableOfContents = x })     "toc" ->       parseJSON v >>= \x -> return (\o -> o{ optTableOfContents = x })+    "list-of-figures" ->+      parseJSON v >>= \x -> return (\o -> o{ optListOfFigures = x })+    "lof" ->+      parseJSON v >>= \x -> return (\o -> o{ optListOfFigures = x })+    "list-of-tables" ->+      parseJSON v >>= \x -> return (\o -> o{ optListOfTables = x })+    "lot" ->+      parseJSON v >>= \x -> return (\o -> o{ optListOfTables = x })     "from" ->       parseJSON v >>= \x -> return (\o -> o{ optFrom = x })     "reader" ->@@ -526,10 +564,13 @@       parseJSON v >>= \x -> return (\o -> o{ optSelfContained = x })     "embed-resources" ->       parseJSON v >>= \x -> return (\o -> o{ optEmbedResources = x })+    "link-images" ->+      parseJSON v >>= \x -> return (\o -> o{ optLinkImages = x })     "html-q-tags" ->       parseJSON v >>= \x -> return (\o -> o{ optHtmlQTags = x })+    -- Deprecated     "highlight-style" ->-      parseJSON v >>= \x -> return (\o -> o{ optHighlightStyle = x })+      parseJSON v >>= \x -> return (\o -> o{ optSyntaxHighlighting = x })     "syntax-definition" ->       (parseJSON v >>= \x ->                 return (\o -> o{ optSyntaxDefinitions =@@ -542,6 +583,8 @@       parseJSON v >>= \x ->              return (\o -> o{ optSyntaxDefinitions =                                 optSyntaxDefinitions o <> map unpack x })+    "syntax-highlighting" ->+      parseJSON v >>= \x -> return (\o -> o{ optSyntaxHighlighting = x })     "top-level-division" ->       parseJSON v >>= \x -> return (\o -> o{ optTopLevelDivision = x })     "html-math-method" ->@@ -590,6 +633,10 @@       parseJSON v >>= \x -> return (\o -> o{ optReferenceLinks = x })     "reference-location" ->       parseJSON v >>= \x -> return (\o -> o{ optReferenceLocation = x })+    "figure-caption-position" ->+      parseJSON v >>= \x -> return (\o -> o{ optFigureCaptionPosition = x })+    "table-caption-position" ->+      parseJSON v >>= \x -> return (\o -> o{ optTableCaptionPosition = x })     "dpi" ->       parseJSON v >>= \x -> return (\o -> o{ optDpi = x })     "wrap" ->@@ -616,7 +663,10 @@     "cite-method" ->       parseJSON v >>= \x -> return (\o -> o{ optCiteMethod = x })     "listings" ->-      parseJSON v >>= \x -> return (\o -> o{ optListings = x })+      parseJSON v >>= \x ->+        if x+        then return (\o -> o{ optSyntaxHighlighting = "idiomatic" })+        else return id     "pdf-engine" ->       parseJSON v >>= \x -> return (\o -> o{ optPdfEngine = unpack <$> x })     "pdf-engine-opts" ->@@ -725,6 +775,8 @@     , optFrom                  = Nothing     , optTo                    = Nothing     , optTableOfContents       = False+    , optListOfFigures         = False+    , optListOfTables          = False     , optShiftHeadingLevelBy   = 0     , optTemplate              = Nothing     , optVariables             = mempty@@ -733,14 +785,15 @@     , optOutputFile            = Nothing     , optInputFiles            = Nothing     , optNumberSections        = False-    , optNumberOffset          = [0,0,0,0,0,0]+    , optNumberOffset          = []     , optSectionDivs           = False     , optIncremental           = False     , optSelfContained         = False     , optEmbedResources        = False+    , optLinkImages            = False     , optHtmlQTags             = False-    , optHighlightStyle        = Just "pygments"     , optSyntaxDefinitions     = []+    , optSyntaxHighlighting    = DefaultHighlightingString     , optTopLevelDivision      = TopLevelDefault     , optHTMLMathMethod        = PlainMath     , optAbbreviations         = Nothing@@ -761,6 +814,8 @@     , optFailIfWarnings        = False     , optReferenceLinks        = False     , optReferenceLocation     = EndOfDocument+    , optFigureCaptionPosition = CaptionBelow+    , optTableCaptionPosition  = CaptionAbove     , optDpi                   = 96     , optWrap                  = WrapAuto     , optColumns               = 72@@ -770,7 +825,6 @@     , optIndentedCodeClasses   = []     , optDataDir               = Nothing     , optCiteMethod            = Citeproc-    , optListings              = False     , optPdfEngine             = Nothing     , optPdfEngineOpts         = []     , optSlideLevel            = Nothing@@ -796,6 +850,7 @@     , optBibliography          = []     , optCitationAbbreviations = Nothing     , optSandbox               = False+    , optTypstInputs           = []     }  yamlToMeta :: Value -> Parser Meta@@ -817,11 +872,19 @@   setVerbosity $ optVerbosity opt   modify $ \defsState -> defsState{ curDefaults = Just file }   inp <- readFileStrict file-  case decodeEither' (B8.unlines . takeWhile (/= "...") . B8.lines $ inp) of-      Right f -> f opt-      Left err'  -> throwError $-         PandocParseError-             $ T.pack $ Data.Yaml.prettyPrintParseException err'+  let isJSON = B8.take 1 (B8.dropWhile isSpace inp) == "{"+  if isJSON+     then+       case eitherDecodeStrict inp of+         Right f -> f opt+         Left err' -> throwError $ PandocParseError $ T.pack $+            "Error parsing " <> file <> ":\n" <> err'+     else+       case decodeEither' (B8.unlines . takeWhile (/= "...") . B8.lines $ inp) of+           Right f -> f opt+           Left err'  -> throwError $ PandocParseError $ T.pack $+                  "Error parsing " <> file <> ":\n" <>+                  Data.Yaml.prettyPrintParseException err'  fullDefaultsPath :: (PandocMonad m, MonadIO m)                  => Maybe FilePath
src/Text/Pandoc/App/OutputSettings.hs view
@@ -2,11 +2,12 @@ {-# LANGUAGE FlexibleContexts    #-} {-# LANGUAGE LambdaCase          #-} {-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE PatternSynonyms     #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TupleSections       #-} {- |    Module      : Text.Pandoc.App-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley@edu>@@ -18,17 +19,18 @@ module Text.Pandoc.App.OutputSettings   ( OutputSettings (..)   , optToOutputSettings+  , sandbox'   ) where import qualified Data.Map as M import qualified Data.Text as T import Text.DocTemplates (toVal, Context(..), Val(..)) import qualified Control.Exception as E import Control.Monad-import Control.Monad.Except (throwError)+import Control.Monad.Except (throwError, catchError) import Control.Monad.Trans import Data.Char (toLower) import Data.List (find)-import Data.Maybe (fromMaybe)+import Data.Maybe (catMaybes, fromMaybe) import Skylighting (defaultSyntaxMap) import Skylighting.Parser (addSyntaxDefinition, parseSyntaxDefinition) import System.Directory (getCurrentDirectory)@@ -37,6 +39,7 @@ import System.IO (stdout) import Text.Pandoc.Chunks (PathTemplate(..)) import Text.Pandoc+import Text.Pandoc.Filter (Filter(CiteprocFilter)) import Text.Pandoc.App.Opt (Opt (..)) import Text.Pandoc.App.CommandLineOptions (engines) import Text.Pandoc.Format (FlavoredFormat (..), applyExtensionsDiff,@@ -82,32 +85,24 @@                         _ -> pure Nothing          liftIO $ pdfWriterAndProg outflavor (optPdfEngine opts)        else case optTo opts of-              Just f -> (, Nothing) <$> parseFlavoredFormat f+              Just f -> (, optPdfEngine opts) <$> parseFlavoredFormat f               Nothing                | outputFile == "-" ->-                   return (defaultOutputFlavor, Nothing)+                   return (defaultOutputFlavor, optPdfEngine opts)                | otherwise -> case formatFromFilePaths [outputFile] of                    Nothing -> do                      report $ CouldNotDeduceFormat                        [T.pack $ takeExtension outputFile] defaultOutput-                     return (defaultOutputFlavor,Nothing)-                   Just f  -> return (f, Nothing)+                     return (defaultOutputFlavor, optPdfEngine opts)+                   Just f  -> return (f, optPdfEngine opts)    when (format == "asciidoctor") $ do     report $ Deprecated "asciidoctor" "use asciidoc instead"    let makeSandboxed pureWriter =-          let files = maybe id (:) (optReferenceDoc opts) .-                      maybe id (:) (optEpubMetadata opts) .-                      maybe id (:) (optEpubCoverImage opts) .-                      maybe id (:) (optCSL opts) .-                      maybe id (:) (optCitationAbbreviations opts) $-                      optEpubFonts opts ++-                      optBibliography opts-           in  case pureWriter of-                 TextWriter w -> TextWriter $ \o d -> sandbox files (w o d)-                 ByteStringWriter w ->-                   ByteStringWriter $ \o d -> sandbox files (w o d)+        case pureWriter of+             TextWriter w -> TextWriter $ \o d -> sandbox' opts (w o d)+             ByteStringWriter w -> ByteStringWriter $ \o d -> sandbox' opts (w o d)    let standalone = optStandalone opts || isBinaryFormat format || pdfOutput   let templateOrThrow = \case@@ -118,15 +113,17 @@           _ | not standalone -> return Nothing           Nothing -> Just <$> getDefault           Just tp -> do-            -- strip off extensions-            let tp' = case takeExtension tp of-                        "" -> tp <.> T.unpack format-                        _  -> tp-            getTemplate tp'-              >>= runWithPartials . compileTemplate tp'-              >>= fmap Just . templateOrThrow+            let getAndCompile fp =+                   getTemplate fp >>= runWithPartials . compileTemplate fp >>=+                      fmap Just . templateOrThrow+            catchError+              (getAndCompile tp)+              (\e ->+                  if null (takeExtension tp)+                     then getAndCompile (tp <.> T.unpack format)+                     else throwError e) -  (writer, writerExts, mtemplate) <-+  (writer, writerExts', mtemplate) <-     if "lua" `T.isSuffixOf` format     then do       let path = T.unpack format@@ -140,7 +137,7 @@       templ <- processCustomTemplate $                case customTemplate components of                  Nothing -> throwError $ PandocNoTemplateError format-                 Just t -> (runWithDefaultPartials $ compileTemplate path t) >>=+                 Just t -> runWithDefaultPartials (compileTemplate path t) >>=                            templateOrThrow       return (w, wexts, templ)     else@@ -155,6 +152,10 @@         tmpl <- processCustomTemplate (compileDefaultTemplate format)         return (w, wexts, tmpl) +  -- see #10662:+  let writerExts = if CiteprocFilter `elem` optFilters opts+                      then disableExtension Ext_citations writerExts'+                      else writerExts'    let addSyntaxMap existingmap f = do         res <- liftIO (parseSyntaxDefinition f)@@ -165,8 +166,11 @@   syntaxMap <- foldM addSyntaxMap defaultSyntaxMap                      (optSyntaxDefinitions opts) -  hlStyle <- traverse (lookupHighlightingStyle . T.unpack) $-               optHighlightStyle opts+  hlStyle <- case optSyntaxHighlighting opts of+    NoHighlightingString        -> pure NoHighlighting+    DefaultHighlightingString   -> pure DefaultHighlighting+    IdiomaticHighlightingString -> pure IdiomaticHighlighting+    style       -> Skylighting <$> lookupHighlightingStyle (T.unpack style)    let setListVariableM _ [] ctx = return ctx       setListVariableM k vs ctx = do@@ -197,6 +201,8 @@     >>=     setVariableM "pandoc-version" pandocVersionText     >>=+    maybe return (setVariableM "pdf-engine" . T.pack) maybePdfProg+    >>=     setFilesVariableM "include-before" (optIncludeBeforeBody opts)     >>=     setFilesVariableM "include-after" (optIncludeAfterBody opts)@@ -224,11 +230,13 @@                       setVariableM "dzslides-core" dzcore vars                   else return vars) -  let writerOpts = def {-          writerTemplate         = mtemplate+  let writerOpts = WriterOptions+        { writerTemplate         = mtemplate         , writerVariables        = variables         , writerTabStop          = optTabStop opts         , writerTableOfContents  = optTableOfContents opts+        , writerListOfFigures    = optListOfFigures opts+        , writerListOfTables     = optListOfTables opts         , writerHTMLMathMethod   = optHTMLMathMethod opts         , writerIncremental      = optIncremental opts         , writerCiteMethod       = optCiteMethod opts@@ -238,6 +246,8 @@         , writerExtensions       = writerExts         , writerReferenceLinks   = optReferenceLinks opts         , writerReferenceLocation = optReferenceLocation opts+        , writerFigureCaptionPosition = optFigureCaptionPosition opts+        , writerTableCaptionPosition = optTableCaptionPosition opts         , writerDpi              = optDpi opts         , writerWrapText         = optWrap opts         , writerColumns          = optColumns opts@@ -245,9 +255,8 @@         , writerIdentifierPrefix = optIdentifierPrefix opts         , writerHtmlQTags        = optHtmlQTags opts         , writerTopLevelDivision = optTopLevelDivision opts-        , writerListings         = optListings opts         , writerSlideLevel       = optSlideLevel opts-        , writerHighlightStyle   = hlStyle+        , writerHighlightMethod  = hlStyle         , writerSetextHeaders    = optSetextHeaders opts         , writerListTables       = optListTables opts         , writerEpubSubdirectory = T.pack $ optEpubSubdirectory opts@@ -262,6 +271,7 @@         , writerReferenceDoc     = optReferenceDoc opts         , writerSyntaxMap        = syntaxMap         , writerPreferAscii      = optAscii opts+        , writerLinkImages       = optLinkImages opts         }   return $ OutputSettings     { outputFormat = format@@ -317,3 +327,17 @@ isBinaryFormat :: T.Text -> Bool isBinaryFormat s =   s `elem` ["odt","docx","epub2","epub3","epub","pptx","pdf","chunkedhtml"]++-- Like 'sandbox', but computes the list of files to preserve from+-- 'Opt'.+sandbox' :: (PandocMonad m, MonadIO m) => Opt -> PandocPure a -> m a+sandbox' opts = sandbox sandboxedFiles+ where+   sandboxedFiles = catMaybes [ optReferenceDoc opts+                              , optEpubMetadata opts+                              , optEpubCoverImage opts+                              , optCSL opts+                              , optCitationAbbreviations opts+                              ] +++                    optEpubFonts opts +++                    optBibliography opts
src/Text/Pandoc/Asciify.hs view
@@ -1,6 +1,6 @@ {- |    Module      : Text.Pandoc.Asciify-   Copyright   : Copyright (C) 2013-2023 John MacFarlane+   Copyright   : Copyright (C) 2013-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>
src/Text/Pandoc/CSS.hs view
@@ -1,6 +1,6 @@ {- | Module      : Text.Pandoc.CSS-Copyright   : © 2006-2023 John MacFarlane <jgm@berkeley.edu>,+Copyright   : © 2006-2024 John MacFarlane <jgm@berkeley.edu>,                 2015-2016 Mauro Bieg,                 2015      Ophir Lifshitz <hangfromthefloor@gmail.com> License     : GNU GPL, version 2 or above
src/Text/Pandoc/CSV.hs view
@@ -1,6 +1,6 @@ {- |    Module      : Text.Pandoc.CSV-   Copyright   : Copyright (C) 2017-2023 John MacFarlane <jgm@berkeley.edu>+   Copyright   : Copyright (C) 2017-2024 John MacFarlane <jgm@berkeley.edu>    License     : GNU GPL, version 2 or above    Maintainer  : John MacFarlane <jgm@berkeley.edu>    Stability   : alpha
+ src/Text/Pandoc/Char.hs view
@@ -0,0 +1,59 @@+{- |+   Module      : Text.Pandoc.Char+   Copyright   : Copyright (C) 2024 John MacFarlane+   License     : GNU GPL, version 2 or above++   Maintainer  : John MacFarlane <jgm@berkeley.edu>+   Stability   : alpha+   Portability : portable++Character functions not defined in Data.Char.+-}+module Text.Pandoc.Char ( isCJK )+where++-- | Returns True if character is CJK. Matches anything in:+--+-- * CJK Unified Ideographs Basic Block: U+4E00 - U+9FFF+-- * CJK Unified Ideographs Extension A: U+3400 - U+4DBF+-- * CJK Unified Ideographs Extension B: U+20000 - U+2A6DF+-- * CJK Unified Ideographs Extension C: U+2A700 - U+2B73F+-- * CJK Unified Ideographs Extension D: U+2B740 - U+2B81F+-- * CJK Compatibility Ideographs: U+F900 - U+FAFF+-- * CJK Compatibility Ideographs Supplement: U+2F800 - U+2FA1F+isCJK :: Char -> Bool+isCJK c =+  c >= '\x4e00' &&+  (    (c >= '\x2e80' && c <= '\x2eff') -- CJK Radicals Supplement+    || (c >= '\x2f00' && c <= '\x2fdf') -- Kangxi Radicals+    || (c >= '\x2ff0' && c <= '\x2fff') -- Ideographic Description Characters+    || (c >= '\x3000' && c <= '\x303f') -- JK Symbols and Punctuation+    || (c >= '\x3040' && c <= '\x309f') -- Hiragana+    || (c >= '\x30a0' && c <= '\x30ff') -- Katakana+    || (c >= '\x3100' && c <= '\x312f') -- Bopomofo+    || (c >= '\x3130' && c <= '\x318f') -- Kanbun+    || (c >= '\x3190' && c <= '\x319f') -- Kanbun+    || (c >= '\x31c0' && c <= '\x31ef') -- CJK Strokes+    || (c >= '\x31f0' && c <= '\x31ff') -- Katakana Phonetic Extensions+    || (c >= '\x3200' && c <= '\x32ff') -- Enclosed CJK Letters & Months+    || (c >= '\x3300' && c <= '\x33ff') -- CJK Compatibility+    || (c >= '\x3400' && c <= '\x4dbf') -- CJK Unified Ideographs Extension A+    || (c >= '\x4e00' && c <= '\x9fff') -- CJK Unified Ideographs+    || (c >= '\xa000' && c <= '\xa48f') -- Yi Syllables+    || (c >= '\xa490' && c <= '\xa4cf') -- Yi Radicals+    || (c >= '\xf900' && c <= '\xfaff') -- CJK Compatibility Ideographs+    || (c >= '\xfe10' && c <= '\xfe1f') -- Vertical forms+    || (c >= '\xfe30' && c <= '\xfe4f') -- CJK Compatibility Forms+    || (c >= '\xFE50' && c <= '\xFE6F') -- Small Form Variants+    || (c >= '\xFF00' && c <= '\xFFEE') -- Halfwidth and Fullwidth Forms+    || (c >= '\x1B000' && c <= '\x1B0FF') -- Kana Supplement+    || (c >= '\x1B100' && c <= '\x1B12F') -- Kana Extended-A+    || (c >= '\x1B130' && c <= '\x1B16F') -- Small Kana Extension+    || (c >= '\x20000' && c <= '\x2A6DF') -- CJK Unified Ideographs Extension B+    || (c >= '\x2A700' && c <= '\x2B73F') -- CJK Unified Ideographs Extension C+    || (c >= '\x2B740' && c <= '\x2B81F') -- CJK Unified Ideographs Extension D+    || (c >= '\x2B820' && c <= '\x2CEAF') -- CJK Unified Ideographs Extension E+    || (c >= '\x2CEB0' && c <= '\x2EBEF') -- CJK Unified Ideographs Extension F+    || (c >= '\x2F800' && c <= '\x2FA1F') -- CJK Compatibility Ideographs Supp+    || (c >= '\x30000' && c <= '\x3134F') -- CJK Unified Ideographs Exten+  )
src/Text/Pandoc/Chunks.hs view
@@ -7,7 +7,7 @@ {-# LANGUAGE DeriveGeneric #-} {- |    Module      : Text.Pandoc.Chunks-   Copyright   : Copyright (C) 2022-2023 John MacFarlane+   Copyright   : Copyright (C) 2022-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -99,7 +99,7 @@ addUp [] = []  addNext :: [Chunk] -> [Chunk]-addNext cs = zipWith go cs (map Just (tail cs) ++ [Nothing])+addNext cs = zipWith go cs (map Just (drop 1 cs) ++ [Nothing])  where   go c nxt = c{ chunkNext = nxt } 
src/Text/Pandoc/Citeproc.hs view
@@ -30,7 +30,7 @@ import Text.Pandoc.Extensions (pandocExtensions) import Text.Pandoc.Logging (LogMessage(..)) import Text.Pandoc.Options (ReaderOptions(..))-import Text.Pandoc.Shared (stringify, tshow)+import Text.Pandoc.Shared (stringify, tshow, makeSections) import Data.Containers.ListUtils (nubOrd) import Text.Pandoc.Walk (query, walk, walkM) import Control.Applicative ((<|>))@@ -295,10 +295,24 @@              -> M.Map Text ItemId              -> Pandoc              -> [Citeproc.Citation Inlines]-getCitations locale otherIdsMap = Foldable.toList . query getCitation+getCitations locale otherIdsMap (Pandoc meta blocks) =+  Foldable.toList (query getCitation meta <>+                   foldMap handleBlock (makeSections False Nothing blocks))  where+  handleBlock :: Block -> Seq.Seq (Citeproc.Citation Inlines)+  handleBlock b@(Div (_,cls,_) _)+    | "section" `elem` cls+    , "reset-citation-positions" `elem` cls =+      case Seq.viewl (query getCitation b) of+        x Seq.:< xs -> addResetTo x Seq.<| xs+        Seq.EmptyL -> mempty+  handleBlock b = query getCitation b+  addResetTo citation = citation{ Citeproc.citationResetPosition = True }   getCitation (Cite cs _fallback) = Seq.singleton $     Citeproc.Citation { Citeproc.citationId = Nothing+                      , Citeproc.citationResetPosition = False+                      , Citeproc.citationPrefix = Nothing+                      , Citeproc.citationSuffix = Nothing                       , Citeproc.citationNoteNumber =                           case cs of                             []    -> Nothing@@ -318,7 +332,7 @@  where   locmap = toLocatorMap locale   go c =-    let (mblocinfo, suffix) = parseLocator locmap (citationSuffix c)+    let (mblocinfo, suffix) = parseLocator locmap (Pandoc.citationSuffix c)         cit = CitationItem                { citationItemId = fromMaybe                    (ItemId $ Pandoc.citationId c)@@ -326,7 +340,7 @@                , citationItemLabel = locatorLabel <$> mblocinfo                , citationItemLocator = locatorLoc <$> mblocinfo                , citationItemType = NormalCite-               , citationItemPrefix = case citationPrefix c of+               , citationItemPrefix = case Pandoc.citationPrefix c of                                         [] -> Nothing                                         ils -> Just $ B.fromList ils <>                                                       B.space@@ -382,12 +396,12 @@             _ -> Nothing  isNote :: Inline -> Bool-isNote (Cite _ [Note _]) = True- -- the following allows citation styles that are "in-text" but use superscript- -- references to be treated as if they are "notes" for the purposes of moving- -- the citations after trailing punctuation (see <https://github.com/jgm/pandoc-citeproc/issues/382>):-isNote (Cite _ [Superscript _]) = True-isNote _                 = False+isNote (Note _) = True+-- the following allows citation styles that are "in-text" but use superscript+-- references to be treated as if they are "notes" for the purposes of moving+-- the citations after trailing punctuation (see <https://github.com/jgm/pandoc-citeproc/issues/382>):+isNote (Superscript _) = True+isNote _ = False  isSpacy :: Inline -> Bool isSpacy Space     = True@@ -405,34 +419,35 @@ mvPunct moveNotes locale (x : xs)   | isSpacy x = x : mvPunct moveNotes locale xs -- 'x [^1],' -> 'x,[^1]'-mvPunct moveNotes locale (q : s : x : ys)+mvPunct moveNotes locale (q : s : x@(Cite _ [il]) : ys)   | isSpacy s-  , isNote x-  = let spunct = T.takeWhile isPunctuation $ stringify ys+  , isNote il+  = let spunct = T.takeWhile isPunct $ stringify ys     in  if moveNotes            then if T.null spunct                    then q : x : mvPunct moveNotes locale ys                    else movePunctInsideQuotes locale                         [q , Str spunct , x] ++ mvPunct moveNotes locale                         (B.toList-                          (dropTextWhile isPunctuation (B.fromList ys)))+                          (dropTextWhile isPunct (B.fromList ys)))            else q : x : mvPunct moveNotes locale ys -- 'x[^1],' -> 'x,[^1]'-mvPunct moveNotes locale (Cite cs ils : ys)-   | not (null ils)-   , isNote (last ils)+mvPunct moveNotes locale (Cite cs ils@(_:_) : ys)+   | isNote (last ils)    , startWithPunct ys    , moveNotes    = let s = stringify ys-         spunct = T.takeWhile isPunctuation s+         spunct = T.takeWhile isPunct s      in  Cite cs (movePunctInsideQuotes locale $                     init ils                     ++ [Str spunct | not (endWithPunct False (init ils))]                     ++ [last ils]) :          mvPunct moveNotes locale-           (B.toList (dropTextWhile isPunctuation (B.fromList ys)))-mvPunct moveNotes locale (s : x : ys) | isSpacy s, isNote x =-  x : mvPunct moveNotes locale ys+           (B.toList (dropTextWhile isPunct (B.fromList ys)))+mvPunct moveNotes locale (s : x@(Cite _ [il]) : ys)+  | isSpacy s+  , isNote il+  = x : mvPunct moveNotes locale ys mvPunct moveNotes locale (s : x@(Cite _ (Superscript _ : _)) : ys)   | isSpacy s = x : mvPunct moveNotes locale ys mvPunct moveNotes locale (Cite cs ils : Str "." : ys)@@ -441,13 +456,18 @@ mvPunct moveNotes locale (x:xs) = x : mvPunct moveNotes locale xs mvPunct _ _ [] = [] +-- We don't treat an em-dash or en-dash as punctuation here, because we don't+-- want notes and quotes to move around them.+isPunct :: Char -> Bool+isPunct c = isPunctuation c && c /= '\x2014' && c /= '\x2013'+ endWithPunct :: Bool -> [Inline] -> Bool endWithPunct _ [] = False endWithPunct onlyFinal xs@(_:_) =   case reverse (T.unpack $ stringify xs) of        []                       -> True        -- covers .), .", etc.:-       (d:c:_) | isPunctuation d+       (d:c:_) | isPunct d                  && not onlyFinal                  && isEndPunct c -> True        (c:_) | isEndPunct c      -> True@@ -477,7 +497,10 @@  -- if document contains a Div with id="refs", insert -- references as its contents.  Otherwise, insert references--- at the end of the document in a Div with id="refs"+-- at the end of the document in a Div with id="refs" or+-- id=".*__refs" (where .* stands for any string -- this is+-- because --file-scope will add such a prefix based on the filename,+-- see #11072.) insertRefs :: [(Text,Text)] -> [Text] -> [Block] -> Pandoc -> Pandoc insertRefs _ _ [] d = d insertRefs refkvs refclasses refs (Pandoc meta bs) =@@ -502,12 +525,13 @@    refDiv = Div ("refs", refclasses, refkvs) refs    addUnNumbered cs = "unnumbered" : [c | c <- cs, c /= "unnumbered"]    go :: Block -> State Bool Block-   go (Div ("refs",cs,kvs) xs) = do-     put True-     -- refHeader isn't used if you have an explicit references div-     let cs' = nubOrd $ cs ++ refclasses-     let kvs' = nubOrd $ kvs ++ refkvs-     return $ Div ("refs",cs',kvs') (xs ++ refs)+   go (Div (ident,cs,kvs) xs)+     | ident == "refs" || "__refs" `T.isSuffixOf` ident = do+       put True+       -- refHeader isn't used if you have an explicit references div+       let cs' = nubOrd $ cs ++ refclasses+       let kvs' = nubOrd $ kvs ++ refkvs+       return $ Div (ident,cs',kvs') (xs ++ refs)    go x = return x  refTitle :: Meta -> Maybe [Inline]@@ -568,7 +592,8 @@       = Cite (c:cs) (addCommas (needsPeriod zs) ils) :         addParens zs     | otherwise-      = Cite (c:cs) (concatMap noteInParens ils) : addParens zs+      = Cite (c:cs) (dropWhile (== Space) (concatMap noteInParens ils))+         : addParens zs   addParens (x:xs) = x : addParens xs    removeNotes (Span ("",["csl-note"],[]) ils) = Span ("",[],[]) ils
src/Text/Pandoc/Citeproc/BibTeX.hs view
@@ -52,11 +52,13 @@ import           Data.Char              (isAlphaNum, isDigit, isLetter,                                          isUpper, toLower, toUpper,                                          isLower, isPunctuation, isSpace)-import           Data.List              (foldl', intercalate, intersperse)+import           Data.List              (intercalate, intersperse)+import qualified Data.List as L import           Safe                   (readMay) import           Text.Printf            (printf) import           Text.DocLayout         (literal, hsep, nest, hang, Doc(..),                                          braces, ($$), cr)+ data Variant = Bibtex | Biblatex   deriving (Show, Eq, Ord) @@ -116,7 +118,7 @@       "manuscript"        -> "unpublished"       "graphic"           | variant == Biblatex -> "artwork"       "song"              | variant == Biblatex -> "music"-      "legal_case"        | variant == Biblatex -> "jurisdictionN"+      "legal_case"        | variant == Biblatex -> "jurisdiction"       "legislation"       | variant == Biblatex -> "legislation"       "treaty"            | variant == Biblatex -> "legal"       "personal_communication" | variant == Biblatex -> "letter"@@ -186,6 +188,7 @@            , "annote"            , "url" -- not officially supported, but supported by                    -- some styles (#8287)+           , "doi"            ]    valToInlines (TextVal t) = B.text t@@ -206,7 +209,7 @@    renderName name =     case nameLiteral name of-      Just t  -> B.text t+      Just t  -> B.spanWith ("",[],[]) $ B.text t       Nothing -> spacedMaybes                   [ nameNonDroppingParticle name                   , nameFamily name@@ -394,7 +397,8 @@                   <|> return Nothing     modify $ \s -> s{ untitlecase = untitlecase s &&                                       case hyphenation of-                                        Just x -> "en-" `T.isPrefixOf` x+                                        Just x ->+                                          "en-" `T.isPrefixOf` x || x == "en"                                         _ -> True }  @@ -473,12 +477,12 @@     subtitle' <- (guard isPeriodical >> getTitle "issuesubtitle")                   <|> (guard hasMaintitle >>                        guard (not isChapterlike) >>-                       getTitle "mainsubtitle")+                       getTitle "mainsubtitle" <|> return mempty)                   <|> getTitle "subtitle"                   <|> return mempty     titleaddon' <- (guard hasMaintitle >>                      guard (not isChapterlike) >>-                     getTitle "maintitleaddon")+                     getTitle "maintitleaddon" <|> return mempty)                     <|> getTitle "titleaddon"                     <|> return mempty @@ -819,7 +823,7 @@ bibComment = do   cistring "comment"   spaces'-  void inBraces <|> bibSkip <|> return ()+  void inBraces  bibPreamble :: BibParser () bibPreamble = do@@ -966,7 +970,7 @@ getPeriodicalTitle :: Text -> Bib Inlines getPeriodicalTitle f = do   ils <- getField f-  return ils+  return $ protectCase id ils  protectCase :: (Inlines -> Inlines) -> (Inlines -> Inlines) protectCase f = Walk.walk unprotect . f . Walk.walk protect@@ -1113,7 +1117,7 @@ toLiteralList _ = mzero  concatWith :: Char -> [Inlines] -> Inlines-concatWith sep = foldl' go mempty+concatWith sep = L.foldl' go mempty   where go :: Inlines -> Inlines -> Inlines         go accum s           | s == mempty = accum@@ -1206,7 +1210,7 @@              | otherwise         -> "article-journal"            "book"                -> "book"            "booklet"             -> "pamphlet"-           "bookinbook"          -> "chapter"+           "bookinbook"          -> "book"            "collection"          -> "book"            "dataset"             -> "dataset"            "electronic"          -> "webpage"
src/Text/Pandoc/Citeproc/Locator.hs view
@@ -11,7 +11,7 @@ import Text.Pandoc.Citeproc.Util (splitStrWhen) import Data.Text (Text) import qualified Data.Text as T-import Data.List (foldl')+import qualified Data.List as L import Text.Pandoc.Definition import Text.Pandoc.Parsing import Text.Pandoc.Shared (stringify)@@ -69,14 +69,48 @@   (rawlab, la, _) <- pLocatorLabelDelimited locMap   -- we only care about balancing {} and [] (because of the outer [] scope);   -- the rest can be anything-  let inner = do { t <- anyToken; return (True, stringify t) }+  let inner = do { t <- anyToken; return (True, cslJsonify t) }   gs <- many (pBalancedBraces [('{','}'), ('[',']')] inner)   _ <- pMatchChar "}" (== '}')-  let lo = T.concat $ map snd gs+  let lo = mconcat $ map snd gs   return $ LocatorInfo{ locatorLoc = lo,                         locatorLabel = la,                         locatorRaw = rawlab <> "{" <> lo <> "}" } +-- a variant of stringify that preserves formatting using CSL JSON+-- conventions+cslJsonify :: Inline -> Text+cslJsonify = go+  where goMany :: [Inline] -> T.Text+        goMany = mconcat . map go+        go :: Inline -> T.Text+        go (Str t) = t+        go Space = " "+        go SoftBreak = " "+        go LineBreak = " "+        go (Emph ils) = "<i>" <> goMany ils <> "</i>"+        go (Underline ils) = "<u>" <> goMany ils <> "</u>"+        go (Strong ils) = "<b>" <> goMany ils <> "</b>"+        go (Strikeout ils) = goMany ils+        go (Superscript ils) = "<sup>" <> goMany ils <> "</sup>"+        go (Subscript ils) = "<sub>" <> goMany ils <> "</sub>"+        go (SmallCaps ils) = "<span style=\"font-variant:small-caps;\">" <>+                              goMany ils <> "</span>"+        go (Quoted SingleQuote ils) = "'" <> goMany ils <> "'"+        go (Quoted DoubleQuote ils) = "\"" <> goMany ils <> "\""+        go (Cite _ ils) = goMany ils+        go (Code _ t) = t+        go (Math _ t) = t+        go (RawInline _ _) = ""+        go (Link _ ils _) = goMany ils+        go (Image _ ils _) = goMany ils+        go (Note _) = ""+        go (Span (_,cls@(_:_),_) ils) =+          "<span class=\"" <> T.unwords cls <> "\">" <> goMany ils <> "</span>"+        go (Span (_,[],[("style","baseline")]) ils) =+          "<span style=\"baseline\">" <> goMany ils <> "</span>"+        go (Span _ ils) = goMany ils+ pLocatorLabelDelimited :: LocatorMap -> LocatorParser (Text, Text, Bool) pLocatorLabelDelimited locMap   = pLocatorLabel' locMap (stringify <$> anyToken)@@ -162,7 +196,7 @@   where       except = notFollowedBy pBraces >> p       -- outer and inner-      surround = foldl' (\a (open, close) -> sur open close except <|> a)+      surround = L.foldl' (\a (open, close) -> sur open close except <|> a)                        except                        braces 
src/Text/Pandoc/Citeproc/Name.hs view
@@ -30,7 +30,7 @@ import qualified Data.Text              as T import           Data.List.Split        (splitWhen, wordsBy) import Data.Char (isUpper, isDigit)-import Data.List (foldl')+import qualified Data.List as L  emptyName :: Name emptyName =@@ -83,7 +83,7 @@         ag{ nameSuffix = Just $ stringify xs }       addPart ag (Space : xs) = addPart ag xs       addPart ag _ = ag-  return $ foldl' addPart emptyName commaParts+  return $ L.foldl' addPart emptyName commaParts -- First von Last -- von Last, First -- von Last, Jr ,First
src/Text/Pandoc/Citeproc/Util.hs view
@@ -48,6 +48,7 @@ toIETF "ngerman"         = "de-DE" toIETF "greek"           = "el-GR" toIETF "polutonikogreek" = "el-GR"+toIETF "polytonicgreek"  = "el-GR" toIETF "hebrew"          = "he-IL" toIETF "hungarian"       = "hu-HU" toIETF "icelandic"       = "is-IS"
src/Text/Pandoc/Class.hs view
@@ -23,7 +23,9 @@   , Translations   ) where -import Text.Pandoc.Class.CommonState (CommonState (..))+-- We export CommonState as an opaque object.  Accessors for+-- its fields are provided in Text.Pandoc.Class.PandocMonad.+import Text.Pandoc.Class.CommonState (CommonState) import Text.Pandoc.Class.PandocMonad import Text.Pandoc.Class.PandocIO import Text.Pandoc.Class.PandocPure
src/Text/Pandoc/Class/CommonState.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {- | Module      : Text.Pandoc.Class.CommonState Copyright   : Copyright (C) 2016-2020 Jesse Rosenthal, John MacFarlane@@ -23,6 +24,9 @@ import Text.Pandoc.MediaBag (MediaBag) import Text.Pandoc.Logging (LogMessage, Verbosity (WARNING)) import Text.Pandoc.Translations.Types (Translations)+#ifdef PANDOC_HTTP_SUPPORT+import Network.HTTP.Client (Manager)+#endif  -- | 'CommonState' represents state that is used by all -- instances of 'PandocMonad'.  Normally users should not@@ -50,6 +54,11 @@   , stResourcePath :: [FilePath]     -- ^ Path to search for resources like     -- included images+#ifdef PANDOC_HTTP_SUPPORT+  , stManager      :: Maybe Manager+    -- ^ Manager for HTTP client; this needs to persist across many requests+    -- for efficiency.+#endif   , stVerbosity    :: Verbosity     -- ^ Verbosity level   , stTrace        :: Bool@@ -75,6 +84,9 @@   , stInputFiles = []   , stOutputFile = Nothing   , stResourcePath = ["."]+#ifdef PANDOC_HTTP_SUPPORT+  , stManager = Nothing+#endif   , stVerbosity = WARNING   , stTrace = False   }
src/Text/Pandoc/Class/IO.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE CPP #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE OverloadedStrings #-} {- | Module      : Text.Pandoc.Class.IO@@ -37,32 +38,38 @@  import Control.Monad.Except (throwError) import Control.Monad.IO.Class (MonadIO, liftIO)-import Data.ByteString.Base64 (decodeLenient)-import Data.ByteString.Lazy (toChunks) import Data.Text (Text, pack, unpack) import Data.Time (TimeZone, UTCTime) import Data.Unique (hashUnique)+#ifdef PANDOC_HTTP_SUPPORT+import Data.ByteString.Lazy (toChunks)+import System.Environment (getEnv)+import Data.Default (def) import Network.Connection (TLSSettings(..)) import qualified Network.TLS as TLS import qualified Network.TLS.Extra as TLS+import System.X509 (getSystemCertificateStore) import Network.HTTP.Client-       (httpLbs, responseBody, responseHeaders,-        Request(port, host, requestHeaders), parseRequest, newManager)+       (httpLbs, Manager, responseBody, responseHeaders,+        Request(port, host, requestHeaders), parseUrlThrow, newManager, HttpException) import Network.HTTP.Client.Internal (addProxy) import Network.HTTP.Client.TLS (mkManagerSettings) import Network.HTTP.Types.Header ( hContentType ) import Network.Socket (withSocketsDo)+import Text.Pandoc.Class.CommonState (CommonState (..))+import Text.Pandoc.Class.PandocMonad ( getsCommonState, modifyCommonState )+import qualified Data.CaseInsensitive as CI+#endif import Network.URI (URI(..), parseURI, unEscapeString) import System.Directory (createDirectoryIfMissing)-import System.Environment (getEnv)-import System.FilePath ((</>), takeDirectory, normalise)+import System.FilePath ((</>), takeDirectory, takeFileName, normalise, takeExtension) import qualified System.FilePath.Posix as Posix import System.IO (stderr) import System.IO.Error import System.Random (StdGen)-import Text.Pandoc.Class.CommonState (CommonState (..)) import Text.Pandoc.Class.PandocMonad-       (PandocMonad, getsCommonState, getMediaBag, report)+       (PandocMonad,+        getMediaBag, report, extractURIData) import Text.Pandoc.Definition (Pandoc, Inline (Image)) import Text.Pandoc.Error (PandocError (..)) import Text.Pandoc.Logging (LogMessage (..), messageVerbosity, showLogMessage)@@ -71,9 +78,7 @@ import Text.Pandoc.Walk (walk) import qualified Control.Exception as E import qualified Data.ByteString as B-import qualified Data.ByteString.Char8 as B8 import qualified Data.ByteString.Lazy as BL-import qualified Data.CaseInsensitive as CI import qualified Data.Text as T import qualified Data.Time import qualified Data.Time.LocalTime@@ -83,8 +88,7 @@ import qualified System.FilePath.Glob import qualified System.Random import qualified Text.Pandoc.UTF8 as UTF8-import Data.Default (def)-import System.X509 (getSystemCertificateStore)+import Codec.Archive.Zip #ifndef EMBED_DATA_FILES import qualified Paths_pandoc as Paths #endif@@ -125,56 +129,69 @@ newUniqueHash :: MonadIO m => m Int newUniqueHash = hashUnique <$> liftIO Data.Unique.newUnique +#ifdef PANDOC_HTTP_SUPPORT+getManager :: (PandocMonad m, MonadIO m) => m Manager+getManager = do+  mbManager <- getsCommonState stManager+  disableCertificateValidation <- getsCommonState stNoCheckCertificate+  case mbManager of+    Just manager -> pure manager+    Nothing -> do+      manager <- liftIO $ do+        certificateStore <- getSystemCertificateStore+        let tlsSettings = TLSSettings $+               (TLS.defaultParamsClient "localhost.localdomain" "80")+                  { TLS.clientSupported = def{ TLS.supportedCiphers =+                                               TLS.ciphersuite_default+                                             , TLS.supportedExtendedMainSecret =+                                                TLS.AllowEMS }+                  , TLS.clientShared = def+                      { TLS.sharedCAStore = certificateStore+                      , TLS.sharedValidationCache =+                          if disableCertificateValidation+                             then TLS.ValidationCache+                                   (\_ _ _ -> return TLS.ValidationCachePass)+                                   (\_ _ _ -> return ())+                             else def+                      }+                  }+        let tlsManagerSettings = mkManagerSettings tlsSettings  Nothing+        newManager tlsManagerSettings+      modifyCommonState $ \st -> st{ stManager = Just manager }+      pure manager+#endif+ openURL :: (PandocMonad m, MonadIO m) => Text -> m (B.ByteString, Maybe MimeType) openURL u  | Just (URI{ uriScheme = "data:",-              uriPath = upath }) <- parseURI (T.unpack u) = do-     let (mimespec, rest) = break (== ',') $ unEscapeString upath-     let contents = UTF8.fromString $ drop 1 rest-     case break (== ';') (filter (/= ' ') mimespec) of-       (mime, ";base64") ->-         return (decodeLenient contents, Just (T.pack mime))-       (mime, _) ->-         return (contents, Just (T.pack mime))+              uriPath = upath }) <- parseURI (T.unpack u)+     = pure $ extractURIData upath+#ifdef PANDOC_HTTP_SUPPORT  | otherwise = do      let toReqHeader (n, v) = (CI.mk (UTF8.fromText n), UTF8.fromText v)      customHeaders <- map toReqHeader <$> getsCommonState stRequestHeaders-     disableCertificateValidation <- getsCommonState stNoCheckCertificate      report $ Fetching u+     manager <- getManager      res <- liftIO $ E.try $ withSocketsDo $ do        proxy <- tryIOError (getEnv "http_proxy")        let addProxy' x = case proxy of                             Left _ -> return x-                            Right pr -> parseRequest pr >>= \r ->+                            Right pr -> parseUrlThrow pr >>= \r ->                                 return (addProxy (host r) (port r) x)-       req <- parseRequest (unpack u) >>= addProxy'+       req <- parseUrlThrow (unpack u) >>= addProxy'        let req' = req{requestHeaders = customHeaders ++ requestHeaders req}-       certificateStore <- getSystemCertificateStore-       let tlsSettings = TLSSettings $-              (TLS.defaultParamsClient (show $ host req')-                                       (B8.pack $ show $ port req'))-                 { TLS.clientSupported = def{ TLS.supportedCiphers =-                                              TLS.ciphersuite_default-                                            , TLS.supportedExtendedMainSecret =-                                               TLS.AllowEMS }-                 , TLS.clientShared = def-                     { TLS.sharedCAStore = certificateStore-                     , TLS.sharedValidationCache =-                         if disableCertificateValidation-                            then TLS.ValidationCache-                                  (\_ _ _ -> return TLS.ValidationCachePass)-                                  (\_ _ _ -> return ())-                            else def-                     }-                 }-       let tlsManagerSettings = mkManagerSettings tlsSettings  Nothing-       resp <- newManager tlsManagerSettings >>= httpLbs req'+       resp <- httpLbs req' manager        return (B.concat $ toChunks $ responseBody resp,                UTF8.toText `fmap` lookup hContentType (responseHeaders resp))       case res of           Right r -> return r-          Left e  -> throwError $ PandocHttpError u e+          Left (e :: HttpException)+                  -> throwError $ PandocHttpError u (T.pack (show e))+#else+ | otherwise =+     throwError $ PandocHttpError u "pandoc was compiled without HTTP support"+#endif  -- | Read the lazy ByteString contents from a file path, raising an error on -- failure.@@ -229,16 +246,26 @@   where go l' = do UTF8.hPutStr stderr "  "                    UTF8.hPutStrLn stderr l' --- | Extract media from the mediabag into a directory.+-- | Extract media from the mediabag into a directory (or a zip archive if the+-- path supplied ends in @.zip@. extractMedia :: (PandocMonad m, MonadIO m) => FilePath -> Pandoc -> m Pandoc-extractMedia dir d = do+extractMedia path d = do   media <- getMediaBag   let items = mediaItems media+  let (dir, mbZip) = case takeExtension path of+                       ".zip" -> (takeDirectory path, Just (takeFileName path))+                       _ -> (path, Nothing)   if null items     then return d     else do-      mapM_ (writeMedia dir) items+      let archive = foldr addEntry emptyArchive items+      case mbZip of+        Just fname -> writeMedia dir+                        (fname, "application/zip", fromArchive archive)+        Nothing -> mapM_ (writeMedia dir) items       return $ walk (adjustImagePath dir media) d+ where+  addEntry (fp, _mime, content) = addEntryToArchive (toEntry fp 0 content)  -- | Write the contents of a media bag to a path. -- If the path contains URI escape sequences (percent-encoding),
src/Text/Pandoc/Class/PandocMonad.hs view
@@ -28,24 +28,30 @@   , getZonedTime   , readFileFromDirs   , report-  , setTrace+  , runSilently   , setRequestHeader   , setNoCheckCertificate   , getLog   , setVerbosity   , getVerbosity+  , setTrace+  , getTrace   , getMediaBag   , setMediaBag   , insertMedia   , setUserDataDir   , getUserDataDir   , fetchItem+  , extractURIData   , getInputFiles   , setInputFiles   , getOutputFile   , setOutputFile   , setResourcePath   , getResourcePath+  , setRequestHeaders+  , getRequestHeaders+  , getSourceURL   , readMetadataFile   , toTextM   , fillMediaBag@@ -76,8 +82,11 @@ import Text.Pandoc.MIME (MimeType, getMimeType) import Text.Pandoc.MediaBag (MediaBag, lookupMedia, MediaItem(..)) import Text.Pandoc.Shared (safeRead, makeCanonical, tshow)-import Text.Pandoc.URI (uriPathToPath)+import Text.Pandoc.URI (uriPathToPath, pBase64DataURI)+import qualified Data.Attoparsec.Text as A import Text.Pandoc.Walk (walkM)+import qualified Text.Pandoc.UTF8 as UTF8+import Data.ByteString.Base64 (decodeLenient) import Text.Parsec (ParsecT, getPosition, sourceLine, sourceName) import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as BL@@ -160,6 +169,15 @@ getVerbosity :: PandocMonad m => m Verbosity getVerbosity = getsCommonState stVerbosity +-- | Set tracing. This affects the behavior of 'trace'. If tracing+-- is not enabled, 'trace' does nothing.+setTrace :: PandocMonad m => Bool -> m ()+setTrace enabled = modifyCommonState $ \st -> st{ stTrace = enabled }++-- | Get tracing status.+getTrace :: PandocMonad m => m Bool+getTrace = getsCommonState stTrace+ -- | Get the accumulated log messages (in temporal order). getLog :: PandocMonad m => m [LogMessage] getLog = reverse <$> getsCommonState stLog@@ -175,12 +193,23 @@   when (level <= verbosity) $ logOutput msg   modifyCommonState $ \st -> st{ stLog = msg : stLog st } --- | Determine whether tracing is enabled.  This affects--- the behavior of 'trace'.  If tracing is not enabled,--- 'trace' does nothing.-setTrace :: PandocMonad m => Bool -> m ()-setTrace useTracing = modifyCommonState $ \st -> st{stTrace = useTracing}+-- | Run an action, but suppress the output of any log messages;+-- instead, all messages reported by @action@ are returned separately+-- and not added to the main log.+runSilently :: PandocMonad m => m a -> m (a, [LogMessage])+runSilently action = do+  -- get current settings+  origLog <- getsCommonState stLog+  origVerbosity <- getVerbosity+  -- reset log level and set verbosity to the minimum+  modifyCommonState (\st -> st { stVerbosity = ERROR, stLog = []})+  result <- action+  -- get log messages reported while running `action`+  newLog <- getsCommonState stLog+  modifyCommonState (\st -> st { stVerbosity = origVerbosity, stLog = origLog}) +  return (result, newLog)+ -- | Set request header to use in HTTP requests. setRequestHeader :: PandocMonad m                  => T.Text  -- ^ Header name@@ -244,6 +273,18 @@ setResourcePath :: PandocMonad m => [FilePath] -> m () setResourcePath ps = modifyCommonState $ \st -> st{stResourcePath = ps} +-- | Retrieve the request headers to add for HTTP requests.+getRequestHeaders :: PandocMonad m => m [(T.Text, T.Text)]+getRequestHeaders = getsCommonState stRequestHeaders++-- | Set the request headers to add for HTTP requests.+setRequestHeaders :: PandocMonad m => [(T.Text, T.Text)] -> m ()+setRequestHeaders hs = modifyCommonState $ \st -> st{ stRequestHeaders = hs }++-- | Get the absolute UL or directory of first source file.+getSourceURL :: PandocMonad m => m (Maybe T.Text)+getSourceURL = getsCommonState stSourceURL+ -- | Get the current UTC time. If the @SOURCE_DATE_EPOCH@ environment -- variable is set to a unix time (number of seconds since midnight -- Jan 01 1970 UTC), it is used instead of the current time, to support@@ -330,10 +371,13 @@ downloadOrRead :: PandocMonad m                => T.Text                -> m (B.ByteString, Maybe MimeType)-downloadOrRead s = do+downloadOrRead s+ | "data:" `T.isPrefixOf` s,+   Right (bs, mt) <- A.parseOnly (pBase64DataURI <* A.endOfInput) s+   = pure (bs, Just mt)+ | otherwise = do   sourceURL <- getsCommonState stSourceURL-  case (sourceURL >>= parseURIReference' .-                       ensureEscaped, ensureEscaped s) of+  case (sourceURL >>= parseURIReference' . ensureEscaped, ensureEscaped s) of     (Just u, s') -> -- try fetching from relative path at source        case parseURIReference' s' of             Just u' -> openURL $ T.pack $ show $ u' `nonStrictRelativeTo` u@@ -345,8 +389,10 @@             Nothing -> openURL s' -- will throw error     (Nothing, s') ->        case parseURI (T.unpack s') of  -- requires absolute URI-            Just u' | uriScheme u' == "file:" ->-                 readLocalFile $ uriPathToPath (T.pack $ uriPath u')+            Just URI{ uriScheme = "file:", uriPath = upath}+              -> readLocalFile $ uriPathToPath (T.pack upath)+            Just URI{ uriScheme = "data:", uriPath = upath}+              -> pure $ extractURIData upath             -- We don't want to treat C:/ as a scheme:             Just u' | length (uriScheme u') > 2 -> openURL (T.pack $ show u')             _ -> readLocalFile fp -- get from local file system@@ -362,8 +408,7 @@                           uriPath = "",                           uriQuery = "",                           uriFragment = "" }-         dropFragmentAndQuery = T.takeWhile (\c -> c /= '?' && c /= '#')-         fp = unEscapeString $ T.unpack $ dropFragmentAndQuery s+         fp = unEscapeString $ T.unpack s          mime = getMimeType $ case takeExtension fp of                      ".gz" -> dropExtension fp                      ".svgz" -> dropExtension fp ++ ".svg"@@ -372,6 +417,16 @@          convertSlash '\\' = '/'          convertSlash x    = x +-- Extract data from a data URI's path component.+extractURIData :: String -> (B.ByteString, Maybe MimeType)+extractURIData upath =+  case break (== ';') (filter (/= ' ') mimespec) of+     (mime', ";base64") -> (decodeLenient contents, Just (T.pack mime'))+     (mime', _) -> (contents, Just (T.pack mime'))+  where+    (mimespec, rest) = break (== ',') $ unEscapeString upath+    contents = UTF8.fromString $ drop 1 rest+ -- | Checks if the file path is relative to a parent directory. isRelativeToParentDir :: FilePath -> Bool isRelativeToParentDir fname =@@ -467,6 +522,11 @@               return $ Image attr lab (src, tit))           (\e ->               case e of+                PandocIOError text err -> do+                  report $ CouldNotFetchResource text . T.pack $+                            (show err ++ "\nReplacing image with description.")+                  -- emit alt text+                  return $ replacementSpan attr src tit lab                 PandocResourceNotFound _ -> do                   report $ CouldNotFetchResource src                             "replacing image with description"@@ -474,7 +534,7 @@                   return $ replacementSpan attr src tit lab                 PandocHttpError u er -> do                   report $ CouldNotFetchResource u-                            (T.pack $ show er ++ "\rReplacing image with description.")+                            (er <> "\nReplacing image with description.")                   -- emit alt text                   return $ replacementSpan attr src tit lab                 _ -> throwError e)
src/Text/Pandoc/Class/PandocPure.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE OverloadedStrings #-}@@ -49,7 +50,7 @@ import System.Directory (doesDirectoryExist, getDirectoryContents) import System.FilePath ((</>)) import System.FilePath.Glob (match, compile)-import System.Random (StdGen, split, mkStdGen)+import System.Random (StdGen, mkStdGen) import Text.Pandoc.Class.CommonState (CommonState (..)) import Text.Pandoc.Class.PandocMonad import Text.Pandoc.Error@@ -58,6 +59,15 @@ import qualified Data.Map as M import qualified Data.Text as T import qualified System.Directory as Directory (getModificationTime)++#if MIN_VERSION_random(1,3,0)+import System.Random (splitGen, SplitGen)++split :: SplitGen g => g -> (g, g)+split = splitGen+#else+import System.Random (split)+#endif  -- | The 'PureState' contains ersatz representations -- of things that would normally be obtained through IO.
src/Text/Pandoc/Class/Sandbox.hs view
@@ -1,6 +1,6 @@ {- | Module      : Text.Pandoc.Class.Sandbox-Copyright   : Copyright (C) 2021-2023 John MacFarlane+Copyright   : Copyright (C) 2021-2024 John MacFarlane License     : GNU GPL, version 2 or above  Maintainer  : John MacFarlane (<jgm@berkeley.edu>)@@ -12,7 +12,9 @@ -}  module Text.Pandoc.Class.Sandbox-  ( sandbox )+  ( sandbox+  , sandboxWithFileTree+  ) where  import Control.Monad (foldM)@@ -30,8 +32,18 @@ -- ersatz file system and be available for reading. sandbox :: (PandocMonad m, MonadIO m) => [FilePath] -> PandocPure a -> m a sandbox files action = do-  oldState <- getCommonState   tree <- liftIO $ foldM addToFileTree mempty files+  sandboxWithFileTree tree action++-- | Lift a PandocPure action into any instance of PandocMonad.+-- The main computation is done purely, but CommonState is preserved+-- continuously, and warnings are emitted after the action completes.+-- The parameter is an ersatz file system which will be available for+-- reading.+sandboxWithFileTree :: (PandocMonad m, MonadIO m)+                    => FileTree -> PandocPure a -> m a+sandboxWithFileTree tree action = do+  oldState <- getCommonState   case runPure (do putCommonState oldState                    modifyPureState $ \ps -> ps{ stFiles = tree }                    result <- action
src/Text/Pandoc/Data.hs view
@@ -5,7 +5,7 @@ #endif {- | Module      : Text.Pandoc.Data-Copyright   : Copyright (C) 2013-2023 John MacFarlane+Copyright   : Copyright (C) 2013-2024 John MacFarlane License     : GNU GPL, version 2 or above  Maintainer  : John MacFarlane <jgm@berkeley@edu>
src/Text/Pandoc/Data/BakedIn.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE TemplateHaskell #-} {- | Module      : Text.Pandoc.Data.BakedIn-Copyright   : Copyright (C) 2013-2023 John MacFarlane+Copyright   : Copyright (C) 2013-2024 John MacFarlane License     : GNU GPL, version 2 or above  Maintainer  : John MacFarlane <jgm@berkeley@edu>
src/Text/Pandoc/Error.hs view
@@ -3,7 +3,7 @@ {-# LANGUAGE OverloadedStrings  #-} {- |    Module      : Text.Pandoc.Error-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -25,7 +25,6 @@ import Data.Text (Text) import qualified Data.Text as T import GHC.Generics (Generic)-import Network.HTTP.Client (HttpException) import System.Exit (ExitCode (..), exitWith) import System.IO (stderr) import qualified Text.Pandoc.UTF8 as UTF8@@ -34,7 +33,7 @@ import Citeproc (CiteprocError, prettyCiteprocError)  data PandocError = PandocIOError Text IOError-                 | PandocHttpError Text HttpException+                 | PandocHttpError Text Text                  | PandocShouldNeverHappenError Text                  | PandocSomeError Text                  | PandocParseError Text@@ -65,16 +64,18 @@                  | PandocUnsupportedExtensionError Text Text                  | PandocCiteprocError CiteprocError                  | PandocBibliographyError Text Text+                 | PandocInputNotTextError Text                  deriving (Show, Typeable, Generic)  instance Exception PandocError+ where+   displayException = T.unpack . renderError  renderError :: PandocError -> Text renderError e =   case e of     PandocIOError _ err' -> T.pack $ displayException err'-    PandocHttpError u err' ->-      "Could not fetch " <> u <> "\n" <> tshow err'+    PandocHttpError u err' -> "Could not fetch " <> u <> "\n" <> err'     PandocShouldNeverHappenError s ->       "Something we thought was impossible happened!\n" <>       "Please report this to pandoc's developers: " <> s@@ -85,40 +86,41 @@     PandocSyntaxMapError s -> s     PandocFailOnWarningError -> "Failing because there were warnings."     PandocPDFProgramNotFoundError pdfprog ->-        pdfprog <> " not found. Please select a different --pdf-engine or install " <> pdfprog+        quote pdfprog <> " not found. Please select a different --pdf-engine or install "+        <> quote pdfprog     PandocPDFError logmsg -> "Error producing PDF.\n" <> logmsg     PandocXMLError fp logmsg -> "Invalid XML" <>-        (if T.null fp then "" else " in " <> fp) <> ":\n" <> logmsg+        (if T.null fp then "" else " in " <> quote fp) <> ":\n" <> logmsg     PandocFilterError filtername msg -> "Error running filter " <>-        filtername <> ":\n" <> msg+        quote filtername <> ":\n" <> msg     PandocLuaError msg -> "Error running Lua:\n" <> msg     PandocNoScriptingEngine -> "This version of pandoc has been compiled " <>                                "without Lua support."     PandocCouldNotFindDataFileError fn ->-        "Could not find data file " <> fn+        "Could not find data file " <> quote fn     PandocCouldNotFindMetadataFileError fn ->-        "Could not find metadata file " <> fn+        "Could not find metadata file " <> quote fn     PandocResourceNotFound fn ->-        "File " <> fn <> " not found in resource path"-    PandocTemplateError s -> "Error compiling template " <> s-    PandocNoTemplateError fp -> "No template defined in " <> fp+        "File " <> quote fn <> " not found in resource path"+    PandocTemplateError s -> "Error compiling template " <> quote s+    PandocNoTemplateError fp -> "No template defined in " <> quote fp     PandocAppError s -> s     PandocEpubSubdirectoryError s ->-      "EPUB subdirectory name '" <> s <> "' contains illegal characters"+      "EPUB subdirectory name " <> quote s <> " contains illegal characters"     PandocMacroLoop s ->       "Loop encountered in expanding macro " <> s     PandocUTF8DecodingError f offset w ->-      "UTF-8 decoding error in " <> f <> " at byte offset " <> tshow offset <>-      " (" <> T.pack (printf "%2x" w) <> ").\n" <>-      "The input must be a UTF-8 encoded text."+      "UTF-8 decoding error in " <> quote f <> " at byte offset "+       <> tshow offset <> " (" <> T.pack (printf "%2x" w) <> ").\n"+       <> "The input must be a UTF-8 encoded text."     PandocIpynbDecodingError w ->       "ipynb decoding error: " <> w     PandocUnsupportedCharsetError charset ->-      "Unsupported charset " <> charset+      "Unsupported charset " <> quote charset     PandocFormatError format s ->-      "Error parsing format " <> tshow format <> ": " <> s+      "Error parsing format " <> quote format <> ": " <> s     PandocUnknownReaderError r ->-      "Unknown input format " <> r <>+      "Unknown input format " <> quote r <>       case r of         "doc" -> "\nPandoc can convert from DOCX, but not from DOC." <>                  "\nTry using Word to save your DOC file as DOCX," <>@@ -126,29 +128,41 @@         "pdf" -> "\nPandoc can convert to PDF, but not from PDF."         _     -> ""     PandocUnknownWriterError w ->-       "Unknown output format " <> w <>+       "Unknown output format " <> quote w <>        case w of          "pdf" -> "To create a pdf using pandoc, use" <>-                  " -t latex|beamer|context|ms|html5" <>+                  " -t latex|beamer|context|ms|html5|typst" <>                  "\nand specify an output file with " <>                  ".pdf extension (-o filename.pdf)."          "doc" -> "\nPandoc can convert to DOCX, but not to DOC."          _     -> ""     PandocUnsupportedExtensionError ext f ->-      "The extension " <> ext <> " is not supported " <>-      "for " <> f+      "The extension " <> quote ext <> " is not supported " <>+      "for " <> f <> ".\nUse --list-extensions=" <> f <> " to " <>+      "list supported extensions."     PandocCiteprocError e' ->       prettyCiteprocError e'     PandocBibliographyError fp msg ->-      "Error reading bibliography file " <> fp <> ":\n" <> msg+      "Error reading bibliography file " <> quote fp <> ":\n" <> msg+    PandocInputNotTextError fp ->+      "Expected text as an input, but received binary data from " <>+      (if T.null fp+        then "stdin"+        else "file " <> quote fp) <>+      ".\nIf you intended to convert from binary format, verify that it's " <>+      "supported and use\nexplicit -f FORMAT." +quote :: Text -> Text+quote s = "'" <> s <> "'"  -- | Handle PandocError by exiting with an error message. handleError :: Either PandocError a -> IO a handleError (Right r) = return r handleError (Left e) =   case e of-    PandocIOError _ err' -> ioError err'+    PandocIOError _ err' -> do+      putStrLn $ displayException err'+      exitWith (ExitFailure 1)     _ -> err exitCode (renderError e)  where   exitCode =@@ -182,6 +196,7 @@       PandocUTF8DecodingError{} -> 92       PandocIpynbDecodingError{} -> 93       PandocUnsupportedCharsetError{} -> 94+      PandocInputNotTextError{} -> 95       PandocCouldNotFindDataFileError{} -> 97       PandocCouldNotFindMetadataFileError{} -> 98       PandocResourceNotFound{} -> 99
src/Text/Pandoc/Extensions.hs view
@@ -4,7 +4,7 @@ {-# LANGUAGE OverloadedStrings          #-} {- |    Module      : Text.Pandoc.Extensions-   Copyright   : Copyright (C) 2012-2023 John MacFarlane+   Copyright   : Copyright (C) 2012-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -59,8 +59,6 @@     | Ext_blank_before_header     -- ^ Require blank line before a header     | Ext_bracketed_spans         -- ^ Bracketed spans with attributes     | Ext_citations           -- ^ Pandoc/citeproc citations-    | Ext_compact_definition_lists  -- ^ Definition lists without space between items,-                                    --   and disallow laziness     | Ext_definition_lists    -- ^ Definition lists as in pandoc, mmd, php     | Ext_east_asian_line_breaks  -- ^ Newlines in paragraphs are ignored between                                   --   East Asian wide characters. Note: this extension@@ -86,6 +84,7 @@     | Ext_gutenberg           -- ^ Use Project Gutenberg conventions for plain     | Ext_hard_line_breaks    -- ^ All newlines become hard line breaks     | Ext_header_attributes   -- ^ Explicit header attributes {#id .class k=v}+    | Ext_table_attributes    -- ^ Explicit table attributes after caption     | Ext_ignore_line_breaks  -- ^ Newlines in paragraphs are ignored     | Ext_implicit_figures    -- ^ A paragraph with just an image is a figure     | Ext_implicit_header_references -- ^ Implicit reference links for headers@@ -122,6 +121,8 @@     | Ext_shortcut_reference_links -- ^ Shortcut reference links     | Ext_simple_tables       -- ^ Pandoc-style simple tables     | Ext_smart               -- ^ "Smart" quotes, apostrophes, ellipses, dashes+    | Ext_smart_quotes        -- ^ "Smart" quotes+    | Ext_special_strings     -- ^ Treat certain strings like special characters     | Ext_sourcepos           -- ^ Include source position attributes     | Ext_space_in_atx_header -- ^ Require space between # and header text     | Ext_spaced_reference_links -- ^ Allow space between two parts of ref link@@ -253,6 +254,7 @@   , Ext_task_lists   , Ext_auto_identifiers   , Ext_header_attributes+  , Ext_table_attributes   , Ext_link_attributes   , Ext_implicit_header_references   , Ext_line_blocks@@ -431,6 +433,7 @@   ] getDefaultExtensions "org"             = extensionsFromList                                           [Ext_citations,+                                           Ext_special_strings,                                            Ext_task_lists,                                            Ext_auto_identifiers] getDefaultExtensions "html"            = extensionsFromList@@ -471,7 +474,9 @@ getDefaultExtensions "opml"            = pandocExtensions -- affects notes getDefaultExtensions "markua"          = extensionsFromList                                           []-getDefaultExtensions "typst"           = extensionsFromList [Ext_citations]+getDefaultExtensions "typst"           = extensionsFromList [Ext_citations,+                                                             Ext_smart]+getDefaultExtensions "dokuwiki"        = extensionsFromList [Ext_smart] getDefaultExtensions _                 = extensionsFromList                                           [Ext_auto_identifiers] @@ -509,7 +514,6 @@        , Ext_mark        , Ext_mmd_link_attributes        , Ext_mmd_header_identifiers-       , Ext_compact_definition_lists        , Ext_gutenberg        , Ext_smart        , Ext_literate_haskell@@ -517,6 +521,7 @@        , Ext_rebase_relative_paths        , Ext_wikilinks_title_after_pipe        , Ext_wikilinks_title_before_pipe+       , Ext_alerts        ]   getAll "markdown_strict"   = allMarkdownExtensions   getAll "markdown_phpextra" = allMarkdownExtensions@@ -581,6 +586,8 @@     extensionsFromList     [ Ext_citations     , Ext_smart+    , Ext_smart_quotes+    , Ext_special_strings     , Ext_fancy_lists     , Ext_task_lists     ]@@ -643,7 +650,9 @@   getAll "vimwiki"         = autoIdExtensions   getAll "dokuwiki"        = autoIdExtensions <>     extensionsFromList-    [ Ext_tex_math_dollars ]+    [ Ext_tex_math_dollars+    , Ext_raw_html+    , Ext_smart ]   getAll "tikiwiki"        = autoIdExtensions   getAll "rst"             = autoIdExtensions <>     extensionsFromList@@ -653,6 +662,7 @@   getAll "mediawiki"       = autoIdExtensions <>     extensionsFromList     [ Ext_smart ]-  getAll "typst"           = extensionsFromList [Ext_citations]+  getAll "typst"           = extensionsFromList [Ext_citations, Ext_smart]   getAll "djot"            = extensionsFromList [Ext_sourcepos]+  getAll "man"             = autoIdExtensions   getAll _                 = mempty
src/Text/Pandoc/Filter.hs view
@@ -3,7 +3,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Filter-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley@edu>@@ -41,7 +41,7 @@ data Filter = LuaFilter FilePath             | JSONFilter FilePath             | CiteprocFilter -- built-in citeproc-            deriving (Show, Generic)+            deriving (Show, Generic, Eq)  instance FromJSON Filter where  parseJSON node =
src/Text/Pandoc/Filter/Environment.hs view
@@ -3,7 +3,7 @@    Copyright   : ©2020-2021 Albert Krewinkel    License     : GNU GPL, version 2 or above -   Maintainer  : Albert Krewinkel <albert@zeitkraut.de>+   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>    Stability   : alpha    Portability : portable 
src/Text/Pandoc/Filter/JSON.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Filter-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley@edu>
src/Text/Pandoc/Format.hs view
@@ -2,9 +2,9 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Format-   Copyright   : © 2022-2023 Albert Krewinkel+   Copyright   : © 2022-2024 Albert Krewinkel    License     : GPL-2.0-or-later-   Maintainer  : Albert Krewinkel <pandoc@tarleb.com>+   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>  Handling of format specifiers for input and output. -}@@ -22,7 +22,7 @@ import Control.Monad.Except (throwError) import Data.Char (toLower) import Data.Foldable (asum)-import Data.List (foldl')+import qualified Data.List as L import System.FilePath (splitExtension, takeExtension) import Text.Pandoc.Class (PandocMonad) import Text.Pandoc.Error (PandocError (..))@@ -38,6 +38,7 @@   , showExtension   , readExtension   )+import Network.URI (URI (..), parseURI) import Text.Pandoc.Parsing import qualified Data.Text as T @@ -141,7 +142,7 @@  pExtensionsDiff :: (UpdateSourcePos s Char, Stream s m Char)                 => ParsecT s u m ExtensionsDiff-pExtensionsDiff = foldl' (flip ($)) mempty <$> many extMod+pExtensionsDiff = L.foldl' (flip ($)) mempty <$> many extMod   where     extMod = do       polarity <- oneOf "-+"@@ -170,7 +171,7 @@ -- | Determines format based on file extension. formatFromFilePath :: FilePath -> Maybe FlavoredFormat formatFromFilePath x =-  case takeExtension (map toLower x) of+  case takeExtension (map toLower fpath) of     ".Rmd"      -> defFlavor "markdown"     ".adoc"     -> defFlavor "asciidoc"     ".asciidoc" -> defFlavor "asciidoc"@@ -180,6 +181,7 @@     ".ctx"      -> defFlavor "context"     ".db"       -> defFlavor "docbook"     ".dj"       -> defFlavor "djot"+    ".djvu"     -> defFlavor "djvu" -- so we get an "unknown reader" error     ".doc"      -> defFlavor "doc"  -- so we get an "unknown reader" error     ".docx"     -> defFlavor "docx"     ".dokuwiki" -> defFlavor "dokuwiki"@@ -203,10 +205,16 @@     ".ms"       -> defFlavor "ms"     ".muse"     -> defFlavor "muse"     ".native"   -> defFlavor "native"+    ".ods"      -> defFlavor "ods"  -- so we get an "unknown reader" error+    ".odp"      -> defFlavor "odp"  -- so we get an "unknown reader" error+    ".odf"      -> defFlavor "odf"  -- so we get an "unknown reader" error     ".odt"      -> defFlavor "odt"     ".opml"     -> defFlavor "opml"     ".org"      -> defFlavor "org"     ".pdf"      -> defFlavor "pdf"  -- so we get an "unknown reader" error+    ".pl"       -> defFlavor "pod"+    ".pm"       -> defFlavor "pod"+    ".pod"      -> defFlavor "pod"     ".pptx"     -> defFlavor "pptx"     ".ris"      -> defFlavor "ris"     ".roff"     -> defFlavor "ms"@@ -221,11 +229,14 @@     ".text"     -> defFlavor "markdown"     ".textile"  -> defFlavor "textile"     ".tsv"      -> defFlavor "tsv"-    ".typ"      -> defFlavor "typst"     ".txt"      -> defFlavor "markdown"     ".typ"      -> defFlavor "typst"     ".wiki"     -> defFlavor "mediawiki"     ".xhtml"    -> defFlavor "html"+    ".xls"      -> defFlavor "xls"   -- so we get an "unknown reader" error+    ".xlsx"     -> defFlavor "xlsx"  -- so we get an "unknown reader" error+    ".xml"      -> defFlavor "xml"+    ".zip"      -> defFlavor "zip"  -- so we get an "unknown reader" error     ['.',y]     | y `elem` ['1'..'9'] -> defFlavor "man"     _           -> Nothing  where@@ -233,3 +244,8 @@   withExtension Nothing _ = Nothing   withExtension (Just (FlavoredFormat f ed)) ext = Just $     FlavoredFormat f (ed <> ExtensionsDiff (extensionsFromList [ext]) mempty)+  fpath = case parseURI x of+            Nothing -> x+            Just URI{ uriPath = "" } -> "index.html"+            Just URI{ uriPath = "/" } -> "index.html"+            Just URI{ uriPath = up } -> up
src/Text/Pandoc/Highlighting.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Highlighting-   Copyright   : Copyright (C) 2008-2023 John MacFarlane+   Copyright   : Copyright (C) 2008-2025 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -29,7 +29,13 @@                                 , formatConTeXtInline                                 , formatConTeXtBlock                                 , styleToConTeXt+                                , formatANSI+                                -- ** Typst+                                , formatTypstBlock+                                , formatTypstInline+                                , styleToTypst                                 -- * Styles+                                , defaultStyle                                 , pygments                                 , espresso                                 , zenburn@@ -43,17 +49,56 @@                                 , fromListingsLanguage                                 , toListingsLanguage                                 ) where-import Control.Monad+import Control.Monad ( msum ) import qualified Data.Map as M import Data.Maybe (fromMaybe) import qualified Data.Text as T import Skylighting-import Text.Pandoc.Definition+    ( SyntaxMap,+      breezeDark,+      espresso,+      haddock,+      kate,+      monochrome,+      pygments,+      tango,+      zenburn,+      formatHtml4Block,+      formatHtmlBlock,+      formatHtmlInline,+      styleToCss,+      formatConTeXtBlock,+      formatConTeXtInline,+      styleToConTeXt,+      formatLaTeXBlock,+      formatLaTeXInline,+      styleToLaTeX,+      formatTypstBlock,+      formatTypstInline,+      styleToTypst,+      formatANSI,+      Style,+      FormatOptions(containerClasses, startNumber, lineAnchors,+                    numberLines, lineIdPrefix, codeClasses),+      SourceLine,+      lookupSyntax,+      syntaxesByExtension,+      parseTheme,+      tokenize,+      defaultFormatOpts,+      TokenizerConfig(traceOutput, TokenizerConfig, syntaxMap),+      Syntax(sShortname, sName),+      TokenType(NormalTok) )+import Text.Pandoc.Definition ( Attr ) import Text.Pandoc.Class (PandocMonad, readFileLazy) import Text.Pandoc.Error (PandocError(..)) import Control.Monad.Except (throwError) import System.FilePath (takeExtension) import Text.Pandoc.Shared (safeRead)++-- | The default highlighting style used by pandoc (pygments).+defaultStyle :: Style+defaultStyle = pygments  highlightingStyles :: [(T.Text, Style)] highlightingStyles =
src/Text/Pandoc/Image.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings, ScopedTypeVariables, CPP #-} {- | Module      : Text.Pandoc.Image-Copyright   : Copyright (C) 2020-2023 John MacFarlane+Copyright   : Copyright (C) 2020-2024 John MacFarlane License     : GNU GPL, version 2 or above  Maintainer  : John MacFarlane <jgm@berkeley.edu>
src/Text/Pandoc/ImageSize.hs view
@@ -3,7 +3,7 @@ {-# OPTIONS_GHC -fno-warn-type-defaults #-} {- | Module      : Text.Pandoc.ImageSize-Copyright   : Copyright (C) 2011-2023 John MacFarlane+Copyright   : Copyright (C) 2011-2024 John MacFarlane License     : GNU GPL, version 2 or above  Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -13,6 +13,7 @@ Functions for determining the size of a PNG, JPEG, or GIF image. -} module Text.Pandoc.ImageSize ( ImageType(..)+                             , ImageSize(..)                              , imageType                              , imageSize                              , sizeInPixels@@ -36,6 +37,9 @@ import qualified Data.ByteString.Char8 as B import qualified Data.ByteString.Lazy as BL import Data.Binary.Get+import Data.Bits ((.&.), shiftR, shiftL)+import Data.Word (bitReverse32, Word32)+import Data.Maybe (isJust, fromJust) import Data.Char (isDigit) import Control.Monad import Text.Pandoc.Shared (safeRead)@@ -49,15 +53,16 @@ import qualified Data.Text.Lazy as TL import qualified Data.Text.Encoding as TE import Control.Applicative+import qualified Data.Attoparsec.ByteString as AW import qualified Data.Attoparsec.ByteString.Char8 as A import qualified Codec.Picture.Metadata as Metadata-import qualified Codec.Picture.Metadata.Exif as Exif import Codec.Picture (decodeImageWithMetadata)+import Codec.Compression.Zlib (decompress)+-- import Debug.Trace  -- quick and dirty functions to get image sizes--- algorithms borrowed from wwwis.pl -data ImageType = Png | Gif | Jpeg | Svg | Pdf | Eps | Emf | Tiff+data ImageType = Png | Gif | Jpeg | Svg | Pdf | Eps | Emf | Tiff | Webp | Avif                  deriving Show data Direction = Width | Height instance Show Direction where@@ -68,6 +73,8 @@                | Centimeter Double                | Millimeter Double                | Inch Double+               | Point Double+               | Pica Double                | Percent Double                | Em Double                deriving Eq@@ -77,6 +84,8 @@   show (Centimeter a) = T.unpack (showFl a) ++ "cm"   show (Millimeter a) = T.unpack (showFl a) ++ "mm"   show (Inch a)       = T.unpack (showFl a) ++ "in"+  show (Point a)      = T.unpack (showFl a) ++ "pt"+  show (Pica a)       = T.unpack (showFl a) ++ "pc"   show (Percent a)    = show a              ++ "%"   show (Em a)         = T.unpack (showFl a) ++ "em" @@ -109,8 +118,11 @@                      "\x47\x49\x46\x38" -> return Gif                      "\x49\x49\x2a\x00" -> return Tiff                      "\x4D\x4D\x00\x2a" -> return Tiff-                     "\xff\xd8\xff\xe0" -> return Jpeg  -- JFIF-                     "\xff\xd8\xff\xe1" -> return Jpeg  -- Exif+                     "\xff\xd8\xff\xbd" -> return Jpeg  -- JPEG without application segment -- see p.32 in https://www.w3.org/Graphics/JPEG/itu-t81.pdf (and https://gist.github.com/leommoore/f9e57ba2aa4bf197ebc5?permalink_comment_id=3863054#gistcomment-3863054)+                     _ | B.take 3 img == "\xff\xd8\xff"+                          && (let byte4 = B.take 1 (B.drop 3 img)+                              in byte4 >= "\xe0" && byte4 <= "\xef")  -- JPEG with application segment+                                        -> return Jpeg                      "%PDF"             -> return Pdf                      "<svg"             -> return Svg                      "<?xm"@@ -124,6 +136,10 @@                                         -> return Emf                      "\xEF\xBB\xBF<" -- BOM before svg                           -> imageType (B.drop 3 img)+                     "RIFF"+                       | B.take 4 (B.drop 8 img) == "WEBP"+                                        -> return Webp+                     _ | B.take 4 (B.drop 4 img) == "ftyp" -> return Avif                      _ -> mzero  findSvgTag :: ByteString -> Bool@@ -140,6 +156,8 @@        Just Eps  -> mbToEither "could not determine EPS size" $ epsSize img        Just Pdf  -> mbToEither "could not determine PDF size" $ pdfSize img        Just Emf  -> mbToEither "could not determine EMF size" $ emfSize img+       Just Webp -> mbToEither "could not determine WebP size" $ webpSize opts img+       Just Avif -> mbToEither "could not determine AVIF size" $ avifSize opts img        Nothing   -> Left "could not determine image type"   where mbToEither msg Nothing  = Left msg         mbToEither _   (Just x) = Right x@@ -193,6 +211,8 @@     (Centimeter a) -> a * 0.3937007874     (Millimeter a) -> a * 0.03937007874     (Inch a)       -> a+    (Point a)      -> (a / 72)+    (Pica a)       -> (a / 6)     (Percent _)    -> 0     (Em a)         -> a * (11/64) @@ -200,11 +220,7 @@ inPixel opts dim =   case dim of     (Pixel a)      -> a-    (Centimeter a) -> floor $ dpi * a * 0.3937007874 :: Integer-    (Millimeter a) -> floor $ dpi * a * 0.03937007874 :: Integer-    (Inch a)       -> floor $ dpi * a :: Integer-    (Percent _)    -> 0-    (Em a)         -> floor $ dpi * a * (11/64) :: Integer+    _              -> floor (dpi * inInch opts dim)   where     dpi = fromIntegral $ writerDpi opts @@ -234,6 +250,8 @@         Centimeter x -> Centimeter (factor * x)         Millimeter x -> Millimeter (factor * x)         Inch x       -> Inch (factor * x)+        Point x      -> Point (factor * x)+        Pica x       -> Pica (factor * x)         Percent x    -> Percent (factor * x)         Em x         -> Em (factor * x) @@ -257,8 +275,8 @@     toDim a "%"    = Just $ Percent a     toDim a "px"   = Just $ Pixel (floor a::Integer)     toDim a ""     = Just $ Pixel (floor a::Integer)-    toDim a "pt"   = Just $ Inch (a / 72)-    toDim a "pc"   = Just $ Inch (a / 6)+    toDim a "pt"   = Just $ Point a+    toDim a "pc"   = Just $ Pica a     toDim a "em"   = Just $ Em a     toDim _ _      = Nothing @@ -286,10 +304,10 @@     Right sz -> Just sz  pPdfSize :: A.Parser ImageSize-pPdfSize = do-  A.skipWhile (/='/')-  A.char8 '/'-  (do A.string "MediaBox"+pPdfSize =+  (A.takeWhile1 (/= '/') *> pPdfSize)+  <|>+  (do A.string "/MediaBox"       A.skipSpace       A.char8 '['       A.skipSpace@@ -306,7 +324,27 @@             , pxY  = y2 - y1             , dpiX = 72             , dpiY = 72 }-   ) <|> pPdfSize+  )+  <|> -- if we encounter a compressed object stream, uncompress it (#10902)+  (do A.string "/Type"+      A.skipSpace+      A.string "/ObjStm"+      _ <- A.manyTill pLine (A.string "stream" *> pEol)+      stream <- BL.pack <$> A.manyTill+                        (AW.satisfy (const True))+                        (pEol *> A.string "endstream" *> pEol)+      let contents = BL.toStrict (decompress stream)+      case A.parseOnly pPdfSize contents of+        Left _ -> pPdfSize+        Right is -> pure is)+  <|>+  (A.char '/' *> pPdfSize)+ where+   iseol '\r' = True+   iseol '\n' = True+   iseol _ = False+   pEol = A.satisfy iseol *> A.skipMany (A.satisfy iseol)+   pLine = A.takeWhile (not . iseol) <* pEol  getSize :: ByteString -> Either T.Text ImageSize getSize img =@@ -314,17 +352,9 @@     Left e -> Left (T.pack e)     Right (_, meta) -> do       pxx <- maybe (Left "Could not determine width") Right $-                   -- first look for exif image width, then width-                   (Metadata.lookup-                     (Metadata.Exif (Exif.TagUnknown 0xA002)) meta >>=-                       exifDataToWord) <|>                    Metadata.lookup Metadata.Width meta       pxy <- maybe (Left "Could not determine height") Right $-                  -- first look for exif image height, then height-                  (Metadata.lookup-                     (Metadata.Exif (Exif.TagUnknown 0xA003)) meta >>=-                       exifDataToWord) <|>-                  Metadata.lookup Metadata.Height meta+                   Metadata.lookup Metadata.Height meta       dpix <- maybe (Right 72) Right $ Metadata.lookup Metadata.DpiX meta       dpiy <- maybe (Right 72) Right $ Metadata.lookup Metadata.DpiY meta       return $ ImageSize@@ -332,12 +362,7 @@                 , pxY = fromIntegral pxy                 , dpiX = fromIntegral dpix                 , dpiY = fromIntegral dpiy }- where-  exifDataToWord (Exif.ExifLong x) = Just $ fromIntegral x-  exifDataToWord (Exif.ExifShort x) = Just $ fromIntegral x-  exifDataToWord _ = Nothing - svgSize :: WriterOptions -> ByteString -> Maybe ImageSize svgSize opts img = do   doc <- either (const mzero) return $ parseXMLElement@@ -349,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 {@@ -389,3 +416,240 @@     case parseheader . BL.fromStrict $ img of       Left _ -> Nothing       Right (_, _, size) -> Just size++-- See https://developers.google.com/speed/webp/docs/riff_container+-- and RFC 6386+pWebpSize :: AW.Parser ImageSize+pWebpSize = do+  AW.string "RIFF"+  AW.take 4+  AW.string "WEBP"+  (w, h) <- lossy <|> lossless <|> extended+  return $ def+    { pxX = w+    , pxY = h+    }+  where+    bitsToMaybe = either (const Nothing) (\((_, _, s)) -> Just s)+    decode d = bitsToMaybe . d . BL.fromStrict+    lossySize = runGetOrFail $ do+      word <- getWord16le+      return $ word .&. 0x3FFF+    lossy = do+      AW.string "VP8 "+      AW.take 4 -- length in bytes of VP8 Lossy stream size+      keyFrame <-  AW.anyWord8+      guard $ keyFrame .&. 1 == 0+      AW.take 2 -- remaining bytes of frame header+      AW.word8 0x9d  -- VP8 keyframe magic+      AW.word8 0x01+      AW.word8 0x2a+      width16 <- AW.take 2+      height16 <- AW.take 2+      let w = toInteger <$> decode lossySize width16+          h = toInteger <$> decode lossySize height16+      guard $ isJust w && isJust h+      return (fromJust w, fromJust h)+    losslessSizes = runGetOrFail $ do+      bitReverse32 <$> getWord32le+    losslessSize word = 1 + (word .&. 0x3FFF)+    lossless = do+      AW.string "VP8L"+      AW.take 4 -- length in bytes of VP8 Lossless chunk size+      AW.word8 0x2f  -- webp lossless stream magic+      sizes <- AW.take 4+      let mbword = decode losslessSizes sizes+      guard $ isJust mbword+      let word = fromJust mbword+      let w = toInteger $ losslessSize word+          h = toInteger $ losslessSize (word `shiftR` 14)+      return (w, h)+    extendedSize = runGetOrFail $ do+      low <- toInteger <$> getWord16le+      high <- toInteger <$> getWord8+      return $ 1 + (high `shiftL` 16) + (low)+    extended = do+      AW.string "VP8X"+      AW.take 8  -- VP8X chunk length, flags and reserved area+      width24 <- AW.take 3+      height24 <- AW.take 3+      let w = decode extendedSize width24+          h = decode extendedSize height24+      guard $ isJust w && isJust h+      return (fromJust w, fromJust h)++webpSize :: WriterOptions -> ByteString -> Maybe ImageSize+webpSize opts img =+  case AW.parseOnly pWebpSize img of+    Left _   -> Nothing+    Right sz -> Just sz { dpiX = fromIntegral $ writerDpi opts, dpiY = fromIntegral $ writerDpi opts}++avifSize :: WriterOptions -> ByteString -> Maybe ImageSize+avifSize _opts img =+  case runGetOrFail (verifyFtyp >> findAvifDimensions) (BL.fromStrict img) of+    Left (_, _, _err) -> Nothing+    Right (_, _, (width, height)) ->+      Just $ ImageSize { pxX = fromIntegral width+                       , pxY = fromIntegral height+                       , dpiX = 72+                       , dpiY = 72 }++---- AVIF parsing:++verifyFtyp :: Get ()+verifyFtyp = do+  ftypSize <- getWord32be+  when (ftypSize < 16) $ fail "Invalid ftyp size"++  ftyp <- getByteString 4+  unless (ftyp == "ftyp") $ fail "ftyp signature not found"++  brand <- getByteString 4+  unless (brand == "avif" || brand == "avis") $ fail "Not an AVIF file"++  -- Skip minor version and compatible brands+  -- (we've read 12 bytes: size+type+brand)+  let remaining_ftyp = fromIntegral ftypSize - 12+  when (remaining_ftyp > 0) $ skip remaining_ftyp++findAvifDimensions :: Get (Word32, Word32)+findAvifDimensions = searchAvifBoxes []++searchAvifBoxes :: [B.ByteString] -> Get (Word32, Word32)+searchAvifBoxes path = do+  isempty <- isEmpty+  if isempty+    then fail $ "No dimensions found. Searched: " ++ show (reverse path)+    else do+      boxSize <- getWord32be+      boxType <- getByteString 4++      let contentSize = fromIntegral boxSize - 8+      let newPath = boxType : path++      -- If it's a container box, search inside it+      if isContainerBox boxType+        then searchInsideBox contentSize newPath+        else do+          -- Try to parse dimensions from this box+          result <- tryParseDimensions boxType contentSize+          case result of+            Just dims -> return dims+            Nothing -> do+              -- Skip this box and continue+              when (contentSize > 0 && contentSize < 10000000) $+                skip contentSize+              searchAvifBoxes path++tryParseDimensions :: B.ByteString -> Int -> Get (Maybe (Word32, Word32))+tryParseDimensions boxType size = do+  pos <- bytesRead+  result <- case boxType of+    "ispe" -> parseIspeBox+    "tkhd" -> parseTkhdBox+    "stsd" -> parseStsdBox+    "av01" -> parseAv01Box+    _ -> return Nothing++  -- Reset position if we didn't find dimensions+  case result of+    Nothing -> do+      newPos <- bytesRead+      let consumed = fromIntegral (newPos - pos)+      case size - consumed of+        n | n > 0 -> skip n+        _ -> return ()+    Just _ -> return ()++  return result++parseIspeBox :: Get (Maybe (Word32, Word32))+parseIspeBox = do+  skip 4  -- version/flags+  width <- getWord32be+  height <- getWord32be+  return $ Just (width, height)++parseTkhdBox :: Get (Maybe (Word32, Word32))+parseTkhdBox = do+  version <- getWord8+  skip 3  -- flags++  -- Skip to width/height based on version+  let skipBytes = if version == 1 then 76 else 64+  skip skipBytes++  width <- getWord32be+  height <- getWord32be+  -- Convert from 16.16 fixed point+  return $ Just (width `shiftR` 16, height `shiftR` 16)++parseStsdBox :: Get (Maybe (Word32, Word32))+parseStsdBox = do+  skip 8  -- version, flags, entry count+  findAv01Entry++findAv01Entry :: Get (Maybe (Word32, Word32))+findAv01Entry = do+  entrySize <- getWord32be+  codec <- getByteString 4++  if codec == "av01"+    then do+      skip 6  -- reserved+      skip 2  -- data reference index+      skip 16 -- pre-defined + reserved+      width <- getWord16be+      height <- getWord16be+      return $ Just (fromIntegral width, fromIntegral height)+    else do+      let skipSize = fromIntegral entrySize - 8+      when (skipSize > 0) $ skip skipSize+      findAv01Entry++parseAv01Box :: Get (Maybe (Word32, Word32))+parseAv01Box = do+  skip 6   -- reserved+  skip 2   -- data reference index+  skip 16  -- predefined/reserved+  width <- getWord16be+  height <- getWord16be+  return $ Just (fromIntegral width, fromIntegral height)++searchInsideBox :: Int -> [B.ByteString] -> Get (Word32, Word32)+searchInsideBox size path = do+  -- For meta boxes, skip version/flags+  let isMeta = case path of+                 "meta":_ -> True+                 _ -> False+  when isMeta $ skip 4++  let searchSize = if isMeta then size - 4 else size+  searchAvifBoxesInRange searchSize path++searchAvifBoxesInRange :: Int -> [B.ByteString] -> Get (Word32, Word32)+searchAvifBoxesInRange remaining' path+  | remaining' < 8 = searchAvifBoxes path+  | otherwise = do+      boxSize <- getWord32be+      boxType <- getByteString 4++      let contentSize = fromIntegral boxSize - 8+      let newPath = boxType : path++      when (contentSize < 0 || fromIntegral boxSize > remaining') $ do+        fail $ "Malformed box at path: " ++ show (reverse newPath)++      if isContainerBox boxType+        then searchInsideBox contentSize newPath+        else do+          result <- tryParseDimensions boxType contentSize+          case result of+            Just dims -> return dims+            Nothing -> do+              -- Don't skip here - tryParseDimensions already handled it+              searchAvifBoxesInRange (remaining' - fromIntegral boxSize) path++isContainerBox :: B.ByteString -> Bool+isContainerBox boxType = boxType `elem`+  ["moov", "trak", "mdia", "minf", "stbl", "meta", "dinf", "ipco", "iprp"]
src/Text/Pandoc/Logging.hs view
@@ -3,7 +3,7 @@ {-# LANGUAGE OverloadedStrings  #-} {- |    Module      : Text.Pandoc.Logging-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -79,6 +79,7 @@   | Fetching Text   | Extracting Text   | LoadedResource FilePath FilePath+  | ScriptingInfo Text (Maybe SourcePos)   | ScriptingWarning Text (Maybe SourcePos)   | NoTitleElement Text   | NoLangSpecified@@ -101,12 +102,17 @@   | NotUTF8Encoded FilePath   | MakePDFInfo Text Text   | MakePDFWarning Text+  | UnclosedDiv SourcePos SourcePos+  | UnsupportedCodePage Int+  | YamlWarning SourcePos Text+  | UnsupportedPdfStandard Text   deriving (Show, Eq, Data, Ord, Typeable, Generic)  instance ToJSON LogMessage where   toJSON x = object $     "verbosity" .= toJSON (messageVerbosity x) :     "type" .= toJSON (show $ toConstr x) :+    "pretty" .= toJSON (showLogMessage x) :     case x of       SkippedContent s pos ->            ["contents" .= s,@@ -203,6 +209,14 @@       LoadedResource orig found ->            ["for"  .= orig            ,"from" .= found]+      ScriptingInfo msg mbpos ->+           ["message" .= msg] <>+           case mbpos of+             Nothing  -> []+             Just pos -> ["source" .= sourceName pos+                         ,"line" .= toJSON (sourceLine pos)+                         ,"column" .= toJSON (sourceColumn pos)+                         ]       ScriptingWarning msg mbpos ->            ["message" .= msg] <>            case mbpos of@@ -260,6 +274,26 @@            ,"contents" .= contents]       MakePDFWarning message ->            ["message" .= message]+      UnclosedDiv openpos closepos ->+           ["openpos" .= object+             [ "source" .= sourceName openpos,+               "line" .= toJSON (sourceLine openpos),+               "column" .= toJSON (sourceColumn openpos)]+           ,"closepos" .= object+             [ "source" .= sourceName closepos,+               "line" .= toJSON (sourceLine closepos),+               "column" .= toJSON (sourceColumn closepos)]+           ]+      UnsupportedCodePage cpg ->+           ["codepage" .= cpg]+      YamlWarning pos msg ->+           [ "source" .= sourceName pos+           , "line" .= toJSON (sourceLine pos)+           , "column" .= toJSON (sourceColumn pos)+           , "message" .= msg+           ]+      UnsupportedPdfStandard s ->+           ["contents" .= s]  showPos :: SourcePos -> Text showPos pos = Text.pack $ sn ++ "line " ++@@ -338,14 +372,16 @@          "Extracting " <> fp <> "..."        LoadedResource orig found ->          "Loaded " <> Text.pack orig <> " from " <> Text.pack found+       ScriptingInfo s mbpos ->+         "Scripting info" <>+         maybe "" (\pos -> " at " <> showPos pos) mbpos  <> ": " <> s        ScriptingWarning s mbpos ->          "Scripting warning" <>          maybe "" (\pos -> " at " <> showPos pos) mbpos  <> ": " <> s        NoTitleElement fallback ->          "This document format requires a nonempty <title> element.\n" <>          "Defaulting to '" <> fallback <> "' as the title.\n" <>-         "To specify a title, use 'title' in metadata or " <>-         "--metadata title=\"...\"."+         "To specify a title, use --variable pagetitle=\"...\"."        NoLangSpecified ->          "No value for 'lang' was specified in the metadata.\n" <>          "It is recommended that lang be specified for this format."@@ -400,6 +436,13 @@              then mempty              else "\n" <> contents        MakePDFWarning message -> "[makePDF] " <> message+       UnclosedDiv openpos closepos -> "Div at " <> showPos openpos <>+          " unclosed at " <> showPos closepos <> ", closing implicitly."+       UnsupportedCodePage cpg -> "Unsupported code page " <> tshow cpg <>+          ". Text will likely be garbled."+       YamlWarning pos m -> "YAML warning (" <> showPos pos <> "): " <> m+       UnsupportedPdfStandard s ->+         "PDF standard '" <> s <> "' is not supported by LaTeX and will be ignored."  messageVerbosity :: LogMessage -> Verbosity messageVerbosity msg =@@ -421,7 +464,7 @@        ParsingUnescaped{}            -> INFO        InlineNotRendered{}           -> INFO        BlockNotRendered{}            -> INFO-       DocxParserWarning{}           -> INFO+       DocxParserWarning{}           -> WARNING        PowerpointTemplateWarning{}   -> WARNING        IgnoredIOError{}              -> WARNING        CouldNotFetchResource{}       -> WARNING@@ -433,8 +476,9 @@        Fetching{}                    -> INFO        Extracting{}                  -> INFO        LoadedResource{}              -> INFO+       ScriptingInfo{}               -> INFO        ScriptingWarning{}            -> WARNING-       NoTitleElement{}              -> WARNING+       NoTitleElement{}              -> INFO        NoLangSpecified               -> INFO        InvalidLang{}                 -> WARNING        CouldNotHighlight{}           -> WARNING@@ -455,3 +499,7 @@        NotUTF8Encoded{}              -> WARNING        MakePDFInfo{}                 -> INFO        MakePDFWarning{}              -> WARNING+       UnclosedDiv{}                 -> WARNING+       UnsupportedCodePage{}         -> WARNING+       YamlWarning{}                 -> WARNING+       UnsupportedPdfStandard{}      -> WARNING
src/Text/Pandoc/MIME.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.MIME-   Copyright   : Copyright (C) 2011-2023 John MacFarlane+   Copyright   : Copyright (C) 2011-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -45,20 +45,21 @@ getMimeTypeDef = fromMaybe "application/octet-stream" . getMimeType  extensionFromMimeType :: MimeType -> Maybe T.Text--- few special cases, where there are multiple options:-extensionFromMimeType "text/plain" = Just "txt"-extensionFromMimeType "video/quicktime" = Just "mov"-extensionFromMimeType "video/mpeg" = Just "mpeg"-extensionFromMimeType "video/dv" = Just "dv"-extensionFromMimeType "image/vnd.djvu" = Just "djvu"-extensionFromMimeType "image/tiff" = Just "tiff"-extensionFromMimeType "image/jpeg" = Just "jpg"-extensionFromMimeType "application/xml" = Just "xml"-extensionFromMimeType "application/ogg" = Just "ogg"-extensionFromMimeType "image/svg+xml" = Just "svg" -- avoid svgz extensionFromMimeType mimetype =-  M.lookup (T.takeWhile (/=';') mimetype) reverseMimeTypes   -- note:  we just look up the basic mime type, dropping the content-encoding etc.+  case T.takeWhile (/=';') mimetype of+    -- handle a few special cases, where there are multiple options:+    "text/plain" -> Just "txt"+    "video/quicktime" -> Just "mov"+    "video/mpeg" -> Just "mpeg"+    "video/dv" -> Just "dv"+    "image/vnd.djvu" -> Just "djvu"+    "image/tiff" -> Just "tiff"+    "image/jpeg" -> Just "jpg"+    "application/xml" -> Just "xml"+    "application/ogg" -> Just "ogg"+    "image/svg+xml" -> Just "svg" -- avoid svgz+    mt -> M.lookup mt reverseMimeTypes  -- | Determine general media category for file path, e.g. --@@ -88,10 +89,12 @@            [("%","application/x-trash")            ,("323","text/h323")            ,("alc","chemical/x-alchemy")+           ,("apng","image/apng")            ,("art","image/x-jg")            ,("asn","chemical/x-ncbi-asn1")            ,("aso","chemical/x-ncbi-asn1-binary")            ,("atomsrv","application/atomserv+xml")+           ,("avif", "image/avif")            ,("b","chemical/x-molconn-Z")            ,("bak","application/x-trash")            ,("bat","application/x-msdos-program")@@ -185,6 +188,7 @@            ,("istr","chemical/x-isostar")            ,("jdx","chemical/x-jcamp-dx")            ,("jfif","image/jpeg")+           ,("jxl","image/jxl")            ,("jmz","application/x-jmol")            ,("key","application/pgp-keys")            ,("kil","application/x-killustrator")
src/Text/Pandoc/MediaBag.hs view
@@ -4,7 +4,7 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} {- |    Module      : Text.Pandoc.MediaBag-   Copyright   : Copyright (C) 2014-2015, 2017-2023 John MacFarlane+   Copyright   : Copyright (C) 2014-2015, 2017-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -23,20 +23,19 @@                      mediaDirectory,                      mediaItems                      ) where+import Crypto.Hash (hashWith, SHA1(SHA1)) import qualified Data.ByteString.Lazy as BL import Data.Data (Data) import qualified Data.Map as M import Data.Maybe (fromMaybe, isNothing) import Data.Typeable (Typeable)-import Network.URI (unEscapeString) import System.FilePath import qualified System.FilePath.Posix as Posix import qualified System.FilePath.Windows as Windows import Text.Pandoc.MIME (MimeType, getMimeTypeDef, extensionFromMimeType) import Data.Text (Text) import qualified Data.Text as T-import Data.Digest.Pure.SHA (sha1, showDigest)-import Network.URI (URI (..), parseURI, isURI)+import Network.URI (URI (..), isURI, parseURI, unEscapeString) import Data.List (isInfixOf)  data MediaItem =@@ -59,6 +58,8 @@ -- | We represent paths with /, in normalized form.  Percent-encoding -- is not resolved. canonicalize :: FilePath -> Text+-- avoid an expensive call to isURI for data URIs:+canonicalize fp@('d':'a':'t':'a':':':_) = T.pack fp canonicalize fp   | isURI fp = T.pack fp   | otherwise = T.replace "\\" "/" . T.pack . normalise $ fp@@ -78,29 +79,39 @@             -> BL.ByteString  -- ^ contents of resource             -> MediaBag             -> MediaBag-insertMedia fp mbMime contents (MediaBag mediamap) =-  MediaBag (M.insert fp' mediaItem mediamap)-  where mediaItem = MediaItem{ mediaPath = newpath-                             , mediaContents = contents-                             , mediaMimeType = mt }-        fp' = canonicalize fp-        fp'' = unEscapeString $ T.unpack fp'-        uri = parseURI fp-        newpath = if Posix.isRelative fp''-                       && Windows.isRelative fp''-                       && isNothing uri-                       && not (".." `isInfixOf` fp'')-                       && '%' `notElem` fp''-                     then fp''-                     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 | '%' `notElem` e -> '.':e-                _ -> maybe "" (\x -> '.':T.unpack x) $ extensionFromMimeType mt+insertMedia fp mbMime contents (MediaBag mediamap)+ | 'd':'a':'t':'a':':':_ <- fp+ , Just mt' <- mbMime+   = MediaBag (M.insert fp'+               MediaItem{ mediaPath = hashpath+                        , mediaContents = contents+                        , mediaMimeType = mt' } mediamap)+ | otherwise = MediaBag (M.insert fp' mediaItem mediamap)+ where+  mediaItem = MediaItem{ mediaPath = newpath+                       , mediaContents = contents+                       , mediaMimeType = mt }+  fp' = canonicalize fp+  fp'' = unEscapeString $ T.unpack fp'+  uri = parseURI fp+  hashpath = show (hashWith SHA1 (BL.toStrict contents)) <> ext+  newpath = if Posix.isRelative fp''+                 && Windows.isRelative fp''+                 && isNothing uri+                 && not (".." `isInfixOf` fp'')+                 && '%' `notElem` fp''+               then fp''+               else hashpath+  fallback = case takeExtension fp'' of+                  ".gz" -> getMimeTypeDef $ dropExtension fp''+                  _     -> getMimeTypeDef fp''+  mt = fromMaybe fallback mbMime+  path = maybe fp'' (unEscapeString . uriPath) uri+  ext = case extensionFromMimeType mt of+             Just e -> '.':T.unpack e+             Nothing -> case takeExtension path of+                             '.':e | '%' `notElem` e -> '.':e+                             _ -> ""  -- | Lookup a media item in a 'MediaBag', returning mime type and contents. lookupMedia :: FilePath
src/Text/Pandoc/Options.hs view
@@ -3,10 +3,11 @@ {-# LANGUAGE DeriveGeneric      #-} {-# LANGUAGE LambdaCase         #-} {-# LANGUAGE OverloadedStrings  #-}+{-# LANGUAGE PatternSynonyms    #-} {-# LANGUAGE TemplateHaskell    #-} {- |    Module      : Text.Pandoc.Options-   Copyright   : Copyright (C) 2012-2023 John MacFarlane+   Copyright   : Copyright (C) 2012-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -21,6 +22,10 @@                            , HTMLMathMethod (..)                            , CiteMethod (..)                            , ObfuscationMethod (..)+                           , HighlightMethod (..)+                           , pattern NoHighlightingString+                           , pattern DefaultHighlightingString+                           , pattern IdiomaticHighlightingString                            , HTMLSlideVariant (..)                            , EPUBVersion (..)                            , WrapOption (..)@@ -28,9 +33,11 @@                            , WriterOptions (..)                            , TrackChanges (..)                            , ReferenceLocation (..)+                           , CaptionPosition (..)                            , def                            , isEnabled                            , defaultMathJaxURL+                           , defaultWebTeXURL                            , defaultKaTeXURL                            ) where import Control.Applicative ((<|>))@@ -40,13 +47,14 @@ import Data.Char (toLower) import Data.Text (Text) import qualified Data.Set as Set+import qualified Data.Text as T import Data.Typeable (Typeable) import GHC.Generics (Generic) import Skylighting (SyntaxMap, defaultSyntaxMap) import Text.DocTemplates (Context(..), Template) import Text.Pandoc.Extensions import Text.Pandoc.Chunks (PathTemplate)-import Text.Pandoc.Highlighting (Style, pygments)+import Text.Pandoc.Highlighting (Style) import Text.Pandoc.UTF8 (toStringLazy) import Data.Aeson.TH (deriveJSON) import Data.Aeson@@ -66,6 +74,7 @@        , readerTrackChanges          :: TrackChanges -- ^ Track changes setting for docx        , readerStripComments         :: Bool -- ^ Strip HTML comments instead of parsing as raw HTML                                              -- (only implemented in commonmark)+       , readerTypstInputs           :: [(Text, Text)] -- ^ parameters specified using --typst-input } deriving (Show, Read, Data, Typeable, Generic)  instance HasSyntaxExtensions ReaderOptions where@@ -82,6 +91,7 @@                , readerDefaultImageExtension = ""                , readerTrackChanges          = AcceptChanges                , readerStripComments         = False+               , readerTypstInputs           = []                }  defaultAbbrevs :: Set.Set Text@@ -113,7 +123,8 @@         mburl <- m .:? "url"         case method :: Text of           "plain" -> return PlainMath-          "webtex" -> return $ WebTeX $ fromMaybe "" mburl+          "webtex" -> return $ WebTeX $+                         fromMaybe defaultWebTeXURL mburl           "gladtex" -> return GladTeX           "mathml" -> return MathML           "mathjax" -> return $ MathJax $@@ -123,7 +134,7 @@           _ -> fail $ "Unknown HTML math method " ++ show method) node        <|> (case node of                String "plain" -> return PlainMath-               String "webtex" -> return $ WebTeX ""+               String "webtex" -> return $ WebTeX defaultWebTeXURL                String "gladtex" -> return GladTeX                String "mathml" -> return MathML                String "mathjax" -> return $ MathJax defaultMathJaxURL@@ -183,6 +194,43 @@    toJSON ReferenceObfuscation = String "references"    toJSON JavascriptObfuscation = String "javascript" +-- | Method to provide code highlighting.+data HighlightMethod =+    Skylighting Style+  | IdiomaticHighlighting+  | DefaultHighlighting+  | NoHighlighting+  deriving (Show, Read, Eq, Data, Typeable, Generic)++-- | String representation of the idiomatic highlighting option.+pattern IdiomaticHighlightingString :: Text+pattern IdiomaticHighlightingString = "idiomatic"++-- | String representation of the default highlighting option.+pattern DefaultHighlightingString :: Text+pattern DefaultHighlightingString = "default"++-- | String representation of the no highlighting option+pattern NoHighlightingString :: Text+pattern NoHighlightingString = "none"++instance ToJSON HighlightMethod where+  toJSON NoHighlighting        = String NoHighlightingString+  toJSON IdiomaticHighlighting = String IdiomaticHighlightingString+  toJSON DefaultHighlighting   = String DefaultHighlightingString+  toJSON (Skylighting style)   = toJSON style++instance FromJSON HighlightMethod where+  parseJSON = \case+    String NoHighlightingString        -> pure NoHighlighting+    String IdiomaticHighlightingString -> pure IdiomaticHighlighting+    String DefaultHighlightingString   -> pure DefaultHighlighting+    String x           -> fail $ "Unknown highlighting method " <> T.unpack x+    Bool True          -> pure DefaultHighlighting+    Bool False         -> pure NoHighlighting+    Null               -> pure NoHighlighting+    v                  -> Skylighting <$> parseJSON v+ -- | Varieties of HTML slide shows. data HTMLSlideVariant = S5Slides                       | SlidySlides@@ -286,12 +334,30 @@    toJSON EndOfSection = "end-of-section"    toJSON EndOfDocument = "end-of-document" +-- | Positions for figure and table captions+data CaptionPosition = CaptionAbove -- ^ above figure or table+                     | CaptionBelow -- ^ below figure or table+                     deriving (Show, Read, Eq, Data, Typeable, Generic)++instance FromJSON CaptionPosition where+  parseJSON v =+    case v of+      String "above" -> return CaptionAbove+      String "below" -> return CaptionBelow+      _ -> fail $ "Unknown caption position " <> toStringLazy (encode v)++instance ToJSON CaptionPosition where+   toJSON CaptionAbove = "above"+   toJSON CaptionBelow = "below"+ -- | Options for writers data WriterOptions = WriterOptions   { writerTemplate          :: Maybe (Template Text) -- ^ Template to use   , writerVariables         :: Context Text -- ^ Variables to set in template   , writerTabStop           :: Int    -- ^ Tabstop for conversion btw spaces and tabs   , writerTableOfContents   :: Bool   -- ^ Include table of contents+  , writerListOfFigures     :: Bool   -- ^ Include list of figures+  , writerListOfTables      :: Bool   -- ^ Include list of tables   , writerIncremental       :: Bool   -- ^ True if lists should be incremental   , writerHTMLMathMethod    :: HTMLMathMethod  -- ^ How to print math in HTML   , writerNumberSections    :: Bool   -- ^ Number sections in LaTeX@@ -309,9 +375,7 @@   , writerHtmlQTags         :: Bool       -- ^ Use @<q>@ tags for quotes in HTML   , writerSlideLevel        :: Maybe Int  -- ^ Force header level of slides   , writerTopLevelDivision  :: TopLevelDivision -- ^ Type of top-level divisions-  , writerListings          :: Bool       -- ^ Use listings package for code-  , writerHighlightStyle    :: Maybe Style  -- ^ Style to use for highlighting-                                           -- (Nothing = no highlighting)+  , writerHighlightMethod   :: HighlightMethod  -- ^ Style to use for highlighting   , writerSetextHeaders     :: Bool       -- ^ Use setext headers for levels 1-2 in markdown   , writerListTables        :: Bool       -- ^ Use list tables for RST tables   , writerEpubSubdirectory  :: Text       -- ^ Subdir for epub in OCF@@ -323,8 +387,11 @@   , writerTOCDepth          :: Int            -- ^ Number of levels to include in TOC   , writerReferenceDoc      :: Maybe FilePath -- ^ Path to reference document if specified   , writerReferenceLocation :: ReferenceLocation    -- ^ Location of footnotes and references for writing markdown+  , writerFigureCaptionPosition :: CaptionPosition -- ^ Position of figure caption+  , writerTableCaptionPosition :: CaptionPosition -- ^ Position of table caption   , writerSyntaxMap         :: SyntaxMap   , writerPreferAscii       :: Bool           -- ^ Prefer ASCII representations of characters when possible+  , writerLinkImages        :: Bool           -- ^ Use links rather than embedding ODT images   } deriving (Show, Data, Typeable, Generic)  instance Default WriterOptions where@@ -332,6 +399,8 @@                       , writerVariables        = mempty                       , writerTabStop          = 4                       , writerTableOfContents  = False+                      , writerListOfFigures    = False+                      , writerListOfTables     = False                       , writerIncremental      = False                       , writerHTMLMathMethod   = PlainMath                       , writerNumberSections   = False@@ -348,8 +417,7 @@                       , writerHtmlQTags        = False                       , writerSlideLevel       = Nothing                       , writerTopLevelDivision = TopLevelDefault-                      , writerListings         = False-                      , writerHighlightStyle   = Just pygments+                      , writerHighlightMethod  = DefaultHighlighting                       , writerSetextHeaders    = False                       , writerListTables       = False                       , writerEpubSubdirectory = "EPUB"@@ -361,8 +429,11 @@                       , writerTOCDepth         = 3                       , writerReferenceDoc     = Nothing                       , writerReferenceLocation = EndOfDocument+                      , writerFigureCaptionPosition = CaptionBelow+                      , writerTableCaptionPosition  = CaptionAbove                       , writerSyntaxMap        = defaultSyntaxMap                       , writerPreferAscii      = False+                      , writerLinkImages       = False                       }  instance HasSyntaxExtensions WriterOptions where@@ -373,10 +444,13 @@ isEnabled ext opts = ext `extensionEnabled` getExtensions opts  defaultMathJaxURL :: Text-defaultMathJaxURL = "https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml-full.js"+defaultMathJaxURL = "https://cdn.jsdelivr.net/npm/mathjax@4/tex-chtml.js" +defaultWebTeXURL :: Text+defaultWebTeXURL = "https://latex.codecogs.com/png.latex?"+ defaultKaTeXURL :: Text-defaultKaTeXURL = "https://cdn.jsdelivr.net/npm/katex@0.15.1/dist/"+defaultKaTeXURL = "https://cdn.jsdelivr.net/npm/katex@latest/dist/"  -- Update documentation in doc/filters.md if this is changed. $(deriveJSON defaultOptions{ fieldLabelModifier =
src/Text/Pandoc/PDF.hs view
@@ -5,7 +5,7 @@ {-# LANGUAGE FlexibleContexts    #-} {- |    Module      : Text.Pandoc.PDF-   Copyright   : Copyright (C) 2012-2023 John MacFarlane+   Copyright   : Copyright (C) 2012-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -20,6 +20,7 @@ import qualified Control.Exception as E import Control.Monad.Trans (MonadIO (..)) import Control.Monad (foldM_)+import Crypto.Hash (hashWith, SHA1(SHA1)) import qualified Data.ByteString as BS import Data.ByteString.Lazy (ByteString) import qualified Data.ByteString.Lazy as BL@@ -42,6 +43,7 @@ import Text.DocLayout (literal, render, hsep) import Text.Pandoc.Definition import Text.Pandoc.Error (PandocError (PandocPDFProgramNotFoundError))+import Text.Pandoc.SelfContained (makeSelfContained) import Text.Pandoc.MIME (getMimeType) import Text.Pandoc.Options (HTMLMathMethod (..), WriterOptions (..)) import Text.Pandoc.Extensions (disableExtension, Extension(Ext_smart))@@ -52,12 +54,12 @@ import Text.Pandoc.Walk (walkM) import Text.Pandoc.Writers.Shared (getField, metaToContext) import Control.Monad.Catch (MonadMask)-import Data.Digest.Pure.SHA (sha1, showDigest) #ifdef _WINDOWS import Data.List (intercalate) #endif import Data.List (isPrefixOf, find)-import Text.Pandoc.Class (fillMediaBag, getVerbosity, setVerbosity,+import Text.Pandoc.MediaBag (mediaItems)+import Text.Pandoc.Class (fillMediaBag, getMediaBag, getVerbosity, setVerbosity,                           readFileStrict, fileExists,                           report, extractMedia, PandocMonad, runIOorExplode) import Text.Pandoc.Logging@@ -81,26 +83,54 @@         -> WriterOptions       -- ^ options         -> Pandoc              -- ^ document         -> m (Either ByteString ByteString)-makePDF program pdfargs writer opts doc =+makePDF program pdfargs writer opts doc = withTempDir (program == "typst") "media" $ \mediaDir -> do+#ifdef _WINDOWS+  -- note:  we want / even on Windows, for TexLive+  let tmpdir = changePathSeparators mediaDir+#else+  let tmpdir = mediaDir+#endif+  let isTeXFormat "context" = True+      isTeXFormat "tectonic" = True+      isTeXFormat "latexmk" = True+      isTeXFormat "lualatex" = True+      isTeXFormat "lualatex-dev" = True+      isTeXFormat "pdflatex" = True+      isTeXFormat "pdflatex-dev" = True+      isTeXFormat "xelatex" = True+      isTeXFormat _ = False+  let opts' = if isTeXFormat program+                 then -- disable quote ligatures to avoid bad ligatures like ?`+                      opts{ writerExtensions = disableExtension Ext_smart+                                (writerExtensions opts) }+                 else opts+  source <- fillMediaBag doc+              >>= extractMedia tmpdir+              >>= (if isTeXFormat program+                      then walkM (convertImages opts' tmpdir)+                      else return)+              >>= writer opts'++  verbosity <- getVerbosity+  let compileHTML mkOutArgs = do+        -- check to see if there is anything in mediabag, and if so,+        -- make the HTML self contained+        mediabag <- getMediaBag+        source' <- case mediaItems mediabag of+                      [] -> pure source+                      _ -> makeSelfContained source+        liftIO $+          toPdfViaTempFile verbosity program pdfargs mkOutArgs ".html" source'   case takeBaseName program of-    "wkhtmltopdf" -> makeWithWkhtmltopdf program pdfargs writer opts doc-    prog | prog `elem` ["pagedjs-cli" ,"weasyprint", "prince"] -> do-      let mkOutArgs f =-            if program `elem` ["pagedjs-cli", "prince"]-               then ["-o", f]-               else [f]-      source <- writer opts doc-      verbosity <- getVerbosity-      liftIO $ toPdfViaTempFile verbosity program pdfargs mkOutArgs source-    "typst" -> do-      source <- writer opts doc-      verbosity <- getVerbosity-      liftIO $-        toPdfViaTempFile verbosity program ("compile":pdfargs) (:[]) source+    "wkhtmltopdf" -> makeWithWkhtmltopdf program pdfargs writer opts' doc+    "pagedjs-cli" -> compileHTML (\f -> ["-o", f])+    "prince"      -> compileHTML (\f -> ["-o", f])+    "weasyprint"  -> compileHTML (:[])+    "typst" -> liftIO $+        toPdfViaTempFile verbosity program ("compile":pdfargs) (:[]) ".typ" source     "pdfroff" -> do-      source <- writer opts doc       let paperargs =-            case lookupContext "papersize" (writerVariables opts) of+            case lookupContext "papersize" (writerVariables opts') of               Just s                 | T.takeEnd 1 s == "l" -> ["-P-p" <>                                            T.unpack (T.dropEnd 1 s), "-P-l"]@@ -111,33 +141,35 @@                    ["-U" | ".PDFPIC" `T.isInfixOf` source] ++                     paperargs ++ pdfargs       generic2pdf program args source-    baseProg -> do-      withTempDir "tex2pdf." $ \tmpdir' -> do-#ifdef _WINDOWS-        -- note:  we want / even on Windows, for TexLive-        let tmpdir = changePathSeparators tmpdir'-#else-        let tmpdir = tmpdir'-#endif-        doc' <- handleImages opts tmpdir doc-        source <- writer opts{ writerExtensions = -- disable use of quote-                                  -- ligatures to avoid bad ligatures like ?`-                                  disableExtension Ext_smart-                                   (writerExtensions opts) } doc'-        case baseProg of-          "context" -> context2pdf program pdfargs tmpdir source-          "tectonic" -> tectonic2pdf program pdfargs tmpdir source-          prog | prog `elem` ["pdflatex", "lualatex", "xelatex", "latexmk"]-              -> tex2pdf program pdfargs tmpdir source-          _ -> return $ Left $ UTF8.fromStringLazy-                             $ "Unknown program " ++ program+    "groff" -> do+      let paperargs =+            case lookupContext "papersize" (writerVariables opts') of+              Just s+                | T.takeEnd 1 s == "l" -> ["-P-p" <>+                                           T.unpack (T.dropEnd 1 s), "-P-l"]+                | otherwise -> ["-P-p" <> T.unpack s]+              Nothing -> []+      let args   = ["-ms", "-Tpdf",+                    "-e", "-t", "-k", "-KUTF-8"] +++                   ["-U" | ".PDFPIC" `T.isInfixOf` source] +++                    paperargs ++ pdfargs+      generic2pdf program args source+    "context"      -> context2pdf program pdfargs tmpdir source+    "tectonic"     -> tectonic2pdf program pdfargs tmpdir source+    "latexmk"      -> tex2pdf program pdfargs tmpdir source+    "lualatex"     -> tex2pdf program pdfargs tmpdir source+    "lualatex-dev" -> tex2pdf program pdfargs tmpdir source+    "pdflatex"     -> tex2pdf program pdfargs tmpdir source+    "pdflatex-dev" -> tex2pdf program pdfargs tmpdir source+    "xelatex"      -> tex2pdf program pdfargs tmpdir source+    _ -> return $ Left $ UTF8.fromStringLazy $ "Unknown program " ++ program  -- latex has trouble with tildes in paths, which -- you find in Windows temp dir paths with longer -- user names (see #777) withTempDir :: (PandocMonad m, MonadMask m, MonadIO m)-            => FilePath -> (FilePath -> m a) -> m a-withTempDir templ action = do+            => Bool -> FilePath -> (FilePath -> m a) -> m a+withTempDir useWorkingDirectory templ action = do   tmp <- liftIO getTemporaryDirectory   uname <- liftIO $ E.catch     (do (ec, sout, _) <- readProcessWithExitCode "uname" ["-o"] ""@@ -145,9 +177,9 @@            then return $ Just $ filter (not . isSpace) sout            else return Nothing)     (\(_  :: E.SomeException) -> return Nothing)-  if '~' `elem` tmp || uname == Just "Cygwin" -- see #5451-         then withTempDirectory "." templ action-         else withSystemTempDirectory templ action+  if useWorkingDirectory || '~' `elem` tmp || uname == Just "Cygwin" -- see #5451+     then withTempDirectory "." templ action+     else withSystemTempDirectory templ action  makeWithWkhtmltopdf :: (PandocMonad m, MonadIO m)                     => String              -- ^ wkhtmltopdf or path@@ -184,18 +216,9 @@                  -- see #6474   source <- writer opts doc   verbosity <- getVerbosity-  liftIO $ toPdfViaTempFile verbosity program args (:[]) source--handleImages :: (PandocMonad m, MonadIO m)-             => WriterOptions-             -> FilePath      -- ^ temp dir to store images-             -> Pandoc        -- ^ document-             -> m Pandoc-handleImages opts tmpdir doc =-  fillMediaBag doc >>=-    extractMedia tmpdir >>=-    walkM (convertImages opts tmpdir)+  liftIO $ toPdfViaTempFile verbosity program args (:[]) ".html" source +-- convert SVG to PDF, and pixel formats to PNG or JPEG, for TeX formats convertImages :: (PandocMonad m, MonadIO m)               => WriterOptions -> FilePath -> Inline -> m Inline convertImages opts tmpdir (Image attr ils (src, tit)) = do@@ -236,7 +259,7 @@                  E.catch (Right pngOut <$ JP.savePngImage pngOut img) $                      \(e :: E.SomeException) -> return (Left (tshow e))   where-    sha = showDigest (sha1 (UTF8.fromStringLazy fname))+    sha = show (hashWith SHA1 (UTF8.fromString fname))     pngOut = normalise $ tmpdir </> sha <.> "png"     pdfOut = normalise $ tmpdir </> sha <.> "pdf"     svgIn = normalise fname@@ -314,7 +337,7 @@    go (Just msg) ln      | ln == "" = do -- emit report and reset accumulator          report $ MakePDFWarning $ render (Just 60) $-            hsep $ map literal $ T.words $ UTF8.toText $ BC.toStrict msg+            hsep $ map literal $ T.words $ utf8ToText msg          pure Nothing      | otherwise = pure $ Just (msg <> ln) @@ -358,7 +381,7 @@     (exit, out) <- liftIO $ E.catch       (pipeProcess (Just env) program programArgs sourceBL)       (handlePDFProgramNotFound program)-    report $ MakePDFInfo "tectonic output" (UTF8.toText $ BL.toStrict out)+    report $ MakePDFInfo "tectonic output" (utf8ToText out)     let pdfFile = tmpDir ++ "/texput.pdf"     (_, pdf) <- getResultingPDF Nothing pdfFile     return (exit, out, pdf)@@ -411,41 +434,32 @@                          , k /= "TEXINPUTS" && k /= "TEXMFOUTPUT"]     liftIO (UTF8.readFile file) >>=       showVerboseInfo (Just tmpDir) program programArgs env''-    go env'' programArgs (1 :: Int) Nothing+    go env'' programArgs (1 :: Int)  where    file = tmpDir ++ "/input.tex"    outfile = outDir ++ "/input.pdf"-   go env'' programArgs runNumber oldTocHash = do+   go env'' programArgs runNumber = do      let maxruns = 4 -- stop if warnings present after 4 runs      report $ MakePDFInfo ("LaTeX run number " <> tshow runNumber) mempty      (exit, out) <- liftIO $ E.catch        (pipeProcess (Just env'') program programArgs BL.empty)        (handlePDFProgramNotFound program)-     report $ MakePDFInfo "LaTeX output" (UTF8.toText $ BL.toStrict out)+     report $ MakePDFInfo "LaTeX output" (utf8ToText out)      -- parse log to see if we need to rerun LaTeX-     let logFile = replaceExtension file ".log"+     let logFile = replaceExtension outfile ".log"      logExists <- fileExists logFile      logContents <- if logExists                        then BL.fromStrict <$> readFileStrict logFile                        else return mempty      let rerunWarnings = checkForRerun logContents-     tocHash <- do-       let tocFile = replaceExtension file ".toc"-       tocFileExists <- fileExists tocFile-       if tocFileExists-          then do-            tocContents <- BL.fromStrict <$> readFileStrict tocFile-            pure $ Just $! sha1 tocContents-          else pure Nothing-     -- compare hash of toc to former hash to see if it changed (#9295)-     let rerunWarnings' = rerunWarnings ++-                           ["TOC changed" | tocHash /= oldTocHash ]+     tocFileExists <- fileExists (replaceExtension outfile ".toc")+       -- if we have a TOC we always need 3 runs, see #10308+     let rerunWarnings' = rerunWarnings ++ ["TOC is present" | tocFileExists]      if not (null rerunWarnings') && runNumber < maxruns         then do           report $ MakePDFInfo "Rerun needed"-                    (T.intercalate "\n"-                      (map (UTF8.toText . BC.toStrict) rerunWarnings'))-          go env'' programArgs (runNumber + 1) tocHash+                    (T.intercalate "\n" (map utf8ToText rerunWarnings'))+          go env'' programArgs (runNumber + 1)        else do           (log', pdf) <- getResultingPDF (Just logFile) outfile           return (exit, fromMaybe out log', pdf)@@ -477,10 +491,11 @@           -> String       -- ^ Program (program name or path)           -> [String]     -- ^ Args to program           -> (String -> [String]) -- ^ Construct args for output file+          -> String       -- ^ extension to use for input file (e.g. '.html')           -> Text         -- ^ Source           -> IO (Either ByteString ByteString)-toPdfViaTempFile verbosity program args mkOutArgs source =-  withTempFile "." "toPdfViaTempFile.html" $ \file h1 ->+toPdfViaTempFile verbosity program args mkOutArgs extension source =+  withTempFile "." ("toPdfViaTempFile" <> extension) $ \file h1 ->     withTempFile "." "toPdfViaTempFile.pdf" $ \pdfFile h2 -> do       hClose h1       hClose h2@@ -496,7 +511,7 @@         (handlePDFProgramNotFound program)       runIOorExplode $ do         setVerbosity verbosity-        report $ MakePDFInfo "pdf-engine output" (UTF8.toText $ BL.toStrict out)+        report $ MakePDFInfo "pdf-engine output" (utf8ToText out)       pdfExists <- doesFileExist pdfFile       mbPdf <- if pdfExists                 -- We read PDF as a strict bytestring to make sure that the@@ -529,7 +544,7 @@       (handlePDFProgramNotFound program)     runIOorExplode $ do       setVerbosity verbosity-      report $ MakePDFInfo "ConTeXt run output" (UTF8.toText $ BL.toStrict out)+      report $ MakePDFInfo "ConTeXt run output" (utf8ToText out)     let pdfFile = replaceExtension file ".pdf"     pdfExists <- doesFileExist pdfFile     mbPdf <- if pdfExists@@ -613,6 +628,7 @@                                , "SELFAUTOPARENT"                                , "SFDFONTS"                                , "SHELL"+                               , "SOURCE_DATE_EPOCH"                                , "T1FONTS"                                , "T1INPUTS"                                , "T42FONTS"
src/Text/Pandoc/Parsing.hs view
@@ -1,6 +1,6 @@ {- |    Module      : Text.Pandoc.Parsing-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -61,6 +61,8 @@                              lineBlockLines,                              tableWith,                              tableWith',+                             tableWithSpans,+                             tableWithSpans',                              widthsFromIndices,                              gridTableWith,                              gridTableWith',@@ -68,6 +70,10 @@                              TableNormalization (..),                              toTableComponents,                              toTableComponents',+                             toTableComponentsWithSpans,+                             toTableComponentsWithSpans',+                             singleRowSpans,+                             singleColumnSpans,                              readWith,                              readWithM,                              testStringWith,@@ -303,8 +309,14 @@       gridTableWith',       tableWith,       tableWith',+      tableWithSpans,+      tableWithSpans',       toTableComponents,       toTableComponents',+      toTableComponentsWithSpans,+      toTableComponentsWithSpans',+      singleRowSpans,+      singleColumnSpans,       widthsFromIndices,       TableComponents(..),       TableNormalization(..) )
src/Text/Pandoc/Parsing/Capabilities.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE MultiParamTypeClasses      #-} {- |    Module      : Text.Pandoc.Parsing-   Copyright   : © 2006-2023 John MacFarlane+   Copyright   : © 2006-2024 John MacFarlane    License     : GPL-2.0-or-later    Maintainer  : John MacFarlane <jgm@berkeley.edu> 
src/Text/Pandoc/Parsing/Citations.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE OverloadedStrings          #-} {- | Module      : Text.Pandoc.Parsing.Citations-Copyright   : © 2006-2023 John MacFarlane+Copyright   : © 2006-2024 John MacFarlane License     : GPL-2.0-or-later Maintainer  : John MacFarlane <jgm@berkeley.edu> 
src/Text/Pandoc/Parsing/Future.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} {- |    Module      : Text.Pandoc.Parsing.Future-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GPL-2.0-or-later    Maintainer  : John MacFarlane <jgm@berkeley.edu> 
src/Text/Pandoc/Parsing/General.hs view
@@ -1,8 +1,9 @@+{-# LANGUAGE BangPatterns               #-} {-# LANGUAGE FlexibleContexts           #-} {-# LANGUAGE OverloadedStrings          #-} {- | Module      : Text.Pandoc.Parsing.General-Copyright   : © 2006-2023 John MacFarlane+Copyright   : © 2006-2024 John MacFarlane License     : GPL-2.0-or-later Maintainer  : John MacFarlane <jgm@berkeley.edu> @@ -86,6 +87,8 @@ import Data.Ord (Down(..)) import Data.Maybe (fromMaybe) import Data.Text (Text)+import qualified Data.Text.Lazy.Builder as TB+import qualified Data.Text.Lazy as TL import Text.Pandoc.Asciify (toAsciiText) import Text.Pandoc.Builder (Attr, Inline(Str), Inlines, trimInlines) import Text.Pandoc.Class.PandocMonad (PandocMonad, readFileFromDirs, report)@@ -278,22 +281,20 @@ -- (This version due to Andrew Pimlott on the Haskell mailing list.)  oneOfStrings' :: (Stream s m Char, UpdateSourcePos s Char)-              => (Char -> Char -> Bool) -> [Text] -> ParsecT s st m Text-oneOfStrings' f = fmap T.pack . oneOfStrings'' f . fmap T.unpack---- TODO: This should be re-implemented in a Text-aware way-oneOfStrings'' :: (Stream s m Char, UpdateSourcePos s Char)-               => (Char -> Char -> Bool) -> [String] -> ParsecT s st m String-oneOfStrings'' _ []   = Prelude.fail "no strings"-oneOfStrings'' matches strs = try $ do-  c <- anyChar-  let strs' = [xs | (x:xs) <- strs, x `matches` c]-  case strs' of+               => (Char -> Char -> Bool) -> [Text] -> ParsecT s st m Text+oneOfStrings' _ [] = Prelude.fail "no strings to match"+oneOfStrings' matches strs =+  TL.toStrict . TB.toLazyText <$> try (go mempty strs)+ where+   go acc strs' = do+     c <- anyChar+     let strs'' = [t | Just (d, t) <- map T.uncons strs', matches c d]+     let !acc' = acc <> TB.singleton c+     case strs'' of        []  -> Prelude.fail "not found"-       _   -> (c:) <$> oneOfStrings'' matches strs'-               <|> if "" `elem` strs'-                      then return [c]-                      else Prelude.fail "not found"+       _   -> if any T.null strs''+                 then option acc' (try (go acc' strs''))+                 else go acc' strs''  -- | Parses one of a list of strings.  If the list contains -- two strings one of which is a prefix of the other, the longer@@ -399,15 +400,13 @@ -- | Parse string, case insensitive. stringAnyCase :: (Stream s m Char, UpdateSourcePos s Char)               => Text -> ParsecT s st m Text-stringAnyCase = fmap T.pack . stringAnyCase' . T.unpack--stringAnyCase' :: (Stream s m Char, UpdateSourcePos s Char)-               => String -> ParsecT s st m String-stringAnyCase' [] = string ""-stringAnyCase' (x:xs) = do-  firstChar <- char (toUpper x) <|> char (toLower x)-  rest <- stringAnyCase' xs-  return (firstChar:rest)+stringAnyCase t = TL.toStrict . TB.toLazyText <$> go (T.unpack t)+  where+    go [] = string "" $> mempty+    go (x:xs) = do+      c <- char (toUpper x) <|> char (toLower x)+      rest <- go xs+      pure $ TB.singleton c <> rest  -- TODO rewrite by just adding to Sources stream? -- | Parse contents of 'str' using 'parser' and return result.@@ -446,8 +445,8 @@ -- | Parse a string of characters between an open character -- and a close character, including text between balanced -- pairs of open and close, which must be different. For example,--- @charsInBalanced '(' ')' anyChar@ will parse "(hello (there))"--- and return "hello (there)".+-- @charsInBalanced '(' ')' (Data.Text.singleton <$> anyChar)@ will parse+-- "(hello (there))" and return "hello (there)". charsInBalanced :: (Stream s m Char, UpdateSourcePos s Char)                 => Char -> Char -> ParsecT s st m Text -> ParsecT s st m Text charsInBalanced open close parser = try $ do@@ -483,8 +482,10 @@                               xs <- many (satisfy isEmailChar)                               return (x:xs)        isEmailChar c     = isAlphaNum c || isEmailPunct c-       isEmailPunct c    = T.any (== c) "!\"#$%&'*+-/=?^_{|}~;"+       isEmailPunct c    = c `Set.member` emailPunctChars +emailPunctChars :: Set.Set Char+emailPunctChars = Set.fromList "!\"#$%&'*+-/=?^_{|}~;"  uriScheme :: (Stream s m Char, UpdateSourcePos s Char) => ParsecT s st m Text uriScheme = oneOfStringsCI (Set.toList schemes)@@ -531,7 +532,7 @@            <|> entity            <|> try (punct <* lookAhead (void wordChar <|> void percentEscaped))     uriChunkBetween l r = try $ do chunk <- between (char l) (char r) uriChunk-                                   return (T.pack $ [l] ++ chunk ++ [r])+                                   return $ T.singleton l <> T.pack chunk <> T.singleton r  -- | Applies a parser, returns tuple of its results and its horizontal -- displacement (the difference between the source column at the end@@ -687,7 +688,7 @@   where     ident' = fromMaybe ident (lookup "id" kvs)     cls'   = maybe cls T.words $ lookup "class" kvs-    kvs'   = filter (\(k,_) -> k /= "id" || k /= "class") kvs+    kvs'   = filter (\(k,_) -> k /= "id" && k /= "class") kvs  insertIncludedFile :: (PandocMonad m, HasIncludeFiles st)                    => ParsecT a st m b -- ^ parser to apply@@ -754,8 +755,9 @@       ((pos,txt):_) ->         let ls = T.lines txt <> [""]             ln = (errLine - sourceLine pos) + 1-         in if length ls > ln && ln >= 1-               then T.concat ["\n", ls !! (ln - 1)-                             ,"\n", T.replicate (errColumn - 1) " "-                             ,"^"]-               else ""+         in case drop (ln - 1) ls of+               (l:_) | ln >= 1 ->+                 T.concat ["\n", l+                          ,"\n", T.replicate (errColumn - 1) " "+                          ,"^"]+               _ -> ""
src/Text/Pandoc/Parsing/GridTable.hs view
@@ -3,7 +3,7 @@ {-# LANGUAGE OverloadedStrings          #-} {- |    Module      : Text.Pandoc.Parsing.GridTable-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GPL-2.0-or-later    Maintainer  : John MacFarlane <jgm@berkeley.edu> @@ -14,12 +14,18 @@   , gridTableWith'   , tableWith   , tableWith'+  , tableWithSpans+  , tableWithSpans'   , widthsFromIndices     -- * Components of a plain-text table   , TableComponents (..)   , TableNormalization (..)   , toTableComponents   , toTableComponents'+  , toTableComponentsWithSpans+  , toTableComponentsWithSpans'+  , singleRowSpans+  , singleColumnSpans   ) where @@ -34,6 +40,7 @@ import Text.Pandoc.Sources import Text.Parsec (Stream (..), ParsecT, optional, sepEndBy1, try) +import Data.Maybe (mapMaybe) import qualified Data.Text as T import qualified Text.GridTable as GT import qualified Text.Pandoc.Builder as B@@ -54,17 +61,30 @@   B.tableWith attr capt colspecs th tb tf  -- | Bundles basic table components into a single value.-toTableComponents :: [Alignment] -> [Double] -> [Blocks] -> [[Blocks]]+toTableComponents :: [Alignment] -> [Double] -> [[Blocks]] -> [[Blocks]]                   -> TableComponents toTableComponents = toTableComponents' NoNormalization  -- | Bundles basic table components into a single value, performing -- normalizations as necessary. toTableComponents' :: TableNormalization-                   -> [Alignment] -> [Double] -> [Blocks] -> [[Blocks]]+                   -> [Alignment] -> [Double] -> [[Blocks]] -> [[Blocks]]                    -> TableComponents toTableComponents' normalization aligns widths heads rows =-  let th = TableHead nullAttr (toHeaderRow normalization heads)+  toTableComponentsWithSpans' normalization aligns widths (singleSpansBlocks heads) (singleSpansBlocks rows)++-- | Bundles basic table components with span information into a single value.+toTableComponentsWithSpans :: [Alignment] -> [Double] -> [[(Blocks, RowSpan, ColSpan)]] -> [[(Blocks, RowSpan, ColSpan)]]+                           -> TableComponents+toTableComponentsWithSpans = toTableComponentsWithSpans' NoNormalization++-- | Bundles basic table components with span information into a single value,+-- performing normalizations as necessary.+toTableComponentsWithSpans' :: TableNormalization+                            -> [Alignment] -> [Double] -> [[(Blocks, RowSpan, ColSpan)]] -> [[(Blocks, RowSpan, ColSpan)]]+                            -> TableComponents+toTableComponentsWithSpans' normalization aligns widths heads rows =+  let th = TableHead nullAttr (mapMaybe (toHeaderRow normalization) heads)       tb = TableBody nullAttr 0 [] (map toRow rows)       tf = TableFoot nullAttr []       colspecs = toColSpecs aligns widths@@ -191,7 +211,7 @@ -- 'lineParser', and 'footerParser'. tableWith :: (Stream s m Char, UpdateSourcePos s Char,               HasReaderOptions st, Monad mf)-          => ParsecT s st m (mf [Blocks], [Alignment], [Int]) -- ^ header parser+          => ParsecT s st m (mf [[Blocks]], [Alignment], [Int]) -- ^ header parser           -> ([Int] -> ParsecT s st m (mf [Blocks]))  -- ^ row parser           -> ParsecT s st m sep                       -- ^ line parser           -> ParsecT s st m end                       -- ^ footer parser@@ -202,12 +222,36 @@ tableWith' :: (Stream s m Char, UpdateSourcePos s Char,                HasReaderOptions st, Monad mf)            => TableNormalization-           -> ParsecT s st m (mf [Blocks], [Alignment], [Int]) -- ^ header parser+           -> ParsecT s st m (mf [[Blocks]], [Alignment], [Int]) -- ^ header parser            -> ([Int] -> ParsecT s st m (mf [Blocks]))  -- ^ row parser            -> ParsecT s st m sep                       -- ^ line parser            -> ParsecT s st m end                       -- ^ footer parser            -> ParsecT s st m (mf TableComponents)-tableWith' n11n headerParser rowParser lineParser footerParser = try $ do+tableWith' n11n headerParser rowParser lineParser footerParser =+  tableWithSpans' n11n headerParser' rowParser' lineParser footerParser+    where+      headerParser' = fmap (\(heads, aligns, indices) -> (fmap singleSpansBlocks heads, aligns, indices)) headerParser+      rowParser' indices = fmap (\row -> zip3 row (repeat 1) (repeat 1)) <$> rowParser indices++tableWithSpans :: (Stream s m Char, UpdateSourcePos s Char,+              HasReaderOptions st, Monad mf)+               => ParsecT s st m (mf [[(Blocks, RowSpan, ColSpan)]], [Alignment], [Int]) -- ^ header parser+               -> ([Int] -> ParsecT s st m (mf [(Blocks, RowSpan, ColSpan)]))  -- ^ row parser+               -> ParsecT s st m sep                       -- ^ line parser+               -> ParsecT s st m end                       -- ^ footer parser+               -> ParsecT s st m (mf Blocks)+tableWithSpans hp rp lp fp = fmap tableFromComponents <$>+  tableWithSpans' NoNormalization hp rp lp fp++tableWithSpans' :: (Stream s m Char, UpdateSourcePos s Char,+               HasReaderOptions st, Monad mf)+                => TableNormalization+                -> ParsecT s st m (mf [[(Blocks, RowSpan, ColSpan)]], [Alignment], [Int]) -- ^ header parser+                -> ([Int] -> ParsecT s st m (mf [(Blocks, RowSpan, ColSpan)]))  -- ^ row parser+                -> ParsecT s st m sep                       -- ^ line parser+                -> ParsecT s st m end                       -- ^ footer parser+                -> ParsecT s st m (mf TableComponents)+tableWithSpans' n11n headerParser rowParser lineParser footerParser = try $ do   (heads, aligns, indices) <- headerParser   lines' <- sequence <$> rowParser indices `sepEndBy1` lineParser   footerParser@@ -215,15 +259,17 @@   let widths = if null indices                then replicate (length aligns) 0.0                else widthsFromIndices numColumns indices-  return $ toTableComponents' n11n aligns widths <$> heads <*> lines'+  return $ toTableComponentsWithSpans' n11n aligns widths <$> heads <*> lines' -toRow :: [Blocks] -> Row-toRow =  Row nullAttr . map B.simpleCell+toRow :: [(Blocks, RowSpan, ColSpan)] -> Row+toRow =  Row nullAttr . map (\(blocks, rowSpan, columnSpan) -> B.cell AlignDefault rowSpan columnSpan blocks) -toHeaderRow :: TableNormalization -> [Blocks] -> [Row]+toHeaderRow :: TableNormalization -> [(Blocks, RowSpan, ColSpan)] -> Maybe Row toHeaderRow = \case-  NoNormalization -> \l -> [toRow l | not (null l)]-  NormalizeHeader -> \l -> [toRow l | not (null l) && not (all null l)]+  NoNormalization -> \l -> if not (null l) then Just (toRow l) else Nothing+  NormalizeHeader -> \l -> if not (all nullHeaderRow l) then Just (toRow l) else Nothing+  where+    nullHeaderRow (l, _, _) = null l  -- | Calculate relative widths of table columns, based on indices widthsFromIndices :: Int      -- Number of columns on terminal@@ -248,4 +294,15 @@                    then fromIntegral totLength                    else fromIntegral numColumns       fracs = map (\l -> fromIntegral l / quotient) lengths in-  tail fracs+  drop 1 fracs++-- | List of lists of `RowSpan` of 1.+singleRowSpans :: [[RowSpan]]+singleRowSpans = repeat $ repeat 1++-- | List of lists of `ColsSpan` of 1.+singleColumnSpans :: [[ColSpan]]+singleColumnSpans = repeat $ repeat 1++singleSpansBlocks :: [[Blocks]] -> [[(Blocks, RowSpan, ColSpan)]]+singleSpansBlocks blocks = zipWith3 zip3 blocks singleRowSpans singleColumnSpans
src/Text/Pandoc/Parsing/Lists.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE OverloadedStrings          #-} {- | Module      : Text.Pandoc.Parsing.Lists-Copyright   : © 2006-2023 John MacFarlane+Copyright   : © 2006-2024 John MacFarlane License     : GPL-2.0-or-later Maintainer  : John MacFarlane <jgm@berkeley.edu> @@ -113,19 +113,23 @@            => ParsecT s ParserState m (ListNumberStyle, Int) exampleNum = do   char '@'-  lab <- mconcat . map T.pack <$>+  lab <- T.pack . concat <$>                     many (many1 alphaNum <|>                           try (do c <- char '_' <|> char '-'                                   cs <- many1 alphaNum                                   return (c:cs)))   st <- getState-  let num = stateNextExample st-  let newlabels = if T.null lab-                     then stateExamples st-                     else M.insert lab num $ stateExamples st-  updateState $ \s -> s{ stateNextExample = num + 1-                       , stateExamples    = newlabels }-  return (Example, num)+  case M.lookup lab (stateExamples st) of+    Nothing -> do -- new label+      let num = stateNextExample st+      let newlabels = if T.null lab+                         then stateExamples st+                         else M.insert lab num $ stateExamples st+      updateState $ \s -> s{ stateNextExample = num + 1+                           , stateExamples    = newlabels }+      return (Example, num)+    Just num -> -- reuse existing label+      return (Example, num)  -- | Parses a '#' returns (DefaultStyle, 1). defaultNum :: (Stream s m Char, UpdateSourcePos s Char) => ParsecT s st m (ListNumberStyle, Int)
src/Text/Pandoc/Parsing/Math.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE OverloadedStrings          #-} {- | Module      : Text.Pandoc.Parsing.Math-Copyright   : © 2006-2023 John MacFarlane+Copyright   : © 2006-2024 John MacFarlane License     : GPL-2.0-or-later Maintainer  : John MacFarlane <jgm@berkeley.edu> @@ -28,6 +28,8 @@   (UpdateSourcePos, anyChar, char, digit, newline, satisfy, space, string)  import qualified Data.Text as T+import qualified Data.Text.Lazy as TL+import qualified Data.Text.Lazy.Builder as TB  mathInlineWith :: (Stream s m Char, UpdateSourcePos s Char)  => Text -> Text -> ParsecT s st m Text mathInlineWith op cl = try $ do@@ -42,31 +44,38 @@                            (try (string "text" >>                                  (("\\text" <>) <$> inBalancedBraces 0 ""))                             <|>  (\c -> T.pack ['\\',c]) <$> anyChar))-                   <|> ("\n" <$ blankline <* notFollowedBy' blankline)+                   <|> ("\n" <$ blankline <* notFollowedBy' blankline <* notFollowedBy (char '$'))                    <|> (T.pack <$> many1 spaceChar <* notFollowedBy (char '$'))                     ) (try $ textStr cl)   notFollowedBy digit  -- to prevent capture of $5   return $ trimMath $ T.concat words'  where-  inBalancedBraces :: (Stream s m Char, UpdateSourcePos s Char) => Int -> Text -> ParsecT s st m Text-  inBalancedBraces n = fmap T.pack . inBalancedBraces' n . T.unpack+  inBalancedBraces :: (Stream s m Char, UpdateSourcePos s Char)+                   => Int -> Text -> ParsecT s st m Text+  inBalancedBraces n t =+    TL.toStrict . TB.toLazyText <$>+      go n False (TB.fromText t) (not (T.null t)) -  inBalancedBraces' :: (Stream s m Char, UpdateSourcePos s Char) => Int -> String -> ParsecT s st m String-  inBalancedBraces' 0 "" = do+  -- go depth lastWasBackslash accumulator started+  go :: (Stream s m Char, UpdateSourcePos s Char)+     => Int -> Bool -> TB.Builder -> Bool -> ParsecT s st m TB.Builder+  go 0 _ acc False = do     c <- anyChar     if c == '{'-       then inBalancedBraces' 1 "{"+       then go 1 False (acc <> TB.singleton '{') True        else mzero-  inBalancedBraces' 0 s = return $ reverse s-  inBalancedBraces' numOpen ('\\':xs) = do+  go 0 _ acc True = return acc+  go depth True acc _ = do     c <- anyChar-    inBalancedBraces' numOpen (c:'\\':xs)-  inBalancedBraces' numOpen xs = do+    go depth False (acc <> TB.singleton c) True+  go depth False acc _ = do     c <- anyChar+    let acc' = acc <> TB.singleton c     case c of-         '}' -> inBalancedBraces' (numOpen - 1) (c:xs)-         '{' -> inBalancedBraces' (numOpen + 1) (c:xs)-         _   -> inBalancedBraces' numOpen (c:xs)+         '\\' -> go depth True acc' True+         '}'  -> go (depth - 1) False acc' True+         '{'  -> go (depth + 1) False acc' True+         _    -> go depth False acc' True  mathDisplayWith :: (Stream s m Char, UpdateSourcePos s Char) => Text -> Text -> ParsecT s st m Text mathDisplayWith op cl = try $ fmap T.pack $ do
src/Text/Pandoc/Parsing/Smart.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE OverloadedStrings          #-} {- | Module      : Text.Pandoc.Parsing.Smart-Copyright   : © 2006-2023 John MacFarlane+Copyright   : © 2006-2024 John MacFarlane License     : GPL-2.0-or-later Maintainer  : John MacFarlane <jgm@berkeley.edu> @@ -43,7 +43,6 @@   , notFollowedBy   , try   )-import qualified Data.Text as T import qualified Text.Pandoc.Builder as B  -- | Parses various ASCII punctuation, quotes, and apostrophe in a smart@@ -93,13 +92,6 @@      (withQuoteContext InDoubleQuote (manyTill inlineParser doubleQuoteEnd)))    <|> pure (B.str "\8220") -charOrRef :: (Stream s m Char, UpdateSourcePos s Char) => [Char] -> ParsecT s st m Char-charOrRef cs =-  oneOf cs <|> try (do t <- characterReference-                       case T.unpack t of-                         [c] | c `elem` cs -> return c-                         _ -> fail "unexpected character reference")- -- | Succeeds if the parser is -- -- * not within single quoted text;@@ -116,13 +108,13 @@   -- single quote start can't be right after str   guard =<< notAfterString   try $ do-    charOrRef "'\8216\145"+    char '\''     void $ lookAhead (satisfy (not . isSpaceChar))  singleQuoteEnd :: (Stream s m Char, UpdateSourcePos s Char)                => ParsecT s st m () singleQuoteEnd = try $ do-  charOrRef "'\8217\146"+  char '\''   notFollowedBy alphaNum  -- | Succeeds if the parser is@@ -142,13 +134,13 @@ doubleQuoteStart = do   failIfInQuoteContext InDoubleQuote   guard =<< notAfterString-  try $ do charOrRef "\"\8220\147"+  try $ do char '"'            void $ lookAhead (satisfy (not . isSpaceChar))  -- | Parses a closing quote character. doubleQuoteEnd :: (Stream s m Char, UpdateSourcePos s Char)                => ParsecT s st m ()-doubleQuoteEnd = void (charOrRef "\"\8221\148")+doubleQuoteEnd = void (char '"')  -- | Parses an ASCII apostrophe (@'@) or right single quotation mark and -- returns a RIGHT SINGLE QUOtatiON MARK character.
src/Text/Pandoc/Parsing/State.hs view
@@ -3,7 +3,7 @@ {-# LANGUAGE OverloadedStrings          #-} {- |    Module      : Text.Pandoc.Parsing-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GPL-2.0-or-later    Maintainer  : John MacFarlane <jgm@berkeley.edu> @@ -186,4 +186,4 @@  type KeyTable = M.Map Key (Target, Attr) -type SubstTable = M.Map Key Inlines+type SubstTable = M.Map Key Blocks
src/Text/Pandoc/Process.hs view
@@ -1,6 +1,6 @@ {- |    Module      : Text.Pandoc.Process-   Copyright   : Copyright (C) 2013-2023 John MacFarlane+   Copyright   : Copyright (C) 2013-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>
src/Text/Pandoc/Readers.hs view
@@ -5,7 +5,7 @@ {-# LANGUAGE TupleSections       #-} {- |    Module      : Text.Pandoc.Readers-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -25,7 +25,10 @@     -- * Readers: converting /to/ Pandoc format     Reader (..)   , readers+  , readAsciiDoc   , readDocx+  , readPptx+  , readXlsx   , readODT   , readMarkdown   , readCommonMark@@ -51,6 +54,7 @@   , readEPUB   , readMuse   , readMan+  , readMdoc   , readFB2   , readIpynb   , readCSV@@ -63,6 +67,8 @@   , readRTF   , readTypst   , readDjot+  , readPod+  , readXML   -- * Miscellaneous   , getReader   , getDefaultExtensions@@ -79,11 +85,14 @@ import Text.Pandoc.Extensions import qualified Text.Pandoc.Format as Format import Text.Pandoc.Options+import Text.Pandoc.Readers.AsciiDoc import Text.Pandoc.Readers.CommonMark import Text.Pandoc.Readers.Markdown import Text.Pandoc.Readers.Creole import Text.Pandoc.Readers.DocBook import Text.Pandoc.Readers.Docx+import Text.Pandoc.Readers.Pptx+import Text.Pandoc.Readers.Xlsx import Text.Pandoc.Readers.DokuWiki import Text.Pandoc.Readers.EPUB import Text.Pandoc.Readers.FB2@@ -99,6 +108,7 @@ import Text.Pandoc.Readers.ODT import Text.Pandoc.Readers.OPML import Text.Pandoc.Readers.Org+import Text.Pandoc.Readers.Pod import Text.Pandoc.Readers.RST import Text.Pandoc.Readers.Textile import Text.Pandoc.Readers.TikiWiki@@ -106,6 +116,7 @@ import Text.Pandoc.Readers.Txt2Tags import Text.Pandoc.Readers.Vimwiki import Text.Pandoc.Readers.Man+import Text.Pandoc.Readers.Mdoc import Text.Pandoc.Readers.CSV import Text.Pandoc.Readers.CslJson import Text.Pandoc.Readers.BibTeX@@ -114,6 +125,7 @@ import Text.Pandoc.Readers.RTF import Text.Pandoc.Readers.Typst import Text.Pandoc.Readers.Djot+import Text.Pandoc.Readers.XML import qualified Text.Pandoc.UTF8 as UTF8 import Text.Pandoc.Sources (ToSources(..), sourcesToText) @@ -132,6 +144,7 @@           ,("markdown_mmd",  TextReader readMarkdown)           ,("commonmark"   , TextReader readCommonMark)           ,("commonmark_x" , TextReader readCommonMark)+          ,("asciidoc"     , TextReader readAsciiDoc)           ,("creole"       , TextReader readCreole)           ,("dokuwiki"     , TextReader readDokuWiki)           ,("gfm"          , TextReader readCommonMark)@@ -151,6 +164,8 @@           ,("twiki"        , TextReader readTWiki)           ,("tikiwiki"     , TextReader readTikiWiki)           ,("docx"         , ByteStringReader readDocx)+          ,("pptx"         , ByteStringReader readPptx)+          ,("xlsx"         , ByteStringReader readXlsx)           ,("odt"          , ByteStringReader readODT)           ,("t2t"          , TextReader readTxt2Tags)           ,("epub"         , ByteStringReader readEPUB)@@ -168,6 +183,9 @@           ,("rtf"          , TextReader readRTF)           ,("typst"        , TextReader readTypst)           ,("djot"         , TextReader readDjot)+          ,("mdoc"         , TextReader readMdoc)+          ,("pod"          , TextReader readPod)+          ,("xml"          , TextReader readXML)           ]  -- | Retrieve reader, extensions based on format spec (format+extensions).
+ src/Text/Pandoc/Readers/AsciiDoc.hs view
@@ -0,0 +1,416 @@+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FlexibleContexts #-}++{- |+   Module      : Text.Pandoc.Readers.AsciiDoc+   Copyright   : Copyright (C) 2024 John MacFarlane+   License     : GNU GPL, version 2 or above++   Maintainer  : John MacFarlane <jgm@berkeley.edu>+   Stability   : alpha+   Portability : portable++Reads and evaluates a AsciiDoc document as a Pandoc AST.+-}+module Text.Pandoc.Readers.AsciiDoc+  ( readAsciiDoc+  )+where++import Text.Pandoc.Class+import Text.Pandoc.Options+import Text.Pandoc.Definition+import Text.Pandoc.Walk+import Text.Pandoc.Shared (addPandocAttributes, blocksToInlines, safeRead,+                           tshow)+import qualified Text.Pandoc.UTF8 as UTF8+import qualified AsciiDoc as A+import Text.Pandoc.Error+import qualified Text.Pandoc.Builder as B+import Text.Pandoc.Readers.HTML (readHtml)+import Control.Monad.Except (throwError)+import Control.Monad+import Text.Pandoc.Parsing (newPos, sourceName)+import Text.Pandoc.Logging+import Text.Pandoc.Sources+import Control.Monad.State+import qualified Data.List as L+import Data.Char (chr, ord)+import qualified Data.Text as T+import qualified Data.Map as M+import Data.Maybe (fromMaybe)++-- import Debug.Trace++-- | Read AsciiDoc from an input string and return a Pandoc document.+readAsciiDoc :: (PandocMonad m, ToSources a) => ReaderOptions -> a -> m Pandoc+readAsciiDoc _opts inp = do+  let Sources sources = toSources inp+  (mconcat <$> mapM+   (\(sourcepos, t) ->+     A.parseDocument getIncludeFile raiseError (sourceName sourcepos) t)+    sources)+   >>= resolveFootnotes+   >>= resolveStem+   >>= resolveIcons+   >>= toPandoc+ where+  getIncludeFile fp = UTF8.toText <$> readFileStrict fp+  raiseError fp pos msg = throwError $ PandocParseError $ T.pack+                            $ msg <> " at " <> show fp <>+                              " char " <> show pos++toPandoc :: PandocMonad m => A.Document -> m Pandoc+toPandoc doc =+  Pandoc <$> doMeta (A.docMeta doc)+         <*> (B.toList <$> doBlocks (A.docBlocks doc))++resolveFootnotes :: Monad m => A.Document -> m A.Document+resolveFootnotes doc = do+  evalStateT (A.mapInlines go doc) (mempty :: M.Map T.Text [A.Inline])+ where+   go (A.Inline attr (A.Footnote (Just (A.FootnoteId fnid)) ils)) = do+     fnmap <- get+     case M.lookup fnid fnmap of+       Just ils' ->+         pure $ A.Inline attr (A.Footnote (Just (A.FootnoteId fnid)) ils')+       Nothing -> do+         put $ M.insert fnid ils fnmap+         pure $ A.Inline attr (A.Footnote (Just (A.FootnoteId fnid)) ils)+   go x = pure x++resolveStem :: Monad m => A.Document -> m A.Document+resolveStem doc = do+  let defaultType = case M.lookup "stem" (A.docAttributes (A.docMeta doc)) of+                      Just "asciimath" -> A.AsciiMath+                      _ -> A.LaTeXMath+  let doInlineStem (A.Inline attr (A.Math Nothing t)) =+        pure $ A.Inline attr (A.Math (Just defaultType) t)+      doInlineStem x = pure x+  let doBlockStem (A.Block attr mbtit (A.MathBlock Nothing t)) =+        pure $ A.Block attr mbtit (A.MathBlock (Just defaultType) t)+      doBlockStem x = A.mapInlines doInlineStem x+  A.mapBlocks doBlockStem doc++-- resolve icons as either characters in an icon font or images+resolveIcons :: Monad m => A.Document -> m A.Document+resolveIcons doc = A.mapInlines fromIcon doc+ where+   docattrs = A.docAttributes (A.docMeta doc)+   iconFont = case M.lookup "icons" docattrs of+                Just "font" -> True+                _ -> False+   iconsdir = fromMaybe "./images/icons" $ M.lookup "iconsdir" docattrs+   icontype = fromMaybe "png" $ M.lookup "icontype" docattrs+   addClasses cls (A.Attr ps kvs) =+     A.Attr ps $+      case M.lookup "role" kvs of+       Just r -> M.insert "role" (T.unwords (r : cls)) kvs+       Nothing -> M.insert "role" (T.unwords cls) kvs+   fromIcon (A.Inline attr (A.Icon name)) =+     if iconFont+        then pure $+              A.Inline (addClasses ["fa", "fa-" <> name] attr) (A.Span [])+        else pure $ -- default is to use an image+              A.Inline (addClasses ["icon"] attr)+                 (A.InlineImage+                   (A.Target+                      (iconsdir <> "/" <> name <> "." <> icontype))+                      Nothing Nothing Nothing)+   fromIcon x = pure x++addAttribution :: Maybe A.Attribution -> B.Blocks -> B.Blocks+addAttribution Nothing bs = bs+addAttribution (Just (A.Attribution t)) bs = B.fromList $+  case B.toList bs of+    [B.Div attr bls] -> [B.Div attr (bls ++ [attrBlock])]+    [B.BlockQuote bls] -> [B.BlockQuote (bls ++ [attrBlock])]+    xs -> xs ++ [attrBlock]+ where+   attrBlock = Para (B.toList $ B.text $ "\x2014 " <> t)++doMeta :: PandocMonad m => A.Meta -> m B.Meta+doMeta meta = do+  tit' <- doInlines (A.docTitle meta)+  pure $+    (if tit' == mempty+        then id+        else B.setMeta "title" tit') .+    (case A.docAuthors meta of+       [] -> id+       as -> B.setMeta "author" (map fromAuthor as)) .+    (case A.docRevision meta of+       Nothing -> id+       Just (A.Revision vers mbdate mbremark) ->+         B.setMeta "version" vers .+         maybe id (B.setMeta "date") mbdate .+         maybe id (B.setMeta "remark") mbremark) .+    flip (L.foldl' (\m (k,v) ->+                    -- leave out flags that are set just for processing+                    if k == "sectids" || k == "stem"+                       then m+                       else if T.null v+                               then B.setMeta k True m+                               else B.setMeta k v m))+      (M.toList (A.docAttributes meta))+    $ mempty++fromAuthor :: A.Author -> B.Inlines+fromAuthor au = B.text (A.authorName au) <>+  maybe mempty (\email ->+    " (" <> B.link ("mailto:" <> email) "" (B.str email) <> ")")+    (A.authorEmail au)++doBlocks :: PandocMonad m => [A.Block] -> m B.Blocks+doBlocks = fmap mconcat . mapM doBlock++addBlockAttr :: A.Attr -> B.Blocks -> B.Blocks+addBlockAttr (A.Attr _ kvs') bs =+  case B.toList bs of+    x@(B.OrderedList{}) : xs -> -- "start" is handled in list attribs+      addPandocAttributes (M.toList $ M.delete "start" kvs)+             (B.singleton x) <> B.fromList xs+    x:xs -> addPandocAttributes (M.toList kvs) (B.singleton x)+                <> B.fromList xs+    [] -> mempty+ where+  kvs = M.mapKeys (\k -> if k == "role" then "class" else k) kvs'++addBlockTitle :: B.Inlines -> B.Blocks -> B.Blocks+addBlockTitle tit' bs =+  let tit = B.toList tit'+  in case B.toList bs of+    [B.Table attr _ colspecs thead tbody tfoot] ->+      B.singleton $ B.Table attr (B.Caption Nothing [B.Plain tit])+                     colspecs thead tbody tfoot+    [B.Figure attr _ bs'] ->+      B.singleton $ B.Figure attr (B.Caption Nothing [B.Plain tit]) bs'+    [B.Div attr (B.Div ("",["title"],[]) [Para _] : bs')] ->+      -- replace existing title, which might be e.g. "Note"+      B.singleton $ B.Div attr (B.Div ("",["title"],[]) [B.Para tit] : bs')+    [B.Div attr bs'] -> -- put title Div inside+      B.singleton $ B.Div attr (B.Div ("",["title"],[]) [B.Para tit] : bs')+    _ -> B.divWith B.nullAttr (B.divWith ("",["title"],[]) (B.para tit') <> bs)++doBlock :: PandocMonad m => A.Block -> m B.Blocks+doBlock (A.Block attr@(A.Attr ps kvs) mbtitle bt) = do+  mbtitle' <- case mbtitle of+                Nothing -> pure Nothing+                Just (A.BlockTitle ils) -> Just <$> doInlines ils+  addBlockAttr attr . maybe id addBlockTitle mbtitle' <$>+   case bt of+    A.Section (A.Level lev) ils bs -> do+      ils' <- doInlines ils+      bs' <- doBlocks bs+      pure $ (B.header lev ils') <> bs'+    A.DiscreteHeading (A.Level lev) ils ->+      B.header lev <$> doInlines ils+    A.Paragraph ils -> B.para <$> doInlines ils+    A.LiteralBlock t -> pure $ B.codeBlock t+    A.Listing mblang lns -> do+      let fromCallout (A.Callout i)+            | i <= 20 = T.pack [' ', chr (0x2460 + i - 1)]+            | otherwise = "<" <> tshow i <> ">"+      let fromSourceLine (A.SourceLine t callouts) =+            t <> mconcat (map fromCallout callouts)+      let code = T.intercalate "\n" $ map fromSourceLine lns+      let classes = case mblang of+                      Nothing -> []+                      Just (A.Language l) -> [l]+      pure $ B.codeBlockWith ("", classes, []) code+    A.IncludeListing _ _ Nothing -> pure mempty+    A.IncludeListing mblang _fp (Just lns) ->+      doBlock (A.Block mempty mbtitle (A.Listing mblang lns))+    A.ExampleBlock bs -> B.divWith ("",["example"],[]) <$> doBlocks bs+    A.Sidebar bs -> B.divWith ("",["sidebar"],[]) <$> doBlocks bs+    A.OpenBlock bs -> B.divWith ("",[],[]) <$> doBlocks bs+    A.QuoteBlock mbattrib bs ->+      addAttribution mbattrib . B.blockQuote <$> doBlocks bs+    A.Verse mbattrib bs ->+      addAttribution mbattrib . B.blockQuote <$> doBlocks bs+    -- TODO when texmath's asciimath parser works, convert:+    A.MathBlock (Just A.AsciiMath) t -> pure $ B.para $ B.displayMath t+    A.MathBlock (Just A.LaTeXMath) t -> pure $ B.para $ B.displayMath t+    A.MathBlock Nothing _ ->+      throwError $ PandocParseError "Encountered math type Nothing"+    A.List (A.BulletList _) items ->+      B.bulletList <$> mapM doItem items+    A.List A.CheckList items ->+      B.bulletList <$> mapM doItem items+    A.List (A.OrderedList _ mbstart) items -> do+      let start = fromMaybe (1 :: Int)+                    (mbstart `mplus` (M.lookup "start" kvs >>= safeRead))+      let getStyle xs = case xs of+                  "arabic":_ -> Decimal+                  "decimal":_ -> Decimal+                  "loweralpha":_ -> LowerAlpha+                  "upperalpha":_ -> UpperAlpha+                  "lowerroman":_ -> LowerRoman+                  "upperroman":_ -> UpperRoman+                  _:rest -> getStyle rest+                  [] -> DefaultStyle+      let sty = getStyle ps+      let delim = DefaultDelim+      B.orderedListWith (start, sty, delim) <$> mapM doItem items+    A.List A.CalloutList items ->+      B.divWith ("",["callout-list"],[]) . B.orderedList <$> mapM doItem items+    A.DefinitionList items+      | "ordered" `elem` ps ->+          B.orderedList <$>+             mapM (fmap (B.definitionList . (:[])) . doDefListItem) items+      | otherwise -> B.definitionList <$> mapM doDefListItem items+    A.Table specs mbHeader rows mbFooter -> do+      let toAlign A.AlignLeft = B.AlignLeft+          toAlign A.AlignCenter = B.AlignCenter+          toAlign A.AlignRight = B.AlignRight+      let fromCell (A.TableCell bs mbHorizAlign _mbVertAlign colspan rowspan) =+            B.Cell B.nullAttr (maybe B.AlignDefault toAlign mbHorizAlign)+                        (B.RowSpan rowspan) (B.ColSpan colspan) . B.toList+                   <$> doBlocks bs+      let fromRow (A.TableRow cs) = B.Row B.nullAttr <$> mapM fromCell cs+      tbody <- B.TableBody B.nullAttr (B.RowHeadColumns 0) [] <$> mapM fromRow rows+      thead <- B.TableHead B.nullAttr <$> maybe (pure []) (mapM fromRow) mbHeader+      tfoot <- B.TableFoot B.nullAttr <$> maybe (pure []) (mapM fromRow) mbFooter+      let totalWidth = sum $ map (fromMaybe 1 . A.colWidth) specs+      let toColSpec spec = (maybe B.AlignDefault toAlign (A.colHorizAlign spec),+                             maybe B.ColWidthDefault+                               (B.ColWidth . (\x ->+                                   fromIntegral x / fromIntegral totalWidth))+                               (A.colWidth spec))+      let colspecs = map toColSpec specs+      pure $ B.table (B.Caption Nothing mempty) -- added by addBlockTitle+                colspecs thead [tbody] tfoot+    A.BlockImage target mbalt mbw mbh -> do+      img' <- doInline (A.Inline mempty (A.InlineImage target mbalt mbw mbh))+      -- TODO have a global function that adds the title to caption here:+      pure $ B.figure (Caption Nothing mempty) -- added by addBlockTitle+                      (B.plain img')+    -- TODO alt text?+    A.BlockAudio (A.Target t) ->+      pure $ B.plain $ B.image t "" (B.str t)+    -- TODO alt text?+    A.BlockVideo (A.Target t) ->+      pure $ B.plain $ B.image t "" (B.str t)+    A.TOC -> pure $ B.divWith ("toc",[],[]) mempty+    A.Admonition admonitionType bs -> do+      let admon = T.pack $ show admonitionType+      bs' <- doBlocks bs+      pure $ B.divWith ("",[T.toLower admon],[])+           $ B.divWith ("",["title"],[]) (B.para (B.str admon)) <> bs'+    A.PageBreak ->+      pure $ B.divWith ("", ["page-break"], [("wrapper", "1")]) B.horizontalRule+    A.ThematicBreak -> pure $ B.horizontalRule+    A.Include fp (Just bs) ->+      B.divWith ("",["included"],[("path",T.pack fp)]) <$> doBlocks bs+    A.Include fp Nothing -> do+      report $ CouldNotLoadIncludeFile (T.pack fp) (newPos "" 0 0)+      pure mempty+    A.PassthroughBlock t ->+         case runPure (readHtml def{+                               readerExtensions = extensionsFromList [Ext_raw_html]+                               } t) of+        Left _ -> pure $ B.rawBlock "html" t+        Right (Pandoc _ bs) -> pure $ B.fromList bs++doItem :: PandocMonad m => A.ListItem -> m B.Blocks+doItem (A.ListItem Nothing bs) = doBlocks bs+doItem (A.ListItem (Just checkstate) bs) = do+  bs' <- doBlocks bs+  let check = case checkstate of+                A.Checked -> Str "\9746"+                A.Unchecked -> Str "\9744"+  pure $ B.fromList+       $ case B.toList bs' of+           (B.Para ils : rest) -> B.Para (check : B.Space : ils) : rest+           (B.Plain ils : rest) -> B.Plain (check : B.Space : ils) : rest+           rest -> B.Para [check] : rest++doDefListItem :: PandocMonad m+              => ([A.Inline], [A.Block]) -> m (B.Inlines , [B.Blocks])+doDefListItem (lab, bs) = do+  lab' <- doInlines lab+  bs' <- doBlocks bs+  pure (lab', [bs'])++doInlines :: PandocMonad m => [A.Inline] -> m B.Inlines+doInlines = fmap mconcat . mapM doInline++doInline :: PandocMonad m => A.Inline -> m B.Inlines+doInline (A.Inline (A.Attr _ps kvs') it) = do+  let kvs = M.mapKeys (\k -> if k == "role" then "class" else k) kvs'+  addPandocAttributes (M.toList kvs) <$>+   case it of+    A.Str t -> pure $ B.text t+    A.HardBreak -> pure B.linebreak+    A.Bold ils -> B.strong <$> doInlines ils+    A.Italic ils -> B.emph <$> doInlines ils+    A.Monospace ils -> walk monospaceStr <$> doInlines ils+    A.Superscript ils -> B.superscript <$> doInlines ils+    A.Subscript ils -> B.subscript <$> doInlines ils+    A.Highlight ils -> B.spanWith ("",["mark"],[]) <$> doInlines ils+    A.Strikethrough ils -> B.strikeout <$> doInlines ils+    A.DoubleQuoted ils -> B.doubleQuoted <$> doInlines ils+    A.SingleQuoted ils -> B.singleQuoted <$> doInlines ils+    -- TODO when texmath's asciimath parser works, convert:+    A.Math (Just A.AsciiMath) t -> pure $ B.math t+    A.Math (Just A.LaTeXMath) t -> pure $ B.math t+    A.Math Nothing _ ->+      throwError $ PandocParseError "Encountered math type Nothing"+    A.Icon t -> pure $ B.spanWith ("",["icon"],[("name",t)])+                         (B.str ("[" <> t <> "]"))+    A.Button t -> pure $ B.spanWith ("",["button"],[])+                         (B.strong $ B.str ("[" <> t <> "]"))+    A.Kbd ts -> pure $ mconcat $ L.intersperse (B.str "+") $+         map (B.spanWith ("",["kbd"],[]) . B.strong . B.str) ts+    A.Menu ts -> pure $ B.spanWith ("",["menu"],[]) $+        B.strong $ B.text $ T.intercalate " › " ts+    -- TODO do we need linktype?+    A.Link _linkType (A.Target t) ils -> B.link t "" <$> doInlines ils+    A.InlineImage (A.Target url) mbalt mbwidth mbheight -> do+      let alt = case mbalt of+                  Just (A.AltText t) -> B.text t+                  Nothing -> mempty+          width = case mbwidth of+                  Just (A.Width n) -> [("width", T.pack $ show n <> "px")]+                  Nothing -> []+          height = case mbheight of+                  Just (A.Height n) -> [("height", T.pack $ show n <> "px")]+                  Nothing -> []+      pure $ B.imageWith ("",[], width ++ height) url "" alt+    A.Footnote _ ils -> B.note . B.para <$> doInlines ils+    A.InlineAnchor t _ -> pure $ B.spanWith (t, [], []) mempty+    A.BibliographyAnchor t _ -> pure $ B.spanWith (t, [], []) mempty+    A.CrossReference t Nothing ->+      pure $ B.linkWith ("",["cross-reference"],[]) ("#" <> t) "" (B.str t)+    A.CrossReference t (Just ils) -> do+      B.linkWith ("",["cross-reference"],[]) ("#" <> t) "" <$> doInlines ils+    A.AttributeReference (A.AttributeName t) -> -- if this is here, it's unresolved+      pure $ B.str ("{" <> t <> "}")+    A.Span ils -> B.spanWith B.nullAttr <$> doInlines ils+    A.IndexEntry (A.TermInText t) ->+      pure $ B.spanWith ("",["index"],[("term",t)]) (B.text t)+    A.IndexEntry (A.TermConcealed ts) ->+      pure $ B.spanWith ("",["index"],[("term",T.intercalate "," ts)]) mempty+    A.Counter name ctype val ->+      pure $ B.spanWith ("",["counter"],[("name",name)]) $ B.str $+        case ctype of+          A.DecimalCounter -> tshow val+          A.UpperAlphaCounter -> T.singleton $ chr (ord 'A' + val - 1)+          A.LowerAlphaCounter -> T.singleton $ chr (ord 'a' + val - 1)+    -- Passthrough is hard to get right, because pandoc's RawInline needs+    -- a format specifier. Often in asciidoc passthrough is used as a form+    -- of escaping, so the best approach seems to be treating it as HTML+    -- and parsing it:+    A.Passthrough t -> do+      case runPure (readHtml def{+                               readerExtensions = extensionsFromList [Ext_raw_html]+                               } t) of+        Left _ -> pure $ B.rawInline "html" t+        Right (Pandoc _ bs) -> pure $ B.fromList . blocksToInlines $ bs++monospaceStr :: Inline -> Inline+monospaceStr (Str t) = Code B.nullAttr t+monospaceStr x = x
src/Text/Pandoc/Readers/BibTeX.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Readers.BibTeX-   Copyright   : Copyright (C) 2020-2023 John MacFarlane+   Copyright   : Copyright (C) 2020-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>
src/Text/Pandoc/Readers/CSV.hs view
@@ -3,7 +3,7 @@ {-# LANGUAGE ScopedTypeVariables #-} {- |    Module      : Text.Pandoc.Readers.CSV-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -25,6 +25,7 @@ import Text.Pandoc.Options (ReaderOptions) import Control.Monad.Except (throwError) import Data.Text (Text)+import Data.List (intersperse) import Text.Pandoc.Parsing (fromParsecError)  readCSV :: (PandocMonad m, ToSources a)@@ -60,7 +61,8 @@                                              (TableFoot nullAttr [])        where capt = B.emptyCaption              numcols = length r-             toplain = B.simpleCell . B.plain . B.text . T.strip+             toplain = B.simpleCell . B.plain . mconcat .+                       intersperse B.linebreak . map B.text . T.lines              toRow = Row nullAttr . map toplain              toHeaderRow l = [toRow l | not (null l)]              hdrs = toHeaderRow r
src/Text/Pandoc/Readers/CommonMark.hs view
@@ -3,7 +3,7 @@ {-# LANGUAGE ScopedTypeVariables #-} {- |    Module      : Text.Pandoc.Readers.CommonMark-   Copyright   : Copyright (C) 2015-2023 John MacFarlane+   Copyright   : Copyright (C) 2015-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -71,7 +71,8 @@     readCommonMarkBody opts sources toks  makeFigures :: Block -> Block-makeFigures (Para [Image (ident,classes,kvs) alt (src,tit)]) =+makeFigures (Para [Image (ident,classes,kvs) alt (src,tit)])+  | not (null alt) =   Figure (ident,[],[])     (Caption Nothing [Plain alt])     [Plain [Image ("",classes,kvs) alt (src,tit)]]@@ -119,8 +120,10 @@ handleGfmMath x = walk handleGfmMathInline x  handleGfmMathInline :: Inline -> Inline-handleGfmMathInline (Math InlineMath math') =-  let (ticks, rest) = T.span (== '`') math'+handleGfmMathInline (Math InlineMath math'') =+  let math' = T.replace "\\\\{" "\\{" . T.replace "\\\\}" "\\}" $ math''+              -- see #10631+      (ticks, rest) = T.span (== '`') math'   in  if T.null ticks          then Math InlineMath math'          else case T.stripSuffix ticks rest of
src/Text/Pandoc/Readers/CslJson.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Readers.CslJson-   Copyright   : Copyright (C) 2020-2023 John MacFarlane+   Copyright   : Copyright (C) 2020-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>
src/Text/Pandoc/Readers/Djot.hs view
@@ -37,7 +37,6 @@ import Text.Pandoc.Emoji (emojiToInline) import Control.Monad.Reader import qualified Data.Foldable as F-import Data.List (foldl') import Data.ByteString (ByteString) -- import Debug.Trace @@ -141,7 +140,7 @@                      (hs,bs):rs -> (hs,row:bs):rs                      [] -> [([],[row])]       let reverseSnd (as,bs) = (as,reverse bs)-      let bodies = reverse $ map reverseSnd $ foldl' getBody [] rest+      let bodies = reverse $ map reverseSnd $ F.foldl' getBody [] rest       let toCell (D.Cell _ al ils) =             Cell nullAttr (toAlign al) (RowSpan 1) (ColSpan 1)                    . (\is -> [Para $ toList is]) <$> convertInlines ils@@ -186,10 +185,10 @@ convertInline :: PandocMonad m => D.Node D.Inline -> ReaderT Env m Inlines convertInline (D.Node pos attr il) = addAttrToInline pos attr <$>   case il of-    D.Str bs -> pure $ str (UTF8.toText bs)+    D.Str bs -> pure $ text (UTF8.toText bs)     D.Emph ils -> emph <$> convertInlines ils     D.Strong ils -> strong <$> convertInlines ils-    D.Highlight ils -> spanWith ("",["highlighted"],[]) <$> convertInlines ils+    D.Highlight ils -> spanWith ("",["mark"],[]) <$> convertInlines ils     D.Insert ils -> spanWith ("",["inserted"],[]) <$> convertInlines ils     D.Delete ils -> spanWith ("",["deleted"],[]) <$> convertInlines ils     D.Subscript ils -> subscript <$> convertInlines ils
src/Text/Pandoc/Readers/DocBook.hs view
@@ -4,7 +4,7 @@ {-# LANGUAGE TemplateHaskell #-} {- |    Module      : Text.Pandoc.Readers.DocBook-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -15,6 +15,7 @@ -} module Text.Pandoc.Readers.DocBook ( readDocBook ) where import Control.Monad (MonadPlus(mplus))+import Control.Applicative () import Control.Monad.State.Strict     ( MonadTrans(lift),       StateT(runStateT),@@ -25,6 +26,7 @@ import Data.FileEmbed import Data.Char (isSpace, isLetter, chr) import Data.Default+import Data.List.Split (splitWhen) import Data.Either (rights) import Data.Foldable (asum) import Data.Generics@@ -44,12 +46,14 @@ import Text.Pandoc.Class.PandocMonad (PandocMonad, report) import Text.Pandoc.Options import Text.Pandoc.Logging (LogMessage(..))-import Text.Pandoc.Shared (safeRead, extractSpaces, headerShift)+import Text.Pandoc.Shared (safeRead, addPandocAttributes) import Text.Pandoc.Sources (ToSources(..), sourcesToText)+import Text.Pandoc.Transforms (headerShift) import Text.TeXMath (readMathML, writeTeX) import qualified Data.Map as M import Text.Pandoc.XML.Light import Text.Pandoc.Walk (query)+import Text.Read (readMaybe)  {- @@ -169,7 +173,7 @@ [ ] errorname - An error name [ ] errortext - An error message. [ ] errortype - The classification of an error message-[ ] example - A formal example, with a title+[x] example - A formal example, with a title [ ] exceptionname - The name of an exception [ ] fax - A fax number [ ] fieldsynopsis - The name of a field in a class definition@@ -434,7 +438,7 @@ [ ] shortaffil - A brief description of an affiliation [ ] shortcut - A key combination for an action that is also accessible through     a menu-[ ] sidebar - A portion of a document that is isolated from the main+[x] sidebar - A portion of a document that is isolated from the main     narrative flow [ ] sidebarinfo - Meta-information for a Sidebar [x] simpara - A paragraph that contains only text and inline markup, no block@@ -538,11 +542,13 @@  type DB m = StateT DBState m -data DBState = DBState{ dbSectionLevel :: Int-                      , dbQuoteType    :: QuoteType-                      , dbMeta         :: Meta-                      , dbBook         :: Bool-                      , dbContent      :: [Content]+data DBState = DBState{ dbSectionLevel  :: Int+                      , dbQuoteType     :: QuoteType+                      , dbMeta          :: Meta+                      , dbBook          :: Bool+                      , dbContent       :: [Content]+                      , dbLiteralLayout :: Bool+                      , dbElementStack  :: [Text]                       } deriving Show  instance Default DBState where@@ -550,7 +556,10 @@                , dbQuoteType = DoubleQuote                , dbMeta = mempty                , dbBook = False-               , dbContent = [] }+               , dbContent = []+               , dbLiteralLayout = False+               , dbElementStack = []+               }   readDocBook :: (PandocMonad m, ToSources a)@@ -615,9 +624,13 @@ --  addMetadataFromElement :: PandocMonad m => Element -> DB m Blocks-addMetadataFromElement e =-  mempty <$ mapM_ handleMetadataElement+addMetadataFromElement e = do+  -- Add metadata if at root or appropriate parent element+  elementStack <- gets dbElementStack+  if take 1 elementStack `elem` [[], ["book"], ["article"]]+    then mempty <$ mapM_ handleMetadataElement                   (filterChildren ((isMetadataField . qName . elName)) e)+    else return mempty  where   handleMetadataElement elt =     case qName (elName elt) of@@ -718,9 +731,7 @@   , "articleinfo"   , "attribution"   , "authorinitials"-  , "bibliodiv"   , "biblioentry"-  , "bibliography"   , "bibliomisc"   , "bibliomixed"   , "blockquote"@@ -759,31 +770,19 @@   , "preface"   , "procedure"   , "programlisting"-  , "qandadiv"   , "question"-  , "refsect1"   , "refsect1info"-  , "refsect2"   , "refsect2info"-  , "refsect3"   , "refsect3info"-  , "refsection"   , "refsectioninfo"   , "screen"-  , "sect1"   , "sect1info"-  , "sect2"   , "sect2info"-  , "sect3"   , "sect3info"-  , "sect4"   , "sect4info"-  , "sect5"   , "sect5info"-  , "section"   , "sectioninfo"   , "simpara"-  , "simplesect"   , "substeps"   , "subtitle"   , "table"@@ -791,11 +790,20 @@   , "titleabbrev"   , "toc"   , "variablelist"-  ] ++ admonitionTags+  ] ++ sectionTags ++ admonitionTags +sectionTags :: [Text]+sectionTags = ["bibliography", "bibliodiv"+              , "sect1", "sect2", "sect3", "sect4", "sect5", "section", "simplesect"+              , "refsect1", "refsect2", "refsect3", "refsection", "qandadiv"+              ]+ admonitionTags :: [Text] admonitionTags = ["caution","danger","important","note","tip","warning"] +titledBlockElements :: [Text]+titledBlockElements = ["example", "formalpara", "sidebar"]+ -- Trim leading and trailing newline characters trimNl :: Text -> Text trimNl = T.dropAround (== '\n')@@ -844,9 +852,16 @@   fmap (imageWith attr imageUrl tit) capt  getBlocks :: PandocMonad m => Element -> DB m Blocks-getBlocks e =  mconcat <$>-                 mapM parseBlock (elContent e)+getBlocks e = do+  modify (\st -> st{ dbElementStack = qName (elName e) : dbElementStack st })+  blocks <- mconcat <$> mapM parseBlock (elContent e)+  modify (\st -> st{ dbElementStack = drop 1 $ dbElementStack st })+  return blocks +getRoleAttr :: Element -> [(Text, Text)] -- extract role attribute and add it to the attribute list+getRoleAttr e = case attrValue "role" e of+                  "" -> []+                  r  -> [("role", r)]  parseBlock :: PandocMonad m => Content -> DB m Blocks parseBlock (Text (CData CDataRaw _ _)) = return mempty -- DOCTYPE@@ -854,21 +869,15 @@                                      then return mempty                                      else return $ plain $ trimInlines $ text s parseBlock (CRef x) = return $ plain $ str $ T.toUpper x-parseBlock (Elem e) =-  case qName (elName e) of+parseBlock (Elem e) = do+  parsedBlock <- case qName (elName e) of         "toc"   -> skip -- skip TOC, since in pandoc it's autogenerated         "index" -> skip -- skip index, since page numbers meaningless         "para"  -> parseMixed para (elContent e)-        "formalpara" -> do-           tit <- case filterChild (named "title") e of-                        Just t  -> divWith ("",["formalpara-title"],[]) .-                                   para .  strong <$> getInlines t-                        Nothing -> return mempty-           (tit <>) <$> parseMixed para (elContent e)         "simpara"  -> parseMixed para (elContent e)         "ackno"  -> parseMixed para (elContent e)         "epigraph" -> parseBlockquote-        "blockquote" -> parseBlockquote+        "blockquote" -> withOptionalTitle parseBlockquote         "attribution" -> skip         "titleabbrev" -> skip         "authorinitials" -> skip@@ -881,7 +890,8 @@         "bibliomisc" -> parseMixed para (elContent e)         "bibliomixed" -> parseMixed para (elContent e)         "equation"         -> para <$> equation e displayMath-        "informalequation" -> para <$> equation e displayMath+        "informalequation" -> divWith (attrValue "id" e,["informalequation"],[]) .+                              para <$> equation e displayMath         "glosssee" -> para . (\ils -> text "See " <> ils <> str ".")                          <$> getInlines e         "glossseealso" -> para . (\ils -> text "See also " <> ils <> str ".")@@ -909,7 +919,8 @@         "refsect2" -> sect 2         "refsect3" -> sect 3         "refsection" -> gets dbSectionLevel >>= sect . (+1)-        l | l `elem` admonitionTags -> parseAdmonition l+        l | l `elem` titledBlockElements -> parseAdmonition False l+        l | l `elem` admonitionTags -> parseAdmonition True l         "area" -> skip         "areaset" -> skip         "areaspec" -> skip@@ -917,9 +928,10 @@         "question" -> addToStart (strong (str "Q:") <> str " ") <$> getBlocks e         "answer" -> addToStart (strong (str "A:") <> str " ") <$> getBlocks e         "abstract" -> blockQuote <$> getBlocks e-        "calloutlist" -> bulletList <$> callouts-        "itemizedlist" -> bulletList . handleCompact <$> listitems-        "orderedlist" -> do+        "calloutlist" -> withOptionalTitle $ bulletList <$> callouts+        "itemizedlist" -> withOptionalTitle $+                            bulletList . handleCompact <$> listitems+        "orderedlist" -> withOptionalTitle $ do           let listStyle = case attrValue "numeration" e of                                "arabic"     -> Decimal                                "loweralpha" -> LowerAlpha@@ -927,9 +939,7 @@                                "lowerroman" -> LowerRoman                                "upperroman" -> UpperRoman                                _            -> Decimal-          let start = fromMaybe 1 $-                      filterElement (named "listitem") e-                       >>= safeRead . attrValue "override"+          let start = fromMaybe 1 $ safeRead $ attrValue "startingnumber" e           orderedListWith (start,listStyle,DefaultDelim) . handleCompact             <$> listitems         "variablelist" -> definitionList <$> deflistitems@@ -965,13 +975,16 @@         "informalexample" -> divWith ("", ["informalexample"], []) <$>                              getBlocks e         "linegroup" -> lineBlock <$> lineItems-        "literallayout" -> codeBlockWithLang+        "literallayout" -> literalLayout         "screen" -> codeBlockWithLang         "programlisting" -> codeBlockWithLang         "?xml"  -> return mempty         "title" -> return mempty     -- handled in parent element         "subtitle" -> return mempty  -- handled in parent element         _ -> skip >> getBlocks e+  if qName (elName e) `elem` sectionTags+     then return parsedBlock+     else return $ addPandocAttributes (getRoleAttr e) parsedBlock    where skip = do            let qn = qName $ elName e            let name = if "pi-" `T.isPrefixOf` qn@@ -980,6 +993,7 @@            lift $ report $ IgnoredElement name            return mempty +          compactSpacing = case attrValue "spacing" e of                             "compact" -> True                             _         -> False@@ -988,6 +1002,17 @@                             then map (fmap paraToPlain)                             else id +         literalLayout+           | "monospaced" `elem` (T.words (attrValue "class" e))+               = codeBlockWithLang+           | otherwise = do+               oldLiteralLayout <- gets dbLiteralLayout+               modify $ \st -> st{ dbLiteralLayout = True }+               content <- mconcat <$> mapM parseInline (elContent e)+               let ls = map fromList . splitWhen (== LineBreak) . toList $ content+               modify $ \st -> st{ dbLiteralLayout = oldLiteralLayout }+               return $ lineBlock ls+          codeBlockWithLang = do            let classes' = case attrValue "language" e of                                 "" -> []@@ -1021,6 +1046,11 @@                      items' <- mapM getBlocks items                      return (mconcat $ intersperse (str "; ") terms', items')          parseTable = do+                      let elId = attrValue "id" e+                      let attrs = case attrValue "tabstyle" e of+                                    "" -> []+                                    x  -> [("custom-style", x)]+                      let classes = T.words $ attrValue "class" e                       let isCaption x = named "title" x || named "caption" x                       capt <- case filterChild isCaption e of                                     Just t  -> getInlines t@@ -1035,9 +1065,8 @@                                        cs -> mapMaybe (findAttr (unqual "colname" )) cs                       let isRow x = named "row" x || named "tr" x                       headrows <- case filterChild (named "thead") e' of-                                       Just h  -> case filterChild isRow h of-                                                       Just x  -> parseRow colnames x-                                                       Nothing -> return []+                                       Just h  -> mapM (parseRow colnames)+                                                  $ filterChildren isRow h                                        Nothing -> return []                       bodyrows <- case filterChild (named "tbody") e' of                                        Just b  -> mapM (parseRow colnames)@@ -1051,7 +1080,7 @@                                                       || x == '.') w                             if n > 0 then Just n else Nothing                       let numrows = maybe 0 maximum $ nonEmpty-                                                    $ map length bodyrows+                                                    $ map length (bodyrows ++ headrows)                       let aligns = case colspecs of                                      [] -> replicate numrows AlignDefault                                      cs -> map toAlignment cs@@ -1073,10 +1102,10 @@                                                             in  ColWidth . scale <$> ws'                                                 Nothing  -> replicate numrows ColWidthDefault                       let toRow = Row nullAttr-                          toHeaderRow l = [toRow l | not (null l)]-                      return $ table (simpleCaption $ plain capt)+                      return $ tableWith (elId,classes,attrs)+                                     (simpleCaption $ plain capt)                                      (zip aligns widths)-                                     (TableHead nullAttr $ toHeaderRow headrows)+                                     (TableHead nullAttr $ map toRow headrows)                                      [TableBody nullAttr 0 [] $ map toRow bodyrows]                                      (TableFoot nullAttr [])          sect n = sectWith(attrValue "id" e) [] [] n@@ -1091,7 +1120,10 @@            modify $ \st -> st{ dbSectionLevel = n }            b <- getBlocks e            modify $ \st -> st{ dbSectionLevel = n - 1 }-           return $ headerWith (elId, classes, maybeToList titleabbrevElAsAttr++attrs) n' headerText <> b+           let hdr = addPandocAttributes (getRoleAttr e)+                        $ headerWith (elId, classes, maybeToList titleabbrevElAsAttr ++ attrs)+                                      n' headerText+           return $ hdr <> b          titleabbrevElAsAttr =            case filterChild (named "titleabbrev") e `mplus`                 (filterChild (named "info") e >>=@@ -1099,23 +1131,37 @@              Just t  -> Just ("titleabbrev", strContentRecursive t)              Nothing -> Nothing          lineItems = mapM getInlines $ filterChildren (named "line") e++         -- <title> elements can be directly nested inside an admonition block, use+         -- it if it's there. It is unclear whether we should include the label in+         -- the title: docbook references are ambiguous on that, and some implementations of admonitions+         -- (e.g. asciidoctor) just use an icon in all cases. To be conservative, we don't+         -- include the label and leave it to styling.+         --+         getTitle = case filterChild (named "title") e of+                        Just t  -> Just <$> getInlines t+                        Nothing -> return Nothing+         withOptionalTitle p = do+           mbt <- getTitle+           b <- p+           case mbt of+             Nothing -> return b+             Just t -> return $ divWith (attrValue "id" e, [], getRoleAttr e)+                         (divWith ("", ["title"], []) (plain t) <> b)+          -- Admonitions are parsed into a div. Following other Docbook tools that output HTML,          -- we parse the optional title as a div with the @title@ class, and give the          -- block itself a class corresponding to the admonition name.-         parseAdmonition label = do-           -- <title> elements can be directly nested inside an admonition block, use-           -- it if it's there. It is unclear whether we should include the label in-           -- the title: docbook references are ambiguous on that, and some implementations of admonitions-           -- (e.g. asciidoctor) just use an icon in all cases. To be conservative, we don't-           -- include the label and leave it to styling.-           title <- divWith ("", ["title"], []) . plain <$>-                    case filterChild (named "title") e of-                        Just t  -> getInlines t-                        Nothing -> return mempty-           -- this will ignore the title element if it is present+         parseAdmonition alwaysIncludeTitle label = do+           mbt <- getTitle+           -- this will ignore the title element if it is present:            b <- getBlocks e+           let t = maybe mempty (divWith ("", ["title"], []) . plain)+                        (case mbt of+                           Nothing | alwaysIncludeTitle -> Just mempty+                           _ -> mbt)            -- we also attach the label as a class, so it can be styled properly-           return $ divWith (attrValue "id" e,[label],[]) (title <> b)+           return $ divWith (attrValue "id" e,[label],[]) (t <> b)  toAlignment :: Element -> Alignment toAlignment c = case findAttr (unqual "align") c of@@ -1139,7 +1185,7 @@  parseRow :: PandocMonad m => [Text] -> Element -> DB m [Cell] parseRow cn = do-  let isEntry x  = named "entry" x || named "td" x || named "th" x+  let isEntry x = named "entry" x || named "td" x || named "th" x   mapM (parseEntry cn) . filterChildren isEntry  parseEntry :: PandocMonad m => [Text] -> Element -> DB m Cell@@ -1156,9 +1202,18 @@         case (mStrt, mEnd) of           (Just start, Just end) -> colDistance start end           _ -> 1+  let rowDistance mr = do+        case readMaybe $ T.unpack mr :: Maybe Int of+          Just moreRow -> RowSpan $ moreRow + 1+          _ -> 1+  let toRowSpan en = do+        case findAttr (unqual "morerows") en of+          Just moreRow -> rowDistance moreRow+          _ -> 1   let colSpan = toColSpan el+  let rowSpan = toRowSpan el   let align = toAlignment el-  (fmap (cell align 1 colSpan) . parseMixed plain . elContent) el+  (fmap (cell align rowSpan colSpan) . parseMixed plain . elContent) el  getInlines :: PandocMonad m => Element -> DB m Inlines getInlines e' = trimInlines . mconcat <$>@@ -1184,11 +1239,18 @@         _ -> Just (n, attrValue n e)  parseInline :: PandocMonad m => Content -> DB m Inlines-parseInline (Text (CData _ s _)) = return $ text s+parseInline (Text (CData _ s _)) = do+  literalLayout <- gets dbLiteralLayout+  if literalLayout+     then do+       let ls = T.splitOn "\n" s+       let toLiteralLine = str . T.map (\c -> if c == ' ' then '\xa0' else c)+       return $ mconcat $ intersperse linebreak $ map toLiteralLine ls+     else return $ text s parseInline (CRef ref) =   return $ text $ fromMaybe (T.toUpper ref) $ lookupEntity ref-parseInline (Elem e) =-  case qName (elName e) of+parseInline (Elem e) = do+  parsedInline <- case qName (elName e) of         "anchor" -> do            return $ spanWith (attrValue "id" e, [], []) mempty         "phrase" -> do@@ -1310,6 +1372,9 @@         -- <?asciidor-br?> to in handleInstructions, above.         "pi-asciidoc-br" -> return linebreak         _          -> skip >> innerInlines id+  return $ case qName (elName e) of+    "emphasis" -> parsedInline+    _ -> addPandocAttributes (getRoleAttr e) parsedInline    where skip = do            let qn = qName $ elName e            let name = if "pi-" `T.isPrefixOf` qn@@ -1318,8 +1383,7 @@            lift $ report $ IgnoredElement name            return mempty -         innerInlines f = extractSpaces f . mconcat <$>-                          mapM parseInline (elContent e)+         innerInlines f = f . mconcat <$> mapM parseInline (elContent e)          codeWithLang = do            let classes' = case attrValue "language" e of                                "" -> []
src/Text/Pandoc/Readers/Docx.hs view
@@ -2,6 +2,7 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE PatternGuards     #-} {-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE LambdaCase        #-} {-# LANGUAGE ViewPatterns      #-} {- |    Module      : Text.Pandoc.Readers.Docx@@ -73,15 +74,16 @@ import Data.Bifunctor (bimap, first) import qualified Data.ByteString.Lazy as B import Data.Default (Default)-import Data.List (delete, intersect, foldl')+import Data.List (delete, intersect)+import qualified Data.List as L import Data.Char (isSpace) import qualified Data.Map as M import qualified Data.Text as T-import Data.Maybe (catMaybes, isJust, fromMaybe, mapMaybe)+import Data.Maybe (isJust, fromMaybe, mapMaybe) import Data.Sequence (ViewL (..), viewl) import qualified Data.Sequence as Seq import qualified Data.Set as Set-import Citeproc (ItemId(..), Reference(..), CitationItem(..))+import Citeproc (ItemId(..), Val(TextVal,FancyVal), Reference(..), CitationItem(..)) import qualified Citeproc import Text.Pandoc.Builder as Pandoc import Text.Pandoc.MediaBag (MediaBag)@@ -92,7 +94,7 @@ import Text.Pandoc.Shared import Text.Pandoc.Walk import Text.TeXMath (writeTeX)-import Control.Monad.Except (throwError)+import Control.Monad.Except (throwError, catchError) import Text.Pandoc.Class.PandocMonad (PandocMonad) import qualified Text.Pandoc.Class.PandocMonad as P import Text.Pandoc.Error@@ -103,7 +105,6 @@ import Text.Pandoc.UTF8 (fromTextLazy) import Text.Pandoc.Citeproc.MetaValue (referenceToMetaValue) import Text.Pandoc.Readers.EndNote (readEndNoteXMLCitation)-import Text.Pandoc.Sources (toSources)  readDocx :: PandocMonad m          => ReaderOptions@@ -132,7 +133,6 @@                      -- restarting                      , docxListState :: M.Map (T.Text, T.Text) Integer                      , docxPrevPara  :: Inlines-                     , docxTableCaptions :: [Blocks]                      , docxReferences :: M.Map ItemId (Reference Inlines)                      } @@ -145,7 +145,6 @@                , docxDropCap   = mempty                , docxListState = M.empty                , docxPrevPara  = mempty-               , docxTableCaptions = []                , docxReferences = mempty                } @@ -203,6 +202,8 @@     inlines <- smushInlines <$> mapM parPartToInlines parParts     remaining <- bodyPartsToMeta' bps     let+      -- for titles, we just take the first one and ignore the rest, #10359:+      f _ x | metaField == "title" || metaField == "subtitle" = x       f (MetaInlines ils) (MetaInlines ils') = MetaBlocks [Para ils, Para ils']       f (MetaInlines ils) (MetaBlocks blks) = MetaBlocks (Para ils : blks)       f m (MetaList mv) = MetaList (m : mv)@@ -305,7 +306,8 @@             emph . go rPr{isItalic = Nothing, isItalicCTL = Nothing}         | Just True <- bold rPr =             strong . go rPr{isBold = Nothing, isBoldCTL = Nothing}-        | Just _ <- rHighlight rPr =+        | Just v <- rHighlight rPr+        , v /= "none" =             spanWith ("",["mark"],[]) . go rPr{rHighlight = Nothing}         | Just True <- isSmallCaps rPr =             smallcaps . go rPr{isSmallCaps = Nothing}@@ -357,9 +359,10 @@ blocksToInlinesWarn :: PandocMonad m => T.Text -> Blocks -> DocxContext m Inlines blocksToInlinesWarn cmtId blks = do   let paraOrPlain :: Block -> Bool-      paraOrPlain (Para _)  = True-      paraOrPlain (Plain _) = True-      paraOrPlain _         = False+      paraOrPlain (Para _)       = True+      paraOrPlain (Plain _)      = True+      paraOrPlain (Div _ nested) = all paraOrPlain nested+      paraOrPlain _              = False   unless (all paraOrPlain blks) $     lift $ P.report $ DocxParserWarning $       "Docx comment " <> cmtId <> " will not retain formatting"@@ -385,22 +388,22 @@  parPartToInlines' :: PandocMonad m => ParPart -> DocxContext m Inlines parPartToInlines' (PlainRun r) = runToInlines r-parPartToInlines' (ChangedRuns (TrackedChange Insertion (ChangeInfo _ author date)) runs) = do+parPartToInlines' (ChangedRuns (TrackedChange Insertion (ChangeInfo _ author date)) pparts) = do   opts <- asks docxOptions   case readerTrackChanges opts of-    AcceptChanges -> smushInlines <$> mapM runToInlines runs+    AcceptChanges -> smushInlines <$> mapM parPartToInlines pparts     RejectChanges -> return mempty     AllChanges    -> do-      ils <- smushInlines <$> mapM runToInlines runs+      ils <- smushInlines <$> mapM parPartToInlines pparts       let attr = ("", ["insertion"], addAuthorAndDate author date)       return $ spanWith attr ils-parPartToInlines' (ChangedRuns (TrackedChange Deletion (ChangeInfo _ author date)) runs) = do+parPartToInlines' (ChangedRuns (TrackedChange Deletion (ChangeInfo _ author date)) pparts) = do   opts <- asks docxOptions   case readerTrackChanges opts of     AcceptChanges -> return mempty-    RejectChanges -> smushInlines <$> mapM runToInlines runs+    RejectChanges -> smushInlines <$> mapM parPartToInlines pparts     AllChanges    -> do-      ils <- smushInlines <$> mapM runToInlines runs+      ils <- smushInlines <$> mapM parPartToInlines pparts       let attr = ("", ["deletion"], addAuthorAndDate author date)       return $ spanWith attr ils parPartToInlines' (CommentStart cmtId author date bodyParts) = do@@ -439,11 +442,10 @@     -- avoid an extra pass.     immedPrevAnchor <- gets docxImmedPrevAnchor     case immedPrevAnchor of-      Just prevAnchor -> do-        unless inHdrBool-          (modify $ \s -> s { docxAnchorMap = M.insert anchor prevAnchor anchorMap})+      Just prevAnchor | not inHdrBool -> do+        (modify $ \s -> s { docxAnchorMap = M.insert anchor prevAnchor anchorMap})         return mempty-      Nothing -> do+      _ -> do         exts <- asks (readerExtensions . docxOptions)         let newAnchor =               if not inHdrBool && anchor `elem` M.elems anchorMap@@ -473,15 +475,29 @@ parPartToInlines' (Field info children) =   case info of     HyperlinkField url -> parPartToInlines' $ ExternalHyperLink url children+    IndexrefField ie ->+      pure $ spanWith ("",["indexref"],+                           (("entry", entryTitle ie) :+                             maybe [] (\x -> [("crossref",x)]) (entrySee ie)+                          ++ maybe [] (\x -> [("yomi",x)]) (entryYomi ie)+                          ++ [("bold","") | entryBold ie]+                          ++ [("italic","") | entryItalic ie])) mempty     PagerefField fieldAnchor True -> parPartToInlines' $ InternalHyperLink fieldAnchor children+    CrossrefField fieldAnchor True -> parPartToInlines' $ InternalHyperLink fieldAnchor children     EndNoteCite t -> do       formattedCite <- smushInlines <$> mapM parPartToInlines' children       opts <- asks docxOptions       if isEnabled Ext_citations opts-         then do-           citation <- readEndNoteXMLCitation (toSources t)-           cs <- handleCitation citation-           return $ cite cs formattedCite+         then catchError+              (do citation <- readEndNoteXMLCitation t+                  cs <- handleCitation citation+                  return $ cite cs formattedCite)+              (\case+                  PandocXMLError _ msg -> do+                    P.report $ DocxParserWarning+                             ("Cannot parse EndNote citation: " <> msg)+                    return formattedCite+                  e -> throwError e)          else return formattedCite     CslCitation t -> do       formattedCite <- smushInlines <$> mapM parPartToInlines' children@@ -507,14 +523,26 @@          else smushInlines <$> mapM parPartToInlines' children     _ -> smushInlines <$> mapM parPartToInlines' children +-- Helper function to convert CitationItemType to CitationMode+convertCitationMode :: Citeproc.CitationItemType -> CitationMode+convertCitationMode itemType = case itemType of+                                 Citeproc.NormalCite -> NormalCitation+                                 Citeproc.SuppressAuthor -> SuppressAuthor+                                 Citeproc.AuthorOnly -> AuthorInText+ -- Turn a 'Citeproc.Citation' into a list of 'Text.Pandoc.Definition.Citation', -- and store the embedded bibliographic data in state. handleCitation :: PandocMonad m                => Citeproc.Citation T.Text                -> DocxContext m [Citation] handleCitation citation = do+  let getItemId item =+        case citationItemData item >>= M.lookup "citation-key" . referenceVariables of+          Just (TextVal k) -> ItemId k+          Just (FancyVal k) -> ItemId k+          _ -> citationItemId item   let toPandocCitation item =-        Citation{ citationId = unItemId (Citeproc.citationItemId item)+        Citation{ citationId = unItemId (getItemId item)                 , citationPrefix = maybe [] (toList . text) $                                      Citeproc.citationItemPrefix item                 , citationSuffix = (toList . text) $@@ -523,13 +551,16 @@                          <> x <> " ")                      (Citeproc.citationItemLocator item)                     <> fromMaybe mempty (Citeproc.citationItemSuffix item)-                , citationMode = NormalCitation -- TODO for now+                , citationMode = convertCitationMode (Citeproc.citationItemType item)                 , citationNoteNum = 0                 , citationHash = 0 }   let items = Citeproc.citationItems citation   let cs = map toPandocCitation items-  refs <- mapM (traverse (return . text)) $-            mapMaybe Citeproc.citationItemData items+  let refs = mapMaybe (\item -> fmap (\itemData -> text <$>+                                        -- see #10366, sometimes itemData has a different+                                        -- id and we need to use the same one:+                                        itemData{ referenceId = getItemId item })+                                  (Citeproc.citationItemData item)) items   modify $ \st ->     st{ docxReferences = foldr           (\ref -> M.insert (referenceId ref) ref)@@ -537,7 +568,6 @@           refs }   return cs - isAnchorSpan :: Inline -> Bool isAnchorSpan (Span (_, ["anchor"], []) _) = True isAnchorSpan _ = False@@ -585,10 +615,11 @@ singleParaToPlain blks = blks  cellToCell :: PandocMonad m => RowSpan -> Docx.Cell -> DocxContext m Pandoc.Cell-cellToCell rowSpan (Docx.Cell gridSpan _ bps) = do+cellToCell rowSpan (Docx.Cell align gridSpan _ bps) = do   blks <- smushBlocks <$> mapM bodyPartToBlocks bps   let blks' = singleParaToPlain $ fromList $ blocksToDefinitions $ blocksToBullets $ toList blks-  return (cell AlignDefault rowSpan (ColSpan (fromIntegral gridSpan)) blks')+  return (cell (convertAlign align)+          rowSpan (ColSpan (fromIntegral gridSpan)) blks')  rowsToRows :: PandocMonad m => [Docx.Row] -> DocxContext m [Pandoc.Row] rowsToRows rows = do@@ -599,8 +630,8 @@ splitHeaderRows :: Bool -> [Docx.Row] -> ([Docx.Row], [Docx.Row]) splitHeaderRows hasFirstRowFormatting rs = bimap reverse reverse $ fst   $ if hasFirstRowFormatting-    then foldl' f ((take 1 rs, []), True) (drop 1 rs)-    else foldl' f (([], []), False) rs+    then L.foldl' f ((take 1 rs, []), True) (drop 1 rs)+    else L.foldl' f (([], []), False) rs   where     f ((headerRows, bodyRows), previousRowWasHeader) r@(Docx.Row h cs)       | h == HasTblHeader || (previousRowWasHeader && any isContinuationCell cs)@@ -608,7 +639,7 @@       | otherwise         = ((headerRows, r : bodyRows), False) -    isContinuationCell (Docx.Cell _ vm _) = vm == Docx.Continue+    isContinuationCell (Docx.Cell _ _ vm _) = vm == Docx.Continue   -- like trimInlines, but also take out linebreaks@@ -658,12 +689,35 @@   where go c | isSpace c = '-'              | otherwise = c -bodyPartToTableCaption :: PandocMonad m => BodyPart -> DocxContext m (Maybe Blocks)-bodyPartToTableCaption (TblCaption pPr parparts) =-  Just <$> bodyPartToBlocks (Paragraph pPr parparts)-bodyPartToTableCaption _ = pure Nothing- bodyPartToBlocks :: PandocMonad m => BodyPart -> DocxContext m Blocks+bodyPartToBlocks (Heading n style pPr numId lvl mblvlInfo parparts) = do+    ils <- local (\s-> s{docxInHeaderBlock=True})+           (smushInlines <$> mapM parPartToInlines parparts)+    let classes = map normalizeToClassName . delete style+                $ getStyleNames (pStyle pPr)+    hasNumbering <- gets docxNumberedHeadings+    let addNum = if hasNumbering && not (numbered pPr)+                 then (++ ["unnumbered"])+                 else id+    if T.null numId+       then pure ()+       else do+         -- We check whether this current numId has previously been used,+         -- since Docx expects us to pick up where we left off.+         listState <- gets docxListState+         let start = case M.lookup (numId, lvl) listState of+                       Nothing -> case mblvlInfo of+                         Nothing -> 1+                         Just (Level _ _ _ z) -> fromMaybe 1 z+                       Just z -> z + 1+         modify $ \st -> st{ docxListState =+             -- expire all the continuation data for lists of level > this one:+             -- a new level 1 list item resets continuation for level 2++             -- see #10258+             let notExpired (_, lvl') _ = lvl' <= lvl+             in M.insert (numId, lvl) start+                  (M.filterWithKey notExpired listState) }+    makeHeaderAnchor $ headerWith ("", addNum classes, []) n ils bodyPartToBlocks (Paragraph pPr parparts)   | Just True <- pBidi pPr = do       let pPr' = pPr { pBidi = Nothing }@@ -676,18 +730,6 @@         codeBlock $         T.concat $         map parPartToText parparts-  | Just (style, n) <- pHeading pPr = do-    ils <- local (\s-> s{docxInHeaderBlock=True})-           (smushInlines <$> mapM parPartToInlines parparts)-    let classes = map normalizeToClassName . delete style-                $ getStyleNames (pStyle pPr)--    hasNumbering <- gets docxNumberedHeadings-    let addNum = if hasNumbering && not (numbered pPr)-                 then (++ ["unnumbered"])-                 else id-    makeHeaderAnchor $-      headerWith ("", addNum classes, []) n ils   | otherwise = do     ils <- trimSps . smushInlines <$> mapM parPartToInlines parparts     prevParaIls <- gets docxPrevPara@@ -761,40 +803,58 @@   let pPr' = pPr {pStyle = constructBogusParStyleData "list-paragraph": pStyle pPr}   in     bodyPartToBlocks $ Paragraph pPr' parparts-bodyPartToBlocks (TblCaption _ _) =-  return mempty-bodyPartToBlocks (Tbl _ _ _ []) =+bodyPartToBlocks (Captioned parstyle parparts bpart) = do+  bs <- bodyPartToBlocks bpart+  captContents <- bodyPartToBlocks (Paragraph parstyle parparts)+  let capt = Caption Nothing (toList captContents)+  let toCaptioned attr' bls = case bls of+        [Table attr _cap colspecs thead tbodies tfoot]+          -> singleton $ Table (attr <> attr') capt colspecs thead tbodies tfoot+        [Figure attr _cap blks]+          -> singleton $ Figure (attr <> attr') capt blks+        [Para im@[Image{}]]+          -> singleton $ Figure attr' capt [Plain im]+        [Div attr bls']+          -> toCaptioned (attr <> attr') bls'+        [BlockQuote bls']+          -> toCaptioned attr' bls'+        _ -> captContents+  pure $ toCaptioned nullAttr (toList bs)+bodyPartToBlocks (Tbl _ _ _ _ []) =   return mempty-bodyPartToBlocks (Tbl cap grid look parts) = do-  captions <- gets docxTableCaptions-  fullCaption <- case captions of-    c : cs -> do-      modify (\s -> s { docxTableCaptions = cs })-      return c-    [] -> return $ if T.null cap then mempty else plain (text cap)+bodyPartToBlocks (Tbl mbsty cap grid look parts) = do+  let fullCaption = if T.null cap then mempty else plain (text cap)   let shortCaption = if T.null cap then Nothing else Just (toList (text cap))       cap' = caption shortCaption fullCaption       (hdr, rows) = splitHeaderRows (firstRowFormatting look) parts    let width = maybe 0 maximum $ nonEmpty $ map rowLength parts       rowLength :: Docx.Row -> Int-      rowLength (Docx.Row _ c) = sum (fmap (\(Docx.Cell gridSpan _ _) -> fromIntegral gridSpan) c)+      rowLength (Docx.Row _ c) = sum (fmap (\(Docx.Cell _ gridSpan _ _) -> fromIntegral gridSpan) c)    headerCells <- rowsToRows hdr   bodyCells <- rowsToRows rows -      -- Horizontal column alignment goes to the default at the moment. Getting-      -- it might be difficult, since there doesn't seem to be a column entity-      -- in docx.-  let alignments = replicate width AlignDefault-      totalWidth = sum grid-      widths = (\w -> ColWidth (fromInteger w / fromInteger totalWidth)) <$> grid+      -- Horizontal column alignment is taken from the first row's cells.+  let getAlignment (Docx.Cell al colspan _ _) = replicate (fromIntegral colspan)+                   $ convertAlign al+      alignments = case rows of+                     [] -> replicate width Pandoc.AlignDefault+                     Docx.Row _ cs : _ -> concatMap getAlignment cs+      widths = map (\n -> if n == 0+                             then ColWidthDefault+                             else ColWidth n) grid -  return $ table cap'+  extStylesEnabled <- asks (isEnabled Ext_styles . docxOptions)+  let attr = case mbsty of+                Just sty | extStylesEnabled -> ("", [], [("custom-style", sty)])+                _ -> nullAttr+  return $ tableWith attr cap'                  (zip alignments widths)                  (TableHead nullAttr headerCells)                  [TableBody nullAttr 0 [] bodyCells]                  (TableFoot nullAttr [])+bodyPartToBlocks HRule = pure Pandoc.horizontalRule  -- replace targets with generated anchors. rewriteLink' :: PandocMonad m => Inline -> DocxContext m Inline@@ -831,11 +891,9 @@ bodyToOutput (Body bps) = do   let (metabps, blkbps) = sepBodyParts bps   meta <- bodyPartsToMeta metabps-  captions <- catMaybes <$> mapM bodyPartToTableCaption blkbps   let isNumberedPara (Paragraph pPr _) = numbered pPr       isNumberedPara _                 = False   modify (\s -> s { docxNumberedHeadings = any isNumberedPara blkbps })-  modify (\s -> s { docxTableCaptions = captions })   blks <- smushBlocks <$> mapM bodyPartToBlocks blkbps   blks' <- rewriteLinks $ blocksToDefinitions $ blocksToBullets $ toList blks   blks'' <- removeOrphanAnchors blks'@@ -856,3 +914,10 @@ addAuthorAndDate :: T.Text -> Maybe T.Text -> [(T.Text, T.Text)] addAuthorAndDate author mdate =   ("author", author) : maybe [] (\date -> [("date", date)]) mdate++convertAlign :: Docx.Align -> Pandoc.Alignment+convertAlign al = case al of+                       Docx.AlignDefault -> Pandoc.AlignDefault+                       Docx.AlignLeft -> Pandoc.AlignLeft+                       Docx.AlignCenter -> Pandoc.AlignCenter+                       Docx.AlignRight -> Pandoc.AlignRight
src/Text/Pandoc/Readers/Docx/Combine.hs view
@@ -2,7 +2,7 @@ {- |    Module      : Text.Pandoc.Readers.Docx.Combine    Copyright   : © 2014-2020 Jesse Rosenthal <jrosenthal@jhu.edu>,-                   2014-2023 John MacFarlane <jgm@berkeley.edu>,+                   2014-2024 John MacFarlane <jgm@berkeley.edu>,                    2020 Nikolay Yakimov <root@livid.pp.ru>    License     : GNU GPL, version 2 or above @@ -52,12 +52,13 @@  -} -module Text.Pandoc.Readers.Docx.Combine ( smushInlines+module Text.Pandoc.Readers.Docx.Combine ( combineBlocks+                                        , smushInlines                                         , smushBlocks                                         )        where -import Data.List+import qualified Data.List as L import Data.Bifunctor import Data.Sequence ( ViewL (..), ViewR (..), viewl, viewr, spanr, spanl                      , (><), (|>) )@@ -135,9 +136,9 @@ combineSingletonInlines x y =   let (xfs, xs) = unstackInlines x       (yfs, ys) = unstackInlines y-      shared = xfs `intersect` yfs-      x_remaining = xfs \\ shared-      y_remaining = yfs \\ shared+      shared = xfs `L.intersect` yfs+      x_remaining = xfs L.\\ shared+      y_remaining = yfs L.\\ shared       x_rem_attr = filter isAttrModifier x_remaining       y_rem_attr = filter isAttrModifier y_remaining   in@@ -182,7 +183,7 @@  smushInlines :: [Inlines] -> Inlines smushInlines xs = combineInlines xs' mempty-  where xs' = foldl' combineInlines mempty xs+  where xs' = L.foldl' combineInlines mempty xs  smushBlocks :: [Blocks] -> Blocks-smushBlocks xs = foldl' combineBlocks mempty xs+smushBlocks xs = L.foldl' combineBlocks mempty xs
src/Text/Pandoc/Readers/Docx/Fields.hs view
@@ -12,19 +12,31 @@ ECMA-376-1:2016, §17.16.5 -}  module Text.Pandoc.Readers.Docx.Fields ( FieldInfo(..)+                                       , IndexEntry(..)                                        , parseFieldInfo                                        ) where  import Data.Functor (($>), void) import qualified Data.Text as T import Text.Pandoc.Parsing+import Data.Maybe (isJust)  type URL = T.Text type Anchor = T.Text +data IndexEntry = IndexEntry+  { entryTitle :: T.Text+  , entrySee :: Maybe T.Text+  , entryYomi :: Maybe T.Text+  , entryBold :: Bool+  , entryItalic :: Bool }+  deriving (Show)+ data FieldInfo = HyperlinkField URL                 -- The boolean indicates whether the field is a hyperlink.                | PagerefField Anchor Bool+               | CrossrefField Anchor Bool+               | IndexrefField IndexEntry                | CslCitation T.Text                | CslBibliography                | EndNoteCite T.Text@@ -38,26 +50,29 @@ parseFieldInfo = parse fieldInfo ""  fieldInfo :: Parser FieldInfo-fieldInfo =-  try (HyperlinkField <$> hyperlink)-  <|>-  try ((uncurry PagerefField) <$> pageref)-  <|>-  try addIn-  <|>-  return UnknownField+fieldInfo = do+  spaces+  hyperlink+    <|>+    pageref+    <|>+    indexref+    <|>+    crossref+    <|>+    addIn+    <|>+    return UnknownField  addIn :: Parser FieldInfo addIn = do-  spaces   string "ADDIN"   spaces   try cslCitation <|> cslBibliography <|> endnoteCite <|> endnoteRefList  cslCitation :: Parser FieldInfo cslCitation = do-  optional (string "ZOTERO_ITEM")-  spaces+  optional (string "ZOTERO_ITEM" *> spaces)   string "CSL_CITATION"   spaces   CslCitation <$> getInput@@ -95,44 +110,58 @@ unquotedString = T.pack <$> manyTill anyChar (try $ void (lookAhead space) <|> eof)  fieldArgument :: Parser T.Text-fieldArgument = quotedString <|> unquotedString---- there are other switches, but this is the only one I've seen in the wild so far, so it's the first one I'll implement. See §17.16.5.25-hyperlinkSwitch :: Parser (T.Text, T.Text)-hyperlinkSwitch = do-  sw <- string "\\l"-  spaces-  farg <- fieldArgument-  return (T.pack sw, farg)+fieldArgument = do+  notFollowedBy (char '\\') -- switch+  quotedString <|> unquotedString -hyperlink :: Parser URL+hyperlink :: Parser FieldInfo hyperlink = do-  many space   string "HYPERLINK"   spaces   farg <- option "" $ notFollowedBy (char '\\') *> fieldArgument-  switches <- spaces *> many hyperlinkSwitch-  let url = case switches of-              ("\\l", s) : _ -> farg <> "#" <> s-              _              -> farg-  return url+  switches <- many fieldSwitch+  let url = case [s | ('l',s) <- switches] of+              [s] -> farg <> "#" <> s+              _   -> farg+  return $ HyperlinkField url  -- See §17.16.5.45-pagerefSwitch :: Parser (T.Text, T.Text)-pagerefSwitch = do-  sw <- string "\\h"+fieldSwitch :: Parser (Char, T.Text)+fieldSwitch = try $ do   spaces-  farg <- fieldArgument-  return (T.pack sw, farg)+  char '\\'+  c <- anyChar+  spaces+  farg <- option mempty fieldArgument+  return (c, farg) -pageref :: Parser (Anchor, Bool)+pageref :: Parser FieldInfo pageref = do-  many space   string "PAGEREF"   spaces   farg <- fieldArgument-  switches <- spaces *> many pagerefSwitch-  let isLink = case switches of-              ("\\h", _) : _ -> True-              _              -> False-  return (farg, isLink)+  switches <- many fieldSwitch+  let isLink = any ((== 'h') . fst) switches+  return $ PagerefField farg isLink++crossref :: Parser FieldInfo+crossref = do+  string "REF"+  spaces+  farg <- fieldArgument+  switches <- many fieldSwitch+  let isLink = any ((== 'h') . fst) switches+  return $ CrossrefField farg isLink++-- second element of tuple is optional "see".+indexref :: Parser FieldInfo+indexref = do+  string "XE"+  spaces+  farg <- fieldArgument+  switches <- spaces *> many fieldSwitch+  return $ IndexrefField $ IndexEntry{ entryTitle = farg+                                     , entrySee = lookup 't' switches+                                     , entryYomi = lookup 'y' switches+                                     , entryBold = isJust (lookup 'b' switches)+                                     , entryItalic = isJust (lookup 'i' switches) }
src/Text/Pandoc/Readers/Docx/Lists.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Readers.Docx.Lists@@ -18,10 +19,11 @@                                       ) where  import Data.List+import Data.Char (isDigit) import Data.Maybe import Data.String (fromString) import qualified Data.Text as T-import Text.Pandoc.Generic (bottomUp)+import Text.Pandoc.Walk (walk) import Text.Pandoc.JSON import Text.Pandoc.Readers.Docx.Parse (ParaStyleName) import Text.Pandoc.Shared (trim, safeRead)@@ -58,9 +60,9 @@                 ("decimal", Decimal)]  listDelimMap :: [(T.Text, ListNumberDelim)]-listDelimMap = [("%1)", OneParen),-                ("(%1)", TwoParens),-                ("%1.", Period)]+listDelimMap = [("%)", OneParen),+                ("(%)", TwoParens),+                ("%.", Period)]  getListType :: Block -> Maybe ListType getListType b@(Div (_, _, kvs) _) | isListItem b =@@ -72,7 +74,7 @@    case frmt of      Just "bullet" -> Just Itemized      Just f        ->-       case txt of+       case T.filter (not . isDigit) <$> txt of          Just t -> Just $ Enumerated (                   fromMaybe 1 (start >>= safeRead) :: Int,                   fromMaybe DefaultStyle (lookup f listStyleMap),@@ -122,25 +124,48 @@  flatToBullets' :: Integer -> [Block] -> [Block] flatToBullets' _ [] = []-flatToBullets' num xs@(b : elems)-  | getLevelN b == num = b : flatToBullets' num elems-  | otherwise =-    let bNumId = getNumIdN b-        bLevel = getLevelN b-        (children, remaining) =-          span-          (\b' ->-            getLevelN b' > bLevel ||-             (getLevelN b' == bLevel && getNumIdN b' == bNumId))-          xs-    in-     case getListType b of-       Just (Enumerated attr) ->-         OrderedList attr (separateBlocks $ flatToBullets' bLevel children) :-         flatToBullets' num remaining-       _ ->-         BulletList (separateBlocks $ flatToBullets' bLevel children) :-         flatToBullets' num remaining+flatToBullets' num xs@(b : elems) =+  if getLevelN b == num+     then (case bCheckmark of+             Just checked -> addCheckmark checked b+             Nothing -> b) : flatToBullets' num elems+     else case getListType b of+            Just (Enumerated attr) ->+              OrderedList attr (separateBlocks $ flatToBullets' bLevel children) :+              flatToBullets' num remaining+            _ ->+              BulletList (separateBlocks $ flatToBullets' bLevel children) :+              flatToBullets' num remaining+ where+  bNumId = getNumIdN b+  bLevel = getLevelN b+  isCheckmark (Just "\9744") = Just False+  isCheckmark (Just "\9746") = Just True+  isCheckmark _ = Nothing+  bCheckmark =+    case getListType b of+      Just Itemized -> isCheckmark (getText b)+      _ -> Nothing+  addCheckmark checked (Div attrs [Para ils]) =+    Div attrs [Para (Str (if checked then "\9746" else "\9744") : Space : ils)]+  addCheckmark checked (Div attrs [Plain ils]) =+    Div attrs [Plain (Str (if checked then "\9746" else "\9744") : Space : ils)]+  addCheckmark _ x = x+  (children, remaining) =+    span+    (\b' ->+      getLevelN b' > bLevel ||+       (getLevelN b' == bLevel &&+          (getNumIdN b' == bNumId ||+            (case bCheckmark of+               Just _ ->+                 case getText b' of+                   Just "" -> True+                   Just " " -> True+                   Just x -> isJust (isCheckmark (Just x))+                   Nothing -> False+               Nothing -> False))))+    xs  flatToBullets :: [Block] -> [Block] flatToBullets elems = flatToBullets' (-1) elems@@ -153,7 +178,7 @@ blocksToBullets :: [Block] -> [Block] blocksToBullets blks =   map singleItemHeaderToHeader $-  bottomUp removeListDivs $ flatToBullets (handleListParagraphs blks)+  walk removeListDivs $ flatToBullets (handleListParagraphs blks)  plainParaInlines :: Block -> [Inline] plainParaInlines (Plain ils) = ils
src/Text/Pandoc/Readers/Docx/Parse.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE ViewPatterns      #-} {-# LANGUAGE TupleSections     #-} {-# LANGUAGE LambdaCase        #-} {-# LANGUAGE OverloadedStrings #-}@@ -31,17 +30,20 @@                                       , RunStyle(..)                                       , VertAlign(..)                                       , ParIndentation(..)+                                      , Justification(..)                                       , ParagraphStyle(..)                                       , ParStyle                                       , CharStyle(cStyleData)                                       , Row(..)                                       , TblHeader(..)+                                      , Align(..)                                       , Cell(..)                                       , VMerge(..)                                       , TrackedChange(..)                                       , ChangeType(..)                                       , ChangeInfo(..)                                       , FieldInfo(..)+                                      , IndexEntry(..)                                       , Level(..)                                       , ParaStyleName                                       , CharStyleName@@ -65,7 +67,7 @@ import Control.Monad.Except import Control.Monad.Reader import Control.Monad.State.Strict-import Data.Bits ((.|.))+import Data.Bits ((.&.)) import qualified Data.ByteString.Lazy as B import Data.Char (chr, ord, readLitChar) import Data.List@@ -90,13 +92,13 @@       filterChild,       filterChildrenName,       filterElementName,+      filterElementsName,       lookupAttrBy,       parseXMLElement,       elChildren,       QName(QName, qName),       Content(Elem),-      Element(..),-      findElements )+      Element(..))  data ReaderEnv = ReaderEnv { envNotes         :: Notes                            , envComments      :: Comments@@ -108,6 +110,7 @@                            , envParStyles     :: ParStyleMap                            , envLocation      :: DocumentLocation                            , envDocXmlPath    :: FilePath+                           , envTextWidth     :: Int                            }                deriving Show @@ -117,7 +120,7 @@                  deriving Show  data FldCharState = FldCharOpen-                  | FldCharFieldInfo FieldInfo+                  | FldCharFieldInfo T.Text                   | FldCharContent FieldInfo [ParPart]                   deriving (Show) @@ -149,48 +152,62 @@   in    concatMapM handler xs -isAltContentRun :: NameSpaces -> Element -> Bool-isAltContentRun ns element-  | isElem ns "w" "r" element-  , Just _altContentElem <- findChildByName ns "mc" "AlternateContent" element-  = True-  | otherwise-  = False---- Elements such as <w:shape> are not always preferred--- to be unwrapped. Only if they are part of an AlternateContent--- element, they should be unwrapped.--- This strategy prevents VML images breaking.-unwrapAlternateContentElement :: NameSpaces -> Element -> [Element]-unwrapAlternateContentElement ns element-  | isElem ns "mc" "AlternateContent" element-  || isElem ns "mc" "Fallback" element-  || isElem ns "w" "pict" element-  || isElem ns "v" "group" element-  || isElem ns "v" "rect" element-  || isElem ns "v" "roundrect" element-  || isElem ns "v" "shape" element-  || isElem ns "v" "textbox" element-  || isElem ns "w" "txbxContent" element-  = concatMap (unwrapAlternateContentElement ns) (elChildren element)-  | otherwise-  = unwrapElement ns element- unwrapElement :: NameSpaces -> Element -> [Element] unwrapElement ns element   | isElem ns "w" "sdt" element   , Just sdtContent <- findChildByName ns "w" "sdtContent" element   = concatMap (unwrapElement ns) (elChildren sdtContent)-  | isElem ns "w" "r" element-  , Just alternateContentElem <- findChildByName ns "mc" "AlternateContent" element-  = unwrapAlternateContentElement ns alternateContentElem   | isElem ns "w" "smartTag" element   = concatMap (unwrapElement ns) (elChildren element)   | isElem ns "w" "p" element-  , Just (modified, altContentRuns) <- extractChildren element (isAltContentRun ns)-  = (unwrapElement ns modified) ++ concatMap (unwrapElement ns) altContentRuns+  , _:_ <- 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@@ -255,32 +272,42 @@ data TrackedChange = TrackedChange ChangeType ChangeInfo                    deriving Show -data ParagraphStyle = ParagraphStyle { pStyle      :: [ParStyle]-                                     , indentation :: Maybe ParIndentation-                                     , numbered    :: Bool-                                     , dropCap     :: Bool-                                     , pChange     :: Maybe TrackedChange-                                     , pBidi       :: Maybe Bool+data Justification = JustifyBoth | JustifyLeft | JustifyRight | JustifyCenter+  deriving (Show, Eq)++data ParagraphStyle = ParagraphStyle { pStyle        :: [ParStyle]+                                     , indentation   :: Maybe ParIndentation+                                     , justification :: Maybe Justification+                                     , numbered      :: Bool+                                     , dropCap       :: Bool+                                     , pChange       :: Maybe TrackedChange+                                     , pBidi         :: Maybe Bool+                                     , pKeepNext     :: Bool                                      }                       deriving Show  defaultParagraphStyle :: ParagraphStyle defaultParagraphStyle = ParagraphStyle { pStyle = []                                        , indentation = Nothing-                                       , numbered    = False-                                       , dropCap     = False-                                       , pChange     = Nothing-                                       , pBidi       = Just False+                                       , justification = Nothing+                                       , numbered = False+                                       , dropCap = False+                                       , pChange = Nothing+                                       , pBidi = Just False+                                       , pKeepNext = False                                        }   data BodyPart = Paragraph ParagraphStyle [ParPart]+              | Heading Int ParaStyleName ParagraphStyle T.Text T.Text (Maybe Level)+                 [ParPart]               | ListItem ParagraphStyle T.Text T.Text (Maybe Level) [ParPart]-              | Tbl T.Text TblGrid TblLook [Row]-              | TblCaption ParagraphStyle [ParPart]+              | Tbl (Maybe T.Text) T.Text TblGrid TblLook [Row]+              | Captioned ParagraphStyle [ParPart] BodyPart+              | HRule               deriving Show -type TblGrid = [Integer]+type TblGrid = [Double]  newtype TblLook = TblLook {firstRowFormatting::Bool}               deriving Show@@ -292,9 +319,15 @@  data TblHeader = HasTblHeader | NoTblHeader deriving (Show, Eq) -data Cell = Cell GridSpan VMerge [BodyPart]+data Align = AlignDefault | AlignLeft | AlignRight | AlignCenter+  deriving (Show, Eq)++data Cell = Cell Align GridSpan VMerge [BodyPart]             deriving Show +emptyCell :: Cell+emptyCell = Cell AlignDefault 1 Restart []+ type GridSpan = Integer  data VMerge = Continue@@ -305,7 +338,7 @@  rowsToRowspans :: [Row] -> [[(Int, Cell)]] rowsToRowspans rows = let-  removeMergedCells = fmap (filter (\(_, Cell _ vmerge _) -> vmerge == Restart))+  removeMergedCells = fmap (filter (\(_, Cell _ _ vmerge _) -> vmerge == Restart))   in removeMergedCells (foldr f [] rows)   where     f :: Row -> [[(Int, Cell)]] -> [[(Int, Cell)]]@@ -321,9 +354,9 @@     g cells columnsLeftBelow (Just rowBelow) =         case cells of           [] -> []-          thisCell@(Cell thisGridSpan _ _) : restOfRow -> case rowBelow of+          thisCell@(Cell _ thisGridSpan _ _) : restOfRow -> case rowBelow of             [] -> map (1,) cells-            (spanSoFarBelow, Cell gridSpanBelow vmerge _) : _ ->+            (spanSoFarBelow, Cell _ gridSpanBelow vmerge _) : _ ->               let spanSoFar = case vmerge of                     Restart -> 1                     Continue -> 1 + spanSoFarBelow@@ -333,7 +366,7 @@      dropColumns :: Integer -> [(a, Cell)] -> (Integer, [(a, Cell)])     dropColumns n [] = (n, [])-    dropColumns n cells@((_, Cell gridSpan _ _) : otherCells) =+    dropColumns n cells@((_, Cell _ gridSpan _ _) : otherCells) =       if n < gridSpan       then (gridSpan - n, cells)       else dropColumns (n - gridSpan) otherCells@@ -358,7 +391,7 @@ type Extent = Maybe (Double, Double)  data ParPart = PlainRun Run-             | ChangedRuns TrackedChange [Run]+             | ChangedRuns TrackedChange [ParPart]              | CommentStart CommentId Author (Maybe CommentDate) [BodyPart]              | CommentEnd CommentId              | BookMark BookMarkId Anchor@@ -408,6 +441,7 @@       rels      = archiveToRelationships archive docXmlPath       media     = filteredFilesFromArchive archive filePathIsMedia       (styles, parstyles) = archiveToStyles archive+      textWidth = archiveToTextWidth archive       rEnv = ReaderEnv { envNotes = notes                        , envComments = comments                        , envNumbering = numbering@@ -418,6 +452,7 @@                        , envParStyles = parstyles                        , envLocation = InDocument                        , envDocXmlPath = docXmlPath+                       , envTextWidth = fromMaybe 9360 textWidth                        }       rState = ReaderState { stateWarnings = []                            , stateFldCharState = []@@ -438,8 +473,10 @@   entry <- findEntryByPath "_rels/.rels" zf   relsElem <- parseXMLFromEntry entry   let rels = filterChildrenName (\n -> qName n == "Relationship") relsElem-  rel <- find (\e -> findAttr (QName "Type" Nothing Nothing) e ==-                       Just "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument")+  rel <- find (\e ->+                 case findAttr (QName "Type" Nothing Nothing) e of+                   Just u -> isNamespace "officeDocument" "relationships/officeDocument" u+                   Nothing -> False)          rels   fp <- findAttr (QName "Target" Nothing Nothing) rel   -- sometimes there will be a leading slash, which windows seems to@@ -460,9 +497,17 @@   return $ Document namespaces body  elemToBody :: NameSpaces -> Element -> D Body-elemToBody ns element | isElem ns "w" "body" element =-  fmap Body (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@@ -525,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]@@ -548,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]@@ -639,6 +680,20 @@ archiveToNumbering archive =   fromMaybe (Numbering mempty [] []) (archiveToNumbering' archive) +archiveToTextWidth :: Archive -> Maybe Int+archiveToTextWidth zf = do+  entry <- findEntryByPath "word/document.xml" zf+  docElem <- parseXMLFromEntry entry+  let ns = elemToNameSpaces docElem+  sectElem <- findChildByName ns "w" "body" docElem >>= findChildByName ns "w" "sectPr"+  pgWidth <- findChildByName ns "w" "pgSz" sectElem+               >>= findAttrByName ns "w" "w" >>= safeRead+  pgMar <- findChildByName ns "w" "pgMar" sectElem+  leftMargin <- findAttrByName ns "w" "left" pgMar >>= safeRead+  rightMargin <- findAttrByName ns "w" "right" pgMar >>= safeRead+  gutter <- findAttrByName ns "w" "gutter" pgMar >>= safeRead+  return $ pgWidth - (leftMargin + rightMargin + gutter)+ elemToNotes :: NameSpaces -> Text -> Element -> Maybe (M.Map T.Text Element) elemToNotes ns notetype element   | isElem ns "w" (notetype <> "s") element =@@ -667,11 +722,20 @@ ---------------------------------------------  elemToTblGrid :: NameSpaces -> Element -> D TblGrid-elemToTblGrid ns element | isElem ns "w" "tblGrid" element =+elemToTblGrid ns element | isElem ns "w" "tblGrid" element = do   let cols = findChildrenByName ns "w" "gridCol" element-  in-   mapD (\e -> maybeToD (findAttrByName ns "w" "w" e >>= stringToInteger))-   cols+  textWidth <- asks envTextWidth+  -- space between cols is 10 twips, so we subtract this:+  let totalWidth = textWidth - (10 * (length cols - 1))+  let toFraction :: Int -> Double+      toFraction x = fromIntegral x / fromIntegral totalWidth+  let normalizeFractions xs =+        case sum xs of+          tot | tot > 1.0 -> map (/ tot) xs+          _ -> xs+  normalizeFractions <$>+    mapD (\e -> maybeToD (findAttrByName ns "w" "w" e >>=+                          fmap toFraction . safeRead)) cols elemToTblGrid _ _ = throwError WrongElem  elemToTblLook :: NameSpaces -> Element -> D TblLook@@ -692,12 +756,21 @@ 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-           >>= findChildByName ns "w" "tblHeader")-    return $ Row hasTblHeader cells+    let hasTblHeader =+          case (properties >>= findChildByName ns "w" "tblHeader") of+            Nothing -> NoTblHeader+            Just he -> case findAttrByName ns "w" "val" he of+              Just "0" -> NoTblHeader+              _ -> HasTblHeader+    return $ Row hasTblHeader (beforeCells ++ cells) elemToRow _ _ = throwError WrongElem  elemToCell :: NameSpaces -> Element -> D Cell@@ -718,14 +791,23 @@                          "restart" -> Just Restart                          _ -> Nothing     cellContents <- mapD (elemToBodyPart ns) (elChildren element)-    return $ Cell (fromMaybe 1 gridSpan) vMerge cellContents+    let align = case cellContents of -- take alignment from first paragraph+                  Paragraph pstyle _ : _ ->+                    case justification pstyle of+                      Just JustifyBoth -> AlignLeft+                      Just JustifyLeft -> AlignLeft+                      Just JustifyRight -> AlignRight+                      Just JustifyCenter -> AlignCenter+                      Nothing -> AlignDefault+                  _ -> AlignDefault+    return $ Cell align (fromMaybe 1 gridSpan) vMerge cellContents elemToCell _ _ = throwError WrongElem  testBitMask :: Text -> Int -> Bool testBitMask bitMaskS n =   case (reads ("0x" ++ T.unpack bitMaskS) :: [(Int, String)]) of     []            -> False-    ((n', _) : _) -> (n' .|. n) /= 0+    ((n', _) : _) -> (n' .&. n) /= 0  pHeading :: ParagraphStyle -> Maybe (ParaStyleName, Int) pHeading = getParStyleField headingLev . pStyle@@ -741,6 +823,46 @@ pStyleIndentation :: ParagraphStyle -> Maybe ParIndentation pStyleIndentation style = (getParStyleField indent . pStyle) style +addCaptioned :: [BodyPart] -> [BodyPart]+addCaptioned [] = []+addCaptioned (Paragraph parstyle parparts : x : xs)+  | hasCaptionStyle parstyle+  , isCaptionable x+    = Captioned parstyle parparts x : addCaptioned xs+addCaptioned (x : Paragraph parstyle parparts : xs)+  | hasCaptionStyle parstyle+  , not (pKeepNext parstyle)+  , isCaptionable x+    = 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+isCaptionable _ = False+ elemToBodyPart :: NameSpaces -> Element -> D BodyPart elemToBodyPart ns element   | isElem ns "m" "oMathPara" element = do@@ -752,50 +874,58 @@ elemToBodyPart ns element   | isElem ns "w" "p" element   , Just (numId, lvl) <- getNumInfo ns element = do+    lvlInfo <- lookupLevel numId lvl <$> asks envNumbering     parstyle <- elemToParagraphStyle ns element                 <$> asks envParStyles                 <*> asks envNumbering     parparts <- mconcat <$> mapD (elemToParPart ns) (elChildren element)     case pHeading parstyle of       Nothing -> mkListItem parstyle numId lvl parparts-      Just _  -> do-        return $ Paragraph parstyle parparts+      Just (parstylename, lev)+        -> return $ Heading lev parstylename parstyle numId lvl lvlInfo parparts elemToBodyPart ns element+  | isElem ns "w" "p" element+  , [Elem ppr] <- elContent element+  , isElem ns "w" "pPr" ppr+  , [Elem pbdr] <- elContent ppr+  , isElem ns "w" "pBdr" pbdr+    = return HRule+      -- for this style of horizontal rule, see+      -- https://support.microsoft.com/en-us/office/insert-a-horizontal-line-9bf172f6-5908-4791-9bb9-2c952197b1a9+elemToBodyPart ns element -- pandoc-style horizontal rule+  | isElem ns "w" "p" element+  , [Elem r] <- elContent element+  , isElem ns "w" "r" r+  , [Elem pict] <- elContent r+  , isElem ns "w" "pict" pict+  , [Elem rect] <- elContent pict+  , isElem ns "v" "rect" rect+    = return HRule+elemToBodyPart ns element   | isElem ns "w" "p" element = do       parstyle <- elemToParagraphStyle ns element                   <$> asks envParStyles                   <*> asks envNumbering -      let hasCaptionStyle =-            any ((== "caption") . pStyleName) (pStyle parstyle)--      let isTableNumberElt el@(Element name attribs _ _) =-           (qName name == "fldSimple" &&-             case lookupAttrBy ((== "instr") . qName) attribs of-               Nothing -> False-               Just instr -> "Table" `elem` T.words instr) ||-           (qName name == "instrText" && "Table" `elem` T.words (strContent el))--      let isTable = hasCaptionStyle &&-                      isJust (filterChild isTableNumberElt element)--      let stripOffLabel = dropWhile (not . isTableNumberElt)+      let children =+            (if hasCaptionStyle parstyle+                then stripCaptionLabel+                else id) (elChildren element) -      let children = (if isTable-                          then stripOffLabel-                          else id) $ elChildren element       parparts' <- mconcat <$> mapD (elemToParPart ns) children       fldCharState <- gets stateFldCharState       modify $ \st -> st {stateFldCharState = emptyFldCharContents fldCharState}       -- Word uses list enumeration for numbered headings, so we only       -- want to infer a list from the styles if it is NOT a heading.-      let parparts = parparts' ++ (openFldCharsToParParts fldCharState)+      let parparts = parparts' ++ openFldCharsToParParts fldCharState       case pHeading parstyle of         Nothing | Just (numId, lvl) <- pNumInfo parstyle -> do                     mkListItem parstyle numId lvl parparts-        _ -> return $ (if hasCaptionStyle then TblCaption else Paragraph)-                      parstyle parparts-+        Just (parstylename, lev) -> do+          let (numId, lvl) = fromMaybe ("","") $ pNumInfo parstyle+          lvlInfo <- lookupLevel numId lvl <$> asks envNumbering+          return $ Heading lev parstylename parstyle numId lvl lvlInfo parparts+        Nothing -> return $ Paragraph parstyle parparts elemToBodyPart ns element   | isElem ns "w" "tbl" element = do     let tblProperties = findChildByName ns "w" "tblPr" element@@ -805,6 +935,9 @@         description = fromMaybe "" $ tblProperties                        >>= findChildByName ns "w" "tblDescription"                        >>= findAttrByName ns "w" "val"+        mbstyle = tblProperties+                       >>= findChildByName ns "w" "tblStyle"+                       >>= findAttrByName ns "w" "val"         grid' = case findChildByName ns "w" "tblGrid" element of           Just g  -> elemToTblGrid ns g           Nothing -> return []@@ -814,10 +947,16 @@                        Just l  -> elemToTblLook ns l                        Nothing -> return defaultTblLook -    grid <- grid'+    grid'' <- grid'     tblLook <- tblLook'     rows <- mapD (elemToRow ns) (elChildren element)-    return $ Tbl (caption <> description) grid tblLook rows+    let grid = if null grid''+                  then let numcols = case rowsToRowspans rows of+                                       (cs@(_:_):_) -> sum (map fst cs)+                                       _ -> 0+                       in replicate numcols 0.0+                  else grid''+    return $ Tbl mbstyle (caption <> description) grid tblLook rows elemToBodyPart _ _ = throwError WrongElem  lookupRelationship :: DocumentLocation -> RelId -> [Relationship] -> Maybe Target@@ -846,11 +985,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 @@ -892,6 +1043,10 @@         <w:fldChar w:fldCharType="end"/>       </w:r> +Note that there may be mulitple w:instrText elements in a row.+For example, you might first have ` XE "`, then `Kay, Alan`, then `"`.+The texts in all of them should be concatenated before it is processed!+ So we do this in a number of steps. If we encounter the fldchar begin tag, we start open a fldchar state variable (see state above). We add the instrtext to it as FieldInfo. Then we close that and start adding@@ -912,13 +1067,15 @@         _ | fldCharType == "begin" -> do           modify $ \st -> st {stateFldCharState = FldCharOpen : fldCharState}           return []-        FldCharFieldInfo info : ancestors | fldCharType == "separate" -> do+        FldCharFieldInfo t : ancestors | fldCharType == "separate" -> do+          info <- eitherToD $ parseFieldInfo t           modify $ \st -> st {stateFldCharState = FldCharContent info [] : ancestors}           return []-        -- Some fields have no content, since Pandoc doesn't understand any of those fields, we can just close it.-        FldCharFieldInfo _ : ancestors | fldCharType == "end" -> do+        -- Some fields have no content, e.g. index XE:+        FldCharFieldInfo t : ancestors | fldCharType == "end" -> do           modify $ \st -> st {stateFldCharState = ancestors}-          return []+          info <- eitherToD $ parseFieldInfo t+          return [Field info []]         [FldCharContent info children] | fldCharType == "end" -> do           modify $ \st -> st {stateFldCharState = []}           return [Field info $ reverse children]@@ -933,9 +1090,14 @@       fldCharState <- gets stateFldCharState       case fldCharState of         FldCharOpen : ancestors -> do-          info <- eitherToD $ parseFieldInfo $ strContent instrText-          modify $ \st -> st {stateFldCharState = FldCharFieldInfo info : ancestors}+          modify $ \st -> st {stateFldCharState =+                               FldCharFieldInfo (strContent instrText) : ancestors}           return []+        FldCharFieldInfo t : ancestors -> do+          modify $ \st -> st {stateFldCharState =+                               FldCharFieldInfo (t <> strContent instrText) :+                                ancestors}+          return []         _ -> return [] {- There is an open fldchar, so we calculate the element and add it to the@@ -958,8 +1120,8 @@ elemToParPart' ns element   | isElem ns "w" "r" element   , Just drawingElem <- findChildByName ns "w" "drawing" element-  , pic_ns <- "http://schemas.openxmlformats.org/drawingml/2006/picture"-  , picElems <- findElements (QName "pic" (Just pic_ns) (Just "pic")) drawingElem+  , picElems <- filterElementsName+                 (matchQName "drawingml" "picture" (Just "pic") "pic") drawingElem   = let (title, alt) = getTitleAndAlt ns drawingElem         drawings = map (\el ->                         ((findBlip el >>= findAttrByName ns "r" "embed"), el))@@ -993,15 +1155,15 @@ elemToParPart' ns element   | isElem ns "w" "r" element   , Just drawingElem <- findChildByName ns "w" "drawing" element-  , d_ns <- "http://schemas.openxmlformats.org/drawingml/2006/diagram"-  , Just _ <- findElement (QName "relIds" (Just d_ns) (Just "dgm")) drawingElem+  , Just _ <- filterElementName+                 (matchQName "drawingml" "diagram" (Just "dgm") "relIds") drawingElem   = return [Diagram] -- Chart elemToParPart' ns element   | isElem ns "w" "r" element   , Just drawingElem <- findChildByName ns "w" "drawing" element-  , c_ns <- "http://schemas.openxmlformats.org/drawingml/2006/chart"-  , Just _ <- findElement (QName "chart" (Just c_ns) (Just "c")) drawingElem+  , Just _ <- filterElementName+                (matchQName "drawingml" "chart" (Just "c") "chart") drawingElem   = return [Chart] elemToParPart' ns element   | isElem ns "w" "r" element = do@@ -1009,7 +1171,7 @@     return $ map PlainRun runs elemToParPart' ns element   | Just change <- getTrackedChange ns element = do-      runs <- mconcat <$> mapD (elemToRun ns) (elChildren element)+      runs <- mconcat <$> mapD (elemToParPart' ns) (elChildren element)       return [ChangedRuns change runs] elemToParPart' ns element   | isElem ns "w" "bookmarkStart" element@@ -1075,15 +1237,15 @@     (Just w, Just h) -> Just (w, h)     _                -> Nothing  where-  getDim at = filterElementName (\n -> qName n `elem` ["extent", "ext"]) el+  getDim at = filterElementName (\n -> qName n == "extent") el               >>= findAttr (QName at Nothing Nothing) >>= safeRead   childElemToRun :: NameSpaces -> Element -> D [Run] childElemToRun ns element   | isElem ns "w" "drawing" element-  , pic_ns <- "http://schemas.openxmlformats.org/drawingml/2006/picture"-  , picElems <- findElements (QName "pic" (Just pic_ns) (Just "pic")) element+  , picElems <- filterElementsName+                 (matchQName "drawingml" "picture" (Just "pic") "pic") element   = let (title, alt) = getTitleAndAlt ns element         drawings = map (\el ->                          ((findBlip el >>= findAttrByName ns "r" "embed"), el))@@ -1097,13 +1259,13 @@        drawings childElemToRun ns element   | isElem ns "w" "drawing" element-  , c_ns <- "http://schemas.openxmlformats.org/drawingml/2006/chart"-  , Just _ <- findElement (QName "chart" (Just c_ns) (Just "c")) element+  , Just _ <- filterElementName+                 (matchQName "drawingml" "chart" (Just "c") "chart") element   = return [InlineChart] childElemToRun ns element   | isElem ns "w" "drawing" element-  , c_ns <- "http://schemas.openxmlformats.org/drawingml/2006/diagram"-  , Just _ <- findElement (QName "relIds" (Just c_ns) (Just "dgm")) element+  , Just _ <- filterElementName+                 (matchQName "drawingml" "diagram" (Just "dgm") "relIds") element   = return [InlineDiagram] childElemToRun ns element   | isElem ns "w" "footnoteReference" element@@ -1126,15 +1288,6 @@ elemToRun :: NameSpaces -> Element -> D [Run] elemToRun ns element   | isElem ns "w" "r" element-  , Just altCont <- findChildByName ns "mc" "AlternateContent" element =-    do let choices = findChildrenByName ns "mc" "Choice" altCont-           choiceChildren = map head $ filter (not . null) $ map elChildren choices-       outputs <- mapD (childElemToRun ns) choiceChildren-       case outputs of-         r : _ -> return r-         []    -> throwError WrongElem-elemToRun ns element-  | isElem ns "w" "r" element   , Just drawingElem <- findChildByName ns "w" "drawing" element =     childElemToRun ns drawingElem elemToRun ns element@@ -1196,6 +1349,14 @@       , numbered = case getNumInfo ns element of           Just (numId, lvl) -> isJust $ lookupLevel numId lvl numbering           Nothing -> isJust $ getParStyleField numInfo pStyle'+      , justification =+          case findChildByName ns "w" "jc" pPr >>= findAttrByName ns "w" "val" of+            Nothing -> Nothing+            Just "both" -> Just JustifyBoth+            Just "center" -> Just JustifyCenter+            Just "left" -> Just JustifyLeft+            Just "right" -> Just JustifyRight+            _ -> Nothing       , indentation =           getIndentation ns element       , dropCap =@@ -1214,6 +1375,7 @@                                   ) >>=                       getTrackedChange ns       , pBidi = checkOnOff ns pPr (elemName ns "w" "bidi")+      , pKeepNext = isJust $ findChildByName ns "w" "keepNext" pPr       }   | otherwise = defaultParagraphStyle @@ -1285,8 +1447,56 @@  findBlip :: Element -> Maybe Element findBlip el = do-  blip <- findElement (QName "blip" (Just a_ns) (Just "a")) el+  blip <- filterElementName (matchQName "drawingml" "main" (Just "a") "blip") el   -- return svg if present:   filterElementName (\(QName tag _ _) -> tag == "svgBlip") el `mplus` pure blip++-- | Checks if any style in the style hierarchy is a caption style.+hasCaptionStyle :: ParagraphStyle -> Bool+hasCaptionStyle =+  any (isCaptionStyleName . pStyleName) . concatMap nestedStyles . pStyle+ where -- note that these are case insensitive:+   isCaptionStyleName "caption" = True+   isCaptionStyleName "table caption" = True+   isCaptionStyleName "image caption" = True+   isCaptionStyleName _ = False++   -- Gets all the style names in the style hierarchy+   nestedStyles :: ParStyle -> [ParStyle]+   nestedStyles ps = ps : maybe [] nestedStyles (psParentStyle ps)++stripCaptionLabel :: [Element] -> [Element]+stripCaptionLabel els =+  if any isNumberElt els+     then dropWhile (not . isNumberElt) els+     else els+  where+    isNumberElt el@(Element name attribs _ _) =+       (qName name == "fldSimple" &&+             case lookupAttrBy ((== "instr") . qName) attribs of+               Nothing -> False+               Just instr -> "Table" `elem` T.words instr ||+                             "Figure" `elem` T.words instr) ||+       (qName name == "instrText" &&+          let ws = T.words (strContent el)+          in  ("Table" `elem` ws || "Figure" `elem` ws))++isNamespace :: Text -> Text -> Text -> Bool+isNamespace primary secondary url =+  -- first try transitional:+  case T.stripPrefix "http://schemas.openxmlformats.org/" url of+    Just path -> path == primary <> "/2006/" <> secondary+    Nothing -> -- then try strict:+      case T.stripPrefix "http://purl.oclc.org/ooxml/" url of+        Just path -> path == primary <> "/" <> snakeToCamel secondary+        Nothing -> False  where-  a_ns = "http://schemas.openxmlformats.org/drawingml/2006/main"+   snakeToCamel "custom-properties" = "customProperties"+   snakeToCamel "extended-properties" = "extendedProperties"+   snakeToCamel x = x++matchQName :: Text -> Text -> Maybe Text -> Text -> QName -> Bool+matchQName primary secondary mbprefix name (QName name' mbns' mbprefix') =+  name == name' &&+  (isNothing mbprefix || mbprefix' == mbprefix) &&+  maybe True (isNamespace primary secondary) mbns'
src/Text/Pandoc/Readers/Docx/Parse/Styles.hs view
@@ -239,8 +239,8 @@  stringToInteger :: Text -> Maybe Integer stringToInteger s = case Data.Text.Read.decimal s of-                      Right (x,_) -> Just x-                      Left _      -> Nothing+                      Right (x,t) | T.null t -> Just x+                      _                      -> Nothing  checkOnOff :: NameSpaces -> Element -> QName -> Maybe Bool checkOnOff ns rPr tag
src/Text/Pandoc/Readers/Docx/Util.hs view
@@ -2,7 +2,7 @@ {- |    Module      : Text.Pandoc.Readers.Docx.Util    Copyright   : © 2014-2020 Jesse Rosenthal <jrosenthal@jhu.edu>,-                   2014-2023 John MacFarlane <jgm@berkeley.edu>,+                   2014-2024 John MacFarlane <jgm@berkeley.edu>,                    2015 Nikolay Yakimov <root@livid.pp.ru>    License     : GNU GPL, version 2 or above @@ -24,51 +24,11 @@                                       , extractChildren                                       ) where -import qualified Data.Text as T-import Data.Text (Text)-import Text.Pandoc.XML.Light-import qualified Data.Map as M import Data.List (partition)--type NameSpaces = M.Map Text Text--elemToNameSpaces :: Element -> NameSpaces-elemToNameSpaces = foldr (\(Attr qn val) ->-                             case qn of-                               QName s _ (Just "xmlns") -> M.insert s val-                               _ -> id) mempty . elAttribs--elemName :: NameSpaces -> Text -> Text -> QName-elemName ns prefix name =-  QName name (M.lookup prefix ns)-             (if T.null prefix then Nothing else Just prefix)--isElem :: NameSpaces -> Text -> Text -> Element -> Bool-isElem ns prefix name element =-  let ns' = ns <> elemToNameSpaces element-  in qName (elName element) == name &&-     qURI (elName element) == M.lookup prefix ns'--findChildByName :: NameSpaces -> Text -> Text -> Element -> Maybe Element-findChildByName ns pref name el =-  let ns' = ns <> elemToNameSpaces el-  in  findChild (elemName ns' pref name) el--findChildrenByName :: NameSpaces -> Text -> Text -> Element -> [Element]-findChildrenByName ns pref name el =-  let ns' = ns <> elemToNameSpaces el-  in  findChildren (elemName ns' pref name) el---- | Like 'findChildrenByName', but searches descendants.-findElementByName :: NameSpaces -> Text -> Text -> Element -> Maybe Element-findElementByName ns pref name el =-  let ns' = ns <> elemToNameSpaces el-  in  findElement (elemName ns' pref name) el--findAttrByName :: NameSpaces -> Text -> Text -> Element -> Maybe Text-findAttrByName ns pref name el =-  let ns' = ns <> elemToNameSpaces el-  in  findAttr (elemName ns' pref name) el+import Text.Pandoc.XML.Light+import Text.Pandoc.Readers.OOXML.Shared+  (NameSpaces, elemName, isElem, elemToNameSpaces,+   findChildByName, findChildrenByName, findElementByName, findAttrByName)   -- | Removes child elements that satisfy a given condition.@@ -79,13 +39,7 @@   | otherwise = Just (modifiedElement, removedChildren)  -- Children removed, return Just   where     -- Separate the children based on the condition-    (removedChildren, keptChildren) = partition condition (onlyElems' $ elContent el)--    -- Helper function to filter only Element types from Content-    onlyElems' :: [Content] -> [Element]-    onlyElems' = foldr (\c acc -> case c of-                                   Elem e -> e : acc-                                   _      -> acc) []+    (removedChildren, keptChildren) = partition condition (onlyElems $ elContent el)      -- Reconstruct the element with the kept children     modifiedElement = el { elContent = map Elem keptChildren }
src/Text/Pandoc/Readers/DokuWiki.hs view
@@ -29,7 +29,7 @@ import Text.Pandoc.Options import Text.Pandoc.Parsing hiding (enclosed) import Text.Pandoc.Shared (trim, stringify, tshow)-import Data.List (isPrefixOf, isSuffixOf)+import Data.List (isPrefixOf, isSuffixOf, groupBy) import qualified Safe  -- | Read DokuWiki from an input string and return a Pandoc document.@@ -111,6 +111,7 @@       <|> autoEmail       <|> notoc       <|> nocache+      <|> smartPunctuation inline       <|> str       <|> symbol       <?> "inline"@@ -443,7 +444,9 @@   many1 ((<>) <$> item <*> fmap mconcat (many continuation))   where     continuation = try $ list ("  " <> prefix)-    item = try $ textStr prefix *> char marker *> char ' ' *>+    item = try $ textStr prefix *>+                   optional (char ' ') *>  -- see #8863+                   char marker *> char ' ' *>                    (mconcat <$> many1 itemContents <* eol)     itemContents = (B.plain . mconcat <$> many1 inline') <|>                    blockCode@@ -453,15 +456,37 @@  where    indentedLine = try $ string "  " *> manyTillChar anyChar eol +-- Note that block quotes in dokuwiki parse as lists of hard-break+-- separated lines; see #6461. quote :: PandocMonad m => DWParser m B.Blocks-quote = try $ nestedQuote 0-  where-    prefix level = count level (char '>')-    contents level = nestedQuote level <|> quoteLine-    quoteLine = try $ B.plain . B.trimInlines . mconcat <$> many1Till inline' eol-    quoteContents level = (<>) <$> contents level <*> quoteContinuation level-    quoteContinuation level = mconcat <$> many (try $ prefix level *> contents level)-    nestedQuote level = B.blockQuote <$ char '>' <*> quoteContents (level + 1 :: Int)+quote = go <$> many1 blockQuoteLine+ where+   blockQuoteLine = try $ do+     lev <- length <$> many1 (char '>')+     skipMany spaceChar+     contents <- (blockCode <* skipMany spaceChar <* optional eol) <|>+       (B.plain . B.trimInlines . mconcat <$> many1Till inline' eol)+     pure (lev, contents)+   go [] = mempty+   go xs = mconcat $ map go' (groupBy (\(x,_) (y,_) -> (x == 0 && y == 0) ||+                                                        (x > 0 && y > 0)) xs)+   go' [] = mempty+   go' xs@((0,_):_) =+        let (lns, bls) = F.foldl' consolidatePlains (mempty,mempty) (map snd xs)+         in bls <> if lns == mempty+                      then mempty+                      else B.plain lns+   go' xs = B.blockQuote (go $ map (\(x,y) -> (x - 1, y)) xs)+   consolidatePlains (lns, bls) b =+     case B.toList b of+       [Plain ils] -> ((if lns == mempty+                           then B.fromList ils+                           else lns <> B.linebreak <> B.fromList ils), bls)+       _ -> (mempty, bls <>+                     (if lns == lns+                         then mempty+                         else B.plain lns)+                      <> b)  blockRaw :: PandocMonad m => DWParser m B.Blocks blockRaw = try $ do@@ -483,7 +508,7 @@   rows <- tableRows   let firstRow = fromMaybe [] . Safe.headMay $ rows   let (headerRow, body) = if firstSeparator == '^'-                            then (firstRow, tail rows)+                            then (firstRow, drop 1 rows)                             else ([], rows)   -- Since Pandoc only has column level alignment, we have to make an arbitrary   -- choice of how to reconcile potentially different alignments in the row.
src/Text/Pandoc/Readers/EPUB.hs view
@@ -29,7 +29,7 @@ import Data.Maybe (mapMaybe) import qualified Data.Text.Lazy as TL import qualified Data.Text.Lazy.Encoding as TL-import Network.URI (unEscapeString)+import Network.URI (unEscapeString, parseRelativeReference, URI(..)) import System.FilePath (dropFileName, dropFileName, normalise, splitFileName,                         takeFileName, (</>)) import qualified Text.Pandoc.Builder as B@@ -211,10 +211,17 @@   Span (fixAttrs s as) v fixInlineIRs s (Code as code) =   Code (fixAttrs s as) code-fixInlineIRs s (Link as is (T.uncons -> Just ('#', url), tit)) =-  Link (fixAttrs s as) is (addHash s url, tit)-fixInlineIRs s (Link as is t) =-  Link (fixAttrs s as) is t+fixInlineIRs s (Link as is (url, tit)) =+  case parseRelativeReference (T.unpack url) of+    Just URI{ uriScheme = ""+            , uriAuthority = Nothing+            , uriPath = upath+            , uriQuery = ""+            , uriFragment = '#':ufrag } ->+         Link (fixAttrs s as) is (addHash (if null upath+                                              then s+                                              else upath) (T.pack ufrag), tit)+    _ -> Link (fixAttrs s as) is (url, tit) fixInlineIRs _ v = v  prependHash :: [Text] -> Inline -> Inline
src/Text/Pandoc/Readers/EndNote.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Readers.EndNote-   Copyright   : Copyright (C) 2022-2023 John MacFarlane+   Copyright   : Copyright (C) 2022-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -72,15 +72,18 @@     B.doc mempty  readEndNoteXMLCitation :: PandocMonad m-                    => Sources -> m (Citeproc.Citation Text)-readEndNoteXMLCitation sources = do+                    => Text -> m (Citeproc.Citation Text)+readEndNoteXMLCitation xml = do   tree <- either (throwError . PandocXMLError "EndNote references") return $-              parseXMLElement (TL.fromStrict . sourcesToText $ sources)+              parseXMLElement (TL.fromStrict xml)   unless (qName (elName tree) == "EndNote") $     throwError $ PandocXMLError "EndNote references" "Expected EndNote element"   let items = map toCitationItem $ filterElementsName (name "Cite") tree   return $ Citeproc.Citation{                      Citeproc.citationId = Nothing+                   , Citeproc.citationResetPosition = False+                   , Citeproc.citationPrefix = Nothing+                   , Citeproc.citationSuffix = Nothing                    , Citeproc.citationNoteNumber = Nothing                    , Citeproc.citationItems = items                    }
src/Text/Pandoc/Readers/HTML.hs view
@@ -5,7 +5,7 @@ {-# LANGUAGE ViewPatterns          #-} {- |    Module      : Text.Pandoc.Readers.HTML-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -33,9 +33,8 @@ import Data.Default (Default (..), def) import Data.Foldable (for_) import Data.List.Split (splitWhen)-import Data.List (foldl')+import qualified Data.List as L import qualified Data.Map as M-import Data.Maybe (fromMaybe, isJust, isNothing) import Data.Either (partitionEithers) import Data.Monoid (First (..)) import qualified Data.Set as Set@@ -70,6 +69,7 @@ import Text.Pandoc.Walk import Text.TeXMath (readMathML, writeTeX) import qualified Data.Sequence as Seq+import Data.Maybe (fromMaybe, isJust)  -- | Convert HTML-formatted string to 'Pandoc' document. readHtml :: (PandocMonad m, ToSources a)@@ -85,7 +85,7 @@         meta <- stateMeta . parserState <$> getState         bs' <- replaceNotes (B.toList blocks)         reportLogMessages-        return $ Pandoc meta bs'+        return $ Pandoc meta $ extractMain bs'       getError (errorMessages -> ms) = case ms of                                          []    -> ""                                          (m:_) -> messageString m@@ -98,6 +98,20 @@     Right doc -> return doc     Left  err -> throwError $ PandocParseError $ T.pack $ getError err +-- Extract contents of main element if exactly one is present; otherwise+-- return all blocks.+extractMain :: [Block] -> [Block]+extractMain bs =+  case query getMain bs of+    [] -> bs+    [Div ("",[],_) bs'] -> bs'+    bs' -> bs'+ where+   getMain :: Block -> [Block]+   getMain b@(Div (_,_,kvs) _)+     | Just "main" <- lookup "role" kvs = [b]+   getMain _ = []+ -- Strip namespace prefixes on tags (not attributes) stripPrefixes :: [Tag Text] -> [Tag Text] stripPrefixes = map stripPrefix@@ -178,6 +192,7 @@     TagOpen name attr ->       let type' = fromMaybe "" $                      lookup "type" attr <|> lookup "epub:type" attr+          role = fromMaybe "" $ lookup "role" attr           epubExts = extensionEnabled Ext_epub_html_exts exts       in       case name of@@ -197,6 +212,8 @@         _ | "titlepage" `T.isInfixOf` type'           , name `elem` ("section" : groupingContent)           -> mempty <$ eTitlePage+        _ | role == "doc-endnotes"+          -> eFootnotes         "p" -> pPara         "h1" -> pHeader         "h2" -> pHeader@@ -220,6 +237,7 @@           -> pLineBlock           | otherwise           -> pDiv+        "aside" -> pDiv         "section" -> pDiv         "header" -> pDiv         "main" -> pDiv@@ -267,14 +285,14 @@  eFootnote :: PandocMonad m => TagParser m () eFootnote = do-  guardEnabled Ext_epub_html_exts+  inNotes <- inFootnotes <$> getState   TagOpen tag attr' <- lookAhead $ pSatisfy     (\case        TagOpen _ attr'          -> case lookup "type" attr' <|> lookup "epub:type" attr' of               Just "footnote" -> True               Just "rearnote" -> True-              _ -> False+              _ -> inNotes        _ -> False)   let attr = toStringAttr attr'   let ident = fromMaybe "" (lookup "id" attr)@@ -285,11 +303,12 @@ eFootnotes :: PandocMonad m => TagParser m Blocks eFootnotes = try $ do   let notes = ["footnotes", "rearnotes"]-  guardEnabled Ext_epub_html_exts   (TagOpen tag attr') <- lookAhead pAny   let attr = toStringAttr attr'-  guard $ maybe False (`elem` notes)-          (lookup "type" attr <|> lookup "epub:type" attr)+  guard (lookup "role" attr == Just "doc-endnotes") <|>+    (guardEnabled Ext_epub_html_exts >>+     guard (maybe False (`elem` notes)+             (lookup "type" attr <|> lookup "epub:type" attr)))   updateState $ \s -> s{ inFootnotes = True }   result <- pInTags tag block   updateState $ \s -> s{ inFootnotes = False }@@ -302,12 +321,12 @@  eNoteref :: PandocMonad m => TagParser m Inlines eNoteref = try $ do-  guardEnabled Ext_epub_html_exts   TagOpen tag attr <-     pSatisfy (\case                  TagOpen _ as                     -> (lookup "type" as <|> lookup "epub:type" as)-                        == Just "noteref"+                        == Just "noteref" ||+                        lookup "role" as == Just "doc-noteref"                  _  -> False)   ident <- case lookup "href" attr >>= T.uncons of              Just ('#', rest) -> return rest@@ -328,17 +347,20 @@ pBulletList :: PandocMonad m => TagParser m Blocks pBulletList = try $ do   pSatisfy (matchTagOpen "ul" [])-  let nonItem = pSatisfy (\t ->-                  not (tagOpen (`elem` ["li","ol","ul","dl"]) (const True) t) &&-                  not (matchTagClose "ul" t))   -- note: if they have an <ol> or <ul> not in scope of a <li>,   -- treat it as a list item, though it's not valid xhtml...-  skipMany nonItem-  items <- manyTill (pListItem nonItem) (pCloses "ul")-  return $ B.bulletList $ map (fixPlains True) items+  skipMany pBlank+  orphans <- many (do notFollowedBy (pSatisfy (matchTagOpen "li" []))+                      notFollowedBy (pSatisfy isTagClose)+                      block) -- e.g. <ul>, see #9187+  items <- manyTill pListItem (pCloses "ul")+  let items' = case orphans of+                 [] -> items+                 xs -> mconcat xs : items+  return $ B.bulletList $ map (fixPlains True) items' -pListItem :: PandocMonad m => TagParser m a -> TagParser m Blocks-pListItem nonItem = setInListItem $ do+pListItem :: PandocMonad m => TagParser m Blocks+pListItem = setInListItem $ do   TagOpen _ attr' <- lookAhead $ pSatisfy (matchTagOpen "li" [])   let attr = toStringAttr attr'   let addId ident bs = case B.toList bs of@@ -346,10 +368,11 @@                                 [Span (ident, [], []) ils] : xs)                            _ -> B.divWith (ident, [], []) bs   item <- pInTags "li" block-  skipMany nonItem+  skipMany pBlank   orphans <- many (do notFollowedBy (pSatisfy (matchTagOpen "li" []))                       notFollowedBy (pSatisfy isTagClose)                       block) -- e.g. <ul>, see #9187+  skipMany pBlank   return $ maybe id addId (lookup "id" attr) $ item <> mconcat orphans  pCheckbox :: PandocMonad m => TagParser m Inlines@@ -391,20 +414,23 @@         where           pickListStyle = pickStyleAttrProps ["list-style-type", "list-style"] -  let nonItem = pSatisfy (\t ->-                  not (tagOpen (`elem` ["li","ol","ul","dl"]) (const True) t) &&-                  not (matchTagClose "ol" t))   -- note: if they have an <ol> or <ul> not in scope of a <li>,   -- treat it as a list item, though it's not valid xhtml...-  skipMany nonItem+  skipMany pBlank+  orphans <- many (do notFollowedBy (pSatisfy (matchTagOpen "li" []))+                      notFollowedBy (pSatisfy isTagClose)+                      block) -- e.g. <ul>, see #9187   if isNoteList      then do        _ <- manyTill (eFootnote <|> pBlank) (pCloses "ol")        return mempty      else do-       items <- manyTill (pListItem nonItem) (pCloses "ol")+       items <- manyTill pListItem (pCloses "ol")+       let items' = case orphans of+                      [] -> items+                      xs -> mconcat xs : items        return $ B.orderedListWith (start, style, DefaultDelim) $-                map (fixPlains True) items+                map (fixPlains True) items'  pDefinitionList :: PandocMonad m => TagParser m Blocks pDefinitionList = try $ do@@ -419,9 +445,9 @@   terms <- many1 (try $ skipMany nonItem >> pInTags "dt" inline)   defs  <- many1 (try $ skipMany nonItem >> pInTags "dd" block)   skipMany nonItem-  let term = foldl' (\x y -> if null x-                                then trimInlines y-                                else x <> B.linebreak <> trimInlines y)+  let term = L.foldl' (\x y -> if null x+                                  then trimInlines y+                                  else x <> B.linebreak <> trimInlines y)                     mempty terms   return (term, map (fixPlains True) defs) @@ -464,6 +490,7 @@ isDivLike "section" = True isDivLike "header"  = True isDivLike "main"    = True+isDivLike "aside"   = True isDivLike _         = False  pDiv :: PandocMonad m => TagParser m Blocks@@ -477,18 +504,20 @@                         | hident == ident ->                           B.Many $ Header lev ("",hclasses,hkvs) ils Seq.<| rest                     _ -> contents-  let classes' = if tag == "section"-                    then "section":classes-                    else classes-      kvs' = if tag == "main" && isNothing (lookup "role" kvs)-               then ("role", "main"):kvs-               else kvs+  let (classes', kvs') =+        case tag of+          "section" -> ("section":classes, kvs)+          "aside" -> ("aside":classes, kvs)+          "header" -> ("header":classes, kvs)+          "main" | Nothing <- lookup "role" kvs -> (classes, ("role", "main"):kvs)+          _ -> (classes, kvs)   return $ B.divWith (ident, classes', kvs') contents'  pIframe :: PandocMonad m => TagParser m Blocks pIframe = try $ do   guardDisabled Ext_raw_html   tag <- pSatisfy (tagOpen (=="iframe") (isJust . lookup "src"))+  skipMany pBlank   pCloses "iframe" <|> eof   url <- canonicalizeUrl $ fromAttrib "src" tag   if T.null url@@ -505,7 +534,7 @@                | "image/" `T.isPrefixOf` mt -> do                     return $ B.divWith ("",["iframe"],[]) $                       B.plain $ B.image url "" mempty-             _ -> return $ B.divWith ("",["iframe"],[("src", url)]) $ mempty)+             _ -> return $ B.divWith ("",["iframe"],[("src", url)]) mempty)        (\e -> do          logMessage $ CouldNotFetchResource url (renderError e)          ignore $ renderTags' [tag, TagClose "iframe"])@@ -634,14 +663,10 @@                              else v ]   contents <- manyTill pAny (pCloses "pre" <|> eof)   let rawText = T.concat $ map tagToText contents-  -- drop leading newline if any-  let result' = case T.uncons rawText of-                     Just ('\n', xs) -> xs-                     _               -> rawText   -- drop trailing newline if any-  let result = case T.unsnoc result' of+  let result = case T.unsnoc rawText of                     Just (result'', '\n') -> result''-                    _                     -> result'+                    _                     -> rawText   return $ B.codeBlockWith attr result  tagToText :: Tag Text -> Text@@ -660,6 +685,9 @@           , Just "noteref" <- lookup "type" attr <|> lookup "epub:type" attr           , Just ('#',_) <- lookup "href" attr >>= T.uncons             -> eNoteref+          | Just "doc-noteref" <- lookup "role" attr+          , Just ('#',_) <- lookup "href" attr >>= T.uncons+            -> eNoteref             | otherwise -> pLink         "switch" -> eSwitch id inline         "q" -> pQ@@ -688,6 +716,7 @@         "input"           | lookup "type" attr == Just "checkbox"           -> asks inListItem >>= guard >> pCheckbox+        "style" -> B.rawInline "html" <$> pHtmlBlock "style"         "script"           | Just x <- lookup "type" attr           , "math/tex" `T.isPrefixOf` x -> pScriptMath@@ -809,7 +838,10 @@   let rawText = T.strip $ renderTags' (opent : contents ++ [closet])   let svgData = "data:image/svg+xml;base64," <>                    UTF8.toText (encode $ UTF8.fromText rawText)-  return $ B.imageWith (ident,cls,[]) svgData mempty mempty+  let kvs = [("width", "1em") | "fa-w-14" `elem` cls ||+                                "fa-w-16" `elem` cls ||+                                "fa-fw" `elem` cls] -- #10134+  return $ B.imageWith (ident,cls,kvs) svgData mempty mempty  pCodeWithClass :: PandocMonad m => Text -> Text -> TagParser m Inlines pCodeWithClass name class' = try $ do@@ -845,23 +877,30 @@ pSpan = do   (TagOpen _ attr') <- lookAhead (pSatisfy $ tagOpen (=="span") (const True))   exts <- getOption readerExtensions-  if extensionEnabled Ext_native_spans exts-     then do-       contents <- pInTags "span" inline-       let attr = toAttr attr'-       let classes = maybe [] T.words $ lookup "class" attr'-       let styleAttr   = fromMaybe "" $ lookup "style" attr'-       let fontVariant = fromMaybe "" $-                          pickStyleAttrProps ["font-variant"] styleAttr-       let isSmallCaps = fontVariant == "small-caps" ||-                           "smallcaps" `elem` classes-       let tag = if isSmallCaps then B.smallcaps else B.spanWith attr-       return $ tag contents-     else if extensionEnabled Ext_raw_html exts-             then do-               tag <- pSatisfy $ tagOpen (=="span") (const True)-               return $ B.rawInline "html" $ renderTags' [tag]-             else pInTags "span" inline -- just contents+  let attr = toAttr attr'+  case attr of+     (_,cls,_) -- skip MathJaX-generated HTML; see #10673+       | "mjx-chtml" `elem` cls -> mempty <$ pInTags "span" inline+       | "MathJax_CHTML" `elem` cls -> mempty <$ pInTags "span" inline+       | "MathJax_Preview" `elem` cls -> mempty <$ pInTags "span" inline+       | "MJX_Assistive_MathML" `elem` cls -> pInTags "span" inline+     (_,["katex-html"],_) -> mempty <$ pInTags "span" inline+       -- skip HTML generated by KaTeX, since we get+       -- the math by parsing mathml (#9971)+     _ | extensionEnabled Ext_native_spans exts -> do+           contents <- pInTags "span" inline+           let classes = maybe [] T.words $ lookup "class" attr'+           let styleAttr   = fromMaybe "" $ lookup "style" attr'+           let fontVariant = fromMaybe "" $+                              pickStyleAttrProps ["font-variant"] styleAttr+           let isSmallCaps = fontVariant == "small-caps" ||+                               "smallcaps" `elem` classes+           let tag = if isSmallCaps then B.smallcaps else B.spanWith attr+           return $ tag contents+       | extensionEnabled Ext_raw_html exts -> do+            tag <- pSatisfy $ tagOpen (=="span") (const True)+            return $ B.rawInline "html" $ renderTags' [tag]+       | otherwise  -> pInTags "span" inline -- just contents  pRawHtmlInline :: PandocMonad m => TagParser m Inlines pRawHtmlInline = do@@ -897,16 +936,30 @@   let attr = toStringAttr attr'   unless inCase $     guard (maybe True (== mathMLNamespace) (lookup "xmlns" attr))+  let constructor = case lookup "display" attr of+                       Just "block" -> B.displayMath+                       _ -> B.math   contents <- manyTill pAny (pSatisfy (matchTagClose "math"))-  case mathMLToTeXMath (renderTags $-          [open] <> contents <> [TagClose "math"]) of-       Left _   -> return $ B.spanWith ("",["math"],attr) $ B.text $-                             innerText contents-       Right "" -> return mempty-       Right x  -> return $ case lookup "display" attr of-                                 Just "block" -> B.displayMath x-                                 _            -> B.math x+  -- KaTeX and others include original TeX in annotation tag;+  -- just use this if present rather than parsing MathML:+  case extractTeXAnnotation contents of+    Just x -> return $ constructor x+    Nothing ->+      case mathMLToTeXMath (renderTags $+              [open] <> contents <> [TagClose "math"]) of+           Left _   -> return $ B.spanWith ("",["math"],attr) $ B.text $+                                 innerText contents+           Right "" -> return mempty+           Right x  -> return $ constructor x +extractTeXAnnotation :: [Tag Text] -> Maybe Text+extractTeXAnnotation [] = Nothing+extractTeXAnnotation (TagOpen "annotation" [("encoding","application/x-tex")]+                       : ts) =+  Just $ innerText $ takeWhile (~/= TagClose ("annotation" :: Text)) ts+extractTeXAnnotation (_:ts) = extractTeXAnnotation ts++ pInlinesInTags :: PandocMonad m => Text -> (Inlines -> Inlines)                -> TagParser m Inlines pInlinesInTags tagtype f = extractSpaces f <$> pInTags tagtype inline@@ -1028,6 +1081,8 @@ isInlineTag t = isCommentTag t || case t of   TagOpen "script" _ -> "math/tex" `T.isPrefixOf` fromAttrib "type" t   TagClose "script"  -> True+  TagOpen "style" _  -> True -- see #10643, invalid but it happens+  TagClose "style"   -> True   TagOpen name _     -> isInlineTagName name   TagClose name      -> isInlineTagName name   _                  -> False@@ -1178,8 +1233,10 @@  -- | Adjusts a url according to the document's base URL. canonicalizeUrl :: PandocMonad m => Text -> TagParser m Text-canonicalizeUrl url = do-  mbBaseHref <- baseHref <$> getState-  return $ case (parseURIReference (T.unpack url), mbBaseHref) of-                (Just rel, Just bs) -> tshow (rel `nonStrictRelativeTo` bs)-                _                   -> url+canonicalizeUrl url+  | "data:" `T.isPrefixOf` url = return url+  | otherwise = do+     mbBaseHref <- baseHref <$> getState+     return $ case (parseURIReference (T.unpack url), mbBaseHref) of+                   (Just rel, Just bs) -> tshow (rel `nonStrictRelativeTo` bs)+                   _                   -> url
src/Text/Pandoc/Readers/HTML/Parsing.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE OverloadedStrings     #-} {- |    Module      : Text.Pandoc.Readers.HTML.Parsing-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>
src/Text/Pandoc/Readers/HTML/Table.hs view
@@ -3,11 +3,11 @@ {-# LANGUAGE ViewPatterns      #-} {- |    Module      : Text.Pandoc.Readers.HTML.Table-   Copyright   : © 2006-2023 John MacFarlane,-                   2020-2023 Albert Krewinkel+   Copyright   : © 2006-2024 John MacFarlane,+                   2020-2024 Albert Krewinkel    License     : GNU GPL, version 2 or above -   Maintainer  : Albert Krewinkel <albert@zeitkraut.de>+   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>    Stability   : alpha    Portability : portable @@ -20,7 +20,7 @@ import Data.Maybe (fromMaybe, isJust) import Data.Either (lefts, rights) import Data.List.NonEmpty (nonEmpty)-import Data.List (foldl')+import qualified Data.List as L import Data.Text (Text) import Text.HTML.TagSoup import Text.Pandoc.Builder (Blocks)@@ -204,9 +204,9 @@   let adjustRowHeadCols         headcolsv         (currentrow, (numheads, Row _ cells)) =-          foldl' (adjustRowHeadColsForCell currentrow) headcolsv+          L.foldl' (adjustRowHeadColsForCell currentrow) headcolsv             (take numheads cells)-  let headcols = foldl' adjustRowHeadCols+  let headcols = L.foldl' adjustRowHeadCols                          (V.replicate numrows (0 :: Int))                          (zip [(0 :: Int)..] rows)   let rowHeadCols = case V.uncons headcols of
src/Text/Pandoc/Readers/HTML/TagCategories.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings     #-} {- |    Module      : Text.Pandoc.Readers.HTML.TagCategories-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>
src/Text/Pandoc/Readers/HTML/Types.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE MultiParamTypeClasses #-} {- |    Module      : Text.Pandoc.Readers.HTML.Types-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>
src/Text/Pandoc/Readers/Haddock.hs view
@@ -101,10 +101,9 @@              toRow = Row nullAttr . map B.simpleCell              toHeaderRow l = [toRow l | not (null l)]              (header, body) =-               if null headerRows-                  then ([], map toCells bodyRows)-                  else (toCells (head headerRows),-                        map toCells (tail headerRows ++ bodyRows))+               case headerRows of+                  [] -> ([], map toCells bodyRows)+                  (x:xs) -> (toCells x, map toCells (xs ++ bodyRows))              colspecs = replicate (maybe 0 maximum (nonEmpty (map length body)))                              (AlignDefault, ColWidthDefault)          in  B.table B.emptyCaption
src/Text/Pandoc/Readers/Ipynb.hs view
@@ -4,7 +4,7 @@ {-# LANGUAGE ScopedTypeVariables #-} {- |    Module      : Text.Pandoc.Readers.Ipynb-   Copyright   : Copyright (C) 2019-2023 John MacFarlane+   Copyright   : Copyright (C) 2019-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -15,9 +15,9 @@ -} module Text.Pandoc.Readers.Ipynb ( readIpynb ) where+import Crypto.Hash (hashWith, SHA1(SHA1)) import Data.Char (isDigit) import Data.Maybe (fromMaybe)-import Data.Digest.Pure.SHA (sha1, showDigest) import Text.Pandoc.Options import Control.Applicative ((<|>)) import qualified Data.Scientific as Scientific@@ -186,16 +186,16 @@                        Error _   -> mempty                    _ -> mempty       let metaPairs = jsonMetaToPairs meta-      let bl = case d of-                 BinaryData bs  -> BL.fromStrict bs-                 TextualData t  -> BL.fromStrict $ UTF8.fromText t-                 JsonData v     -> encode v+      let bs = case d of+                 BinaryData bs' -> bs'+                 TextualData t  -> UTF8.fromText t+                 JsonData v     -> BL.toStrict $ encode v       -- SHA1 hash for filename-      let fname = T.pack (showDigest (sha1 bl)) <>+      let fname = T.pack (show (hashWith SHA1 bs)) <>             case extensionFromMimeType mt of               Nothing  -> ""               Just ext -> "." <> ext-      insertMedia (T.unpack fname) (Just mt) bl+      insertMedia (T.unpack fname) (Just mt) (BL.fromStrict bs)       return $ B.para $ B.imageWith ("",[],metaPairs) fname "" mempty      dataBlock ("text/html", TextualData t)
src/Text/Pandoc/Readers/JATS.hs view
@@ -21,7 +21,7 @@ import Data.Char (isDigit, isSpace) import Data.Default import Data.Generics-import Data.List (foldl', intersperse)+import qualified Data.List as L import qualified Data.Map as Map import Data.Maybe (maybeToList, fromMaybe, catMaybes) import Data.Text (Text)@@ -31,7 +31,7 @@ import Text.Pandoc.Builder import Text.Pandoc.Class.PandocMonad (PandocMonad) import Text.Pandoc.Options-import Text.Pandoc.Shared (safeRead, extractSpaces)+import Text.Pandoc.Shared (safeRead) import Text.Pandoc.Walk (walk) import Text.Pandoc.XML.Light import Text.TeXMath (readMathML, writeTeX)@@ -290,11 +290,11 @@                      let items = filterChildren (named "def") e'                      terms' <- mapM getInlines terms                      items' <- mapM getBlocks items-                     return (mconcat $ intersperse (str "; ") terms', items')+                     return (mconcat $ L.intersperse (str "; ") terms', items')          parseFigure = do            modify $ \st -> st{ jatsInFigure = True }            capt <- case filterChild (named "caption") e of-                     Just t  -> mconcat . intersperse linebreak <$>+                     Just t  -> mconcat . L.intersperse linebreak <$>                                 mapM getInlines (filterChildren (const True) t)                      Nothing -> return mempty            contents <- getBlocks e@@ -350,7 +350,7 @@                             n <- safeRead $ "0" <> T.filter (\x -> isDigit x || x == '.') w                             if n > 0 then Just n else Nothing                       let firstBody = fromMaybe [] (headMay multipleBodyRowElements)-                      let numrows = foldl' max 0 $ map length firstBody+                      let numrows = L.foldl' max 0 $ map length firstBody                       let aligns = case colspecs of                                      [] -> replicate numrows AlignDefault                                      cs -> map toAlignment cs@@ -388,7 +388,7 @@                                   Just t -> read $ T.unpack t                                   Nothing -> if isBook || n == 0 then n + 1 else n                       headerText <- case filterChild (named "title") e of-                                       Just t  -> case maybeAttrValue "supress" t of+                                       Just t  -> case maybeAttrValue "suppress" t of                                                      Just s -> if s == "no"                                                                  then getInlines t                                                                  else return mempty@@ -733,8 +733,7 @@         "fn" -> note . mconcat <$>                          mapM parseBlock (elContent e)         _          -> innerInlines id-   where innerInlines f = extractSpaces f . mconcat <$>-                          mapM parseInline (elContent e)+   where innerInlines f = f . mconcat <$> mapM parseInline (elContent e)          codeWithLang = do            let classes' = case attrValue "language" e of                                "" -> []@@ -757,7 +756,9 @@                             filterChildren (named  "tex-math") whereToLook                 mathMLs = map mathML $                             filterChildren isMathML whereToLook-            return . para . head . take 1 . map constructor $ texMaths ++ mathMLs+            case texMaths ++ mathMLs of+              [] -> return mempty+              (m:_) -> return $ para (constructor m)  mathML :: Element -> Text mathML x =
src/Text/Pandoc/Readers/Jira.hs view
@@ -2,10 +2,10 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Readers.Jira-   Copyright   : © 2019-2023 Albert Krewinkel+   Copyright   : © 2019-2024 Albert Krewinkel    License     : GPL-2.0-or-later -   Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>  Conversion of jira wiki formatted plain text to 'Pandoc' document. -}
src/Text/Pandoc/Readers/LaTeX.hs view
@@ -4,7 +4,7 @@ {-# LANGUAGE ViewPatterns          #-} {- |    Module      : Text.Pandoc.Readers.LaTeX-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -52,8 +52,8 @@ import Text.Pandoc.TeX (Tok (..), TokType (..)) import Text.Pandoc.Readers.LaTeX.Parsing import Text.Pandoc.Readers.LaTeX.Citation (citationCommands, cites)-import Text.Pandoc.Readers.LaTeX.Math (dollarsMath, inlineEnvironments,-                                       inlineEnvironment,+import Text.Pandoc.Readers.LaTeX.Math (withMathMode, dollarsMath,+                                       inlineEnvironments, inlineEnvironment,                                        mathDisplay, mathInline,                                        newtheorem, theoremstyle, proof,                                        theoremEnvironment)@@ -67,6 +67,7 @@ import Text.Pandoc.Readers.LaTeX.Inline (acronymCommands, refCommands,                                          nameCommands, charCommands,                                          accentCommands,+                                         miscCommands,                                          biblatexInlineCommands,                                          verbCommands, rawInlineOr,                                          listingsLanguage)@@ -109,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' @@ -123,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{@@ -143,16 +157,28 @@   toks <- getInputTokens   snd <$> (           rawLaTeXParser toks-             (macroDef (const mempty) <|>+             (makeAtLetterSection <|>+              macroDef (const mempty) <|>               do choice (map controlSeq                    ["include", "input", "subfile", "usepackage"])                  skipMany opt                  braced                  return mempty) blocks       <|> rawLaTeXParser toks-           (environment <|> blockCommand)+           (void (environment <|> blockCommand))            (mconcat <$> many (block <|> beginOrEndCommand))) +makeAtLetterSection :: PandocMonad m => LP m ()+makeAtLetterSection = try $ do+  controlSeq "makeatletter"+  void $ manyTill+    (   whitespace+    <|> newlineTok+    <|> macroDef (const ())+    <|> void environment+    <|> void blockCommand+    ) (controlSeq "makeatother")+ -- See #4667 for motivation; sometimes people write macros -- that just evaluate to a begin or end command, which blockCommand -- won't accept.@@ -176,8 +202,7 @@           (   rawLaTeXParser toks               (mempty <$ (controlSeq "input" >> skipMany rawopt >> braced))               inlines-          <|> rawLaTeXParser toks (inlineEnvironment <|> inlineCommand')-              inlines+          <|> rawLaTeXParser toks (void inline) inlines           )   finalbraces <- mconcat <$> many (try (string "{}")) -- see #5439   return $ raw <> T.pack finalbraces@@ -186,7 +211,7 @@ inlineCommand = do   lookAhead (try (char '\\' >> letter))   toks <- getInputTokens-  fst <$> rawLaTeXParser toks (inlineEnvironment <|> inlineCommand')+  fst <$> rawLaTeXParser toks (void (inlineEnvironment <|> inlineCommand'))           inlines  -- inline elements:@@ -331,6 +356,7 @@ inlineCommands :: PandocMonad m => M.Map Text (LP m Inlines) inlineCommands = M.unions   [ accentCommands tok+  , miscCommands   , citationCommands inline   , siunitxCommands tok   , acronymCommands@@ -343,6 +369,12 @@   , biblatexInlineCommands tok   , rest ]  where+  disableLigatures p = do+    oldLigatures <- sLigatures <$> getState+    updateState (\s -> s{ sLigatures = False })+    res <- p+    updateState (\s -> s{ sLigatures = oldLigatures })+    pure res   rest = M.fromList     [ ("emph", extractSpaces emph <$> tok)     , ("textit", extractSpaces emph <$> tok)@@ -352,7 +384,7 @@     , ("textmd", extractSpaces (spanWith ("",["medium"],[])) <$> tok)     , ("textrm", extractSpaces (spanWith ("",["roman"],[])) <$> tok)     , ("textup", extractSpaces (spanWith ("",["upright"],[])) <$> tok)-    , ("texttt", formatCode nullAttr <$> tok)+    , ("texttt", formatCode nullAttr <$> disableLigatures tok)     , ("alert", skipopts >> spanWith ("",["alert"],[]) <$> tok) -- beamer     , ("textsuperscript", extractSpaces superscript <$> tok)     , ("textsubscript", extractSpaces subscript <$> tok)@@ -363,9 +395,11 @@     , ("hbox", rawInlineOr "hbox" $ processHBox <$> tok)     , ("vbox", rawInlineOr "vbox" tok)     , ("lettrine", rawInlineOr "lettrine" lettrine)-    , ("(", mathInline . untokenize <$> manyTill anyTok (controlSeq ")"))-    , ("[", mathDisplay . untokenize <$> manyTill anyTok (controlSeq "]"))-    , ("ensuremath", mathInline . untokenize <$> braced)+    , ("(", withMathMode+        (mathInline . untokenize <$> manyTill anyTok (controlSeq ")")))+    , ("[", withMathMode+        (mathDisplay . untokenize <$> manyTill anyTok (controlSeq "]")))+    , ("ensuremath", withMathMode (mathInline . untokenize <$> braced))     , ("texorpdfstring", const <$> tok <*> tok)     -- old TeX commands     , ("em", extractSpaces emph <$> inlines)@@ -386,20 +420,19 @@     , ("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                            -- for listings     , ("includegraphics", do options <- option [] keyvals-                             src <- braced-                             mkImage options .-                               unescapeURL .-                               removeDoubleQuotes $ untokenize src)+                             src <- bracedFilename+                             mkImage options . unescapeURL $ src)     -- svg     , ("includesvg",      do options <- option [] keyvals-                             src <- braced-                             mkImage options .-                               unescapeURL .-                               removeDoubleQuotes $ untokenize src)+                             src <- bracedFilename+                             mkImage options . unescapeURL $ src)     -- hyperref     , ("url", (\url -> linkWith ("",["uri"],[]) url "" (str url))                         . unescapeURL . untokenize <$> bracedUrl)@@ -418,7 +451,6 @@     , ("textcolor", coloredInline "color")     , ("colorbox", coloredInline "background-color")     -- etoolbox-    , ("ifstrequal", ifstrequal)     , ("newtoggle", braced >>= newToggle)     , ("toggletrue", braced >>= setToggle True)     , ("togglefalse", braced >>= setToggle False)@@ -436,8 +468,19 @@     , ("ifdim", ifdim)     -- generally only used in \date     , ("today", today)+    -- this is used internally by pandoc but the definition is too complicated+    -- for pandoc to handle (see #11140):+    , ("pandocbounded", tok)     ] +bracedFilename :: PandocMonad m => LP m Text+bracedFilename =+  removeDoubleQuotes . T.strip . untokenize . filter (not . isComment) <$> braced++isComment :: Tok -> Bool+isComment (Tok _ Comment _) = True+isComment _ = False+ today :: PandocMonad m => LP m Inlines today =   text . T.pack . showGregorian . localDay . zonedTimeToLocalTime@@ -449,6 +492,39 @@   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) _)   | Just lab <- lookup "label" kvs = do@@ -533,9 +609,9 @@ ifToggle = do   name <- braced   spaces-  yes <- braced+  yes <- withVerbatimMode braced   spaces-  no <- braced+  no <- withVerbatimMode braced   toggles <- sToggles <$> getState   TokStream _ inp <- getInput   let name' = untokenize name@@ -547,18 +623,6 @@                   report $ UndefinedToggle name' pos   return () -ifstrequal :: (PandocMonad m, Monoid a) => LP m a-ifstrequal = do-  str1 <- tok-  str2 <- tok-  ifequal <- braced-  ifnotequal <- braced-  TokStream _ ts <- getInput-  if str1 == str2-     then setInput $ TokStream False (ifequal ++ ts)-     else setInput $ TokStream False (ifnotequal ++ ts)-  return mempty- coloredInline :: PandocMonad m => Text -> LP m Inlines coloredInline stylename = do   skipopts@@ -628,6 +692,7 @@         do eatOneToken            report $ ParsingUnescaped t pos            return $ str t+  ligatures <- sLigatures <$> getState   case toktype of     Comment     -> mempty <$ eatOneToken     Spaces      -> space <$ eatOneToken@@ -635,14 +700,19 @@     Word        -> str t <$ eatOneToken     Symbol      ->       case t of-        "-"     -> eatOneToken *>+        "-" | ligatures+                -> eatOneToken *>                     option (str "-") (symbol '-' *>                       option (str "–") (str "—" <$ symbol '-'))         "'"     -> eatOneToken *>-                    option (str "’") (str  "”" <$ symbol '\'')+                    option (str "’") (str  "”" <$ (guard ligatures *> symbol '\''))         "~"     -> str "\160" <$ eatOneToken-        "`"     -> doubleQuote <|> singleQuote <|> symbolAsString-        "\""    -> doubleQuote <|> singleQuote <|> symbolAsString+        "`" | ligatures+                -> doubleQuote <|> singleQuote <|> (str "‘" <$ symbol '`')+            | otherwise+                -> str "‘" <$ symbol '`'+        "\"" | ligatures+                -> doubleQuote <|> singleQuote <|> symbolAsString         "“"     -> doubleQuote <|> symbolAsString         "‘"     -> singleQuote <|> symbolAsString         "$"     -> dollarsMath <|> unescapedSymbolAsString@@ -719,7 +789,7 @@ doSubfile :: PandocMonad m => LP m Blocks doSubfile = do   skipMany opt-  f <- T.unpack . removeDoubleQuotes . T.strip . untokenize <$> braced+  f <- T.unpack <$> bracedFilename   oldToks <- getInput   setInput $ TokStream False []   insertIncluded (ensureExtension (/= "") ".tex" f)@@ -737,7 +807,7 @@           _ -> const False   skipMany opt   fs <- map (T.unpack . removeDoubleQuotes . T.strip) . T.splitOn "," .-         untokenize <$> braced+         untokenize . filter (not . isComment) <$> braced   mapM_ (insertIncluded . ensureExtension isAllowed ".tex") fs   return mempty @@ -745,7 +815,7 @@ usepackage = do   skipMany opt   fs <- map (T.unpack . removeDoubleQuotes . T.strip) . T.splitOn "," .-         untokenize <$> braced+           untokenize . filter (not . isComment) <$> braced   let parsePackage f = do         TokStream _ ts <- getIncludedToks (ensureExtension (== ".sty") ".sty" f)         parseFromToks (do _ <- blocks@@ -915,7 +985,7 @@    , ("address", mempty <$ (skipopts *> tok >>= addMeta "address"))    , ("signature", mempty <$ (skipopts *> authors))    , ("date", mempty <$ (skipopts *> tok >>= addMeta "date"))-   , ("newtheorem", newtheorem inline)+   , ("newtheorem", newtheorem)    , ("theoremstyle", theoremstyle)    -- KOMA-Script metadata commands    , ("extratitle", mempty <$ (skipopts *> tok >>= addMeta "extratitle"))@@ -941,6 +1011,7 @@    , ("paragraph*", section ("",["unnumbered"],[]) 4)    , ("subparagraph", section nullAttr 5)    , ("subparagraph*", section ("",["unnumbered"],[]) 5)+   , ("minisec", section ("",["unnumbered","unlisted"],[]) 6) -- from KOMA    -- beamer slides    , ("frametitle", section nullAttr 3)    , ("framesubtitle", section nullAttr 4)@@ -999,6 +1070,11 @@    , ("epigraph", epigraph)    -- alignment    , ("raggedright", pure mempty)+   -- etoolbox+   , ("newtoggle", braced >>= newToggle)+   , ("toggletrue", braced >>= setToggle True)+   , ("togglefalse", braced >>= setToggle False)+   , ("iftoggle", try $ ifToggle >> block)    ]  skipSameFileToks :: PandocMonad m => LP m ()@@ -1007,15 +1083,16 @@     skipMany $ infile (sourceName pos)  environments :: PandocMonad m => M.Map Text (LP m Blocks)-environments = M.union (tableEnvironments blocks inline) $+environments = M.union (tableEnvironments block inline) $    M.fromList    [ ("document", env "document" blocks <* skipMany anyTok)    , ("abstract", mempty <$ (env "abstract" blocks >>= addMeta "abstract"))    , ("sloppypar", env "sloppypar" blocks)    , ("letter", env "letter" letterContents)-   , ("minipage", env "minipage" $-          skipopts *> spaces *> optional braced *> spaces *> blocks)-   , ("figure", env "figure" $ skipopts *> figure')+   , ("minipage", divWith ("",["minipage"],[]) <$>+       env "minipage" (skipopts *> spaces *> optional braced *> spaces *> blocks))+   , ("figure", env "figure" figure')+   , ("figure*", env "figure*" figure')    , ("subfigure", env "subfigure" $ skipopts *> tok *> figure')    , ("center", divWith ("", ["center"], []) <$> env "center" blocks)    , ("quote", blockQuote <$> env "quote" blocks)@@ -1041,12 +1118,7 @@    , ("ly", rawVerbEnv "ly")    -- amsthm    , ("proof", proof blocks opt)-   -- etoolbox-   , ("ifstrequal", ifstrequal)-   , ("newtoggle", braced >>= newToggle)-   , ("toggletrue", braced >>= setToggle True)-   , ("togglefalse", braced >>= setToggle False)-   , ("iftoggle", try $ ifToggle >> block)+   -- other    , ("CSLReferences", braced >> braced >> env "CSLReferences" blocks)    , ("otherlanguage", env "otherlanguage" otherlanguageEnv)    ]@@ -1084,7 +1156,7 @@   name <- untokenize <$> braced   M.findWithDefault mzero name environments <|>     langEnvironment name <|>-    theoremEnvironment blocks opt name <|>+    theoremEnvironment blocks inlines opt name <|>     if M.member name (inlineEnvironments                        :: M.Map Text (LP PandocPure Inlines))        then mzero@@ -1187,15 +1259,18 @@  figure' :: PandocMonad m => LP m Blocks figure' = try $ do+  sp+  poshint <- option "" $ untokenize <$> bracketedToks+  sp   resetCaption   innerContent <- many $ try (Left <$> label) <|> (Right <$> block)   let content = walk go $ mconcat $ snd $ partitionEithers innerContent   st <- getState   let caption' = fromMaybe B.emptyCaption $ sCaption st   let mblabel  = sLastLabel st-  let attr     = case mblabel of-                   Just lab -> (lab, [], [])-                   Nothing  -> nullAttr+  let kvs = [("latex-placement", poshint) | not (T.null poshint)]+  let ident = fromMaybe "" mblabel+  let attr  = (ident, [], kvs)   case mblabel of     Nothing   -> pure ()     Just lab  -> do
src/Text/Pandoc/Readers/LaTeX/Inline.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE ViewPatterns          #-} {- |    Module      : Text.Pandoc.Readers.LaTeX.Inline-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -14,6 +14,7 @@   , verbCommands   , charCommands   , accentCommands+  , miscCommands   , nameCommands   , biblatexInlineCommands   , refCommands@@ -183,6 +184,43 @@   , ("Verb", doverb)   ] +miscCommands :: PandocMonad m => M.Map Text (LP m Inlines)+miscCommands =+  M.fromList+  [ ("pounds", lit "£")+  , ("euro", lit "€")+  , ("copyright", lit "©")+  , ("textasciicircum", lit "^")+  , ("textasciitilde", lit "~")+  , ("textbaht", lit "฿")+  , ("textblank", lit "␢")+  , ("textbigcircle", lit "○")+  , ("textbrokenbar", lit "¦")+  , ("textbullet", lit "•")+  , ("textcentoldstyle", lit "¢")+  , ("textcopyright", lit "©")+  , ("textdagger", lit "†")+  , ("textdegree", lit "°")+  , ("textdollar", lit "$")+  , ("textdong", lit "₫")+  , ("textlira", lit "₤")+  , ("textmu", lit "μ")+  , ("textmusicalnote", lit "♪")+  , ("textonehalf", lit "½")+  , ("textonequarter", lit "¼")+  , ("textparagraph", lit "¶")+  , ("textpertenthousand", lit "‱")+  , ("textpeso", lit "₱")+  , ("textquotesingle", lit "'")+  , ("textregistered", lit "®")+  , ("textsection", lit "§")+  , ("textsterling", lit "£")+  , ("textthreequarters", lit "¾")+  , ("textthreesuperior", lit "³")+  , ("texttwosuperior", lit "²")+  , ("textyen", lit "¥")+  ]+ accentCommands :: PandocMonad m => LP m Inlines -> M.Map Text (LP m Inlines) accentCommands tok =   let accent = accentWith tok@@ -198,11 +236,6 @@   , ("AE", lit "Æ")   , ("oe", lit "œ")   , ("OE", lit "Œ")-  , ("pounds", lit "£")-  , ("euro", lit "€")-  , ("copyright", lit "©")-  , ("textasciicircum", lit "^")-  , ("textasciitilde", lit "~")   , ("H", accent '\779' Nothing) -- hungarumlaut   , ("`", accent '\768' (Just '`')) -- grave   , ("'", accent '\769' (Just '\'')) -- acute@@ -248,6 +281,7 @@   , ("_", lit "_")   , ("{", lit "{")   , ("}", lit "}")+  , ("-", lit "\x00ad") -- soft hyphen   , ("qed", lit "\a0\x25FB")   , ("lq", return (str "‘"))   , ("rq", return (str "’"))@@ -281,6 +315,26 @@   , ("dothyp", lit ".\173")   , ("colonhyp", lit ":\173")   , ("hyp", lit "-")+  -- ngerman (babel)+  , ("glq", lit "‚")+  , ("grq", lit "‘")+  , ("glqq", lit "„")+  , ("grqq", lit "“")+  , ("flq", lit "‹")+  , ("frq", lit "›")+  , ("flqq", lit "«")+  , ("frqq", lit "»")+  , ("dq", lit "\"")+  -- fontspec+  , ("guillemetleft", lit "«")+  , ("guillemotleft", lit "«")+  , ("guillemetright", lit "»")+  , ("guillemotright", lit "»")+  , ("guilsinglleft", lit "‹")+  , ("guilsinglright", lit "›")+  , ("quotedblbase", lit "„")+  , ("quotesinglbase", lit ",")+  , ("textquotedbl", lit "\"")   ]  biblatexInlineCommands :: PandocMonad m
src/Text/Pandoc/Readers/LaTeX/Lang.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Readers.LaTeX.Lang-   Copyright   : Copyright (C) 2018-2023 John MacFarlane+   Copyright   : Copyright (C) 2018-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -171,7 +171,7 @@   , ("indonesian", \_ -> simpleLang "id")   , ("icelandic", \_ -> simpleLang "is")   , ("italian", \_ -> simpleLang "it")-  , ("japanese", \_ -> simpleLang "jp")+  , ("japanese", \_ -> simpleLang "ja")   , ("khmer", \_ -> simpleLang "km")   , ("kurmanji", \_ -> simpleLang "kmr")   , ("kannada", \_ -> simpleLang "kn")@@ -226,6 +226,7 @@        "ngerman" -> Just $ Lang "de" Nothing (Just "DE") [] [] []        "lowersorbian" -> Just $ Lang "dsb" Nothing Nothing [] [] []        "uppersorbian" -> Just $ Lang "hsb" Nothing Nothing [] [] []+       "polytonicgreek" -> Just $ Lang "el" Nothing Nothing ["polyton"] [] []        "polutonikogreek" -> Just $ Lang "el" Nothing Nothing ["polyton"] [] []        "slovene" -> Just $ simpleLang "sl"        "australian" -> Just $ Lang "en" Nothing (Just "AU") [] [] []
src/Text/Pandoc/Readers/LaTeX/Math.hs view
@@ -1,7 +1,9 @@ {-# LANGUAGE OverloadedStrings #-} module Text.Pandoc.Readers.LaTeX.Math-  ( dollarsMath+  ( withMathMode+  , dollarsMath   , inlineEnvironments+  , inlineEnvironmentNames   , inlineEnvironment   , mathInline   , mathDisplay@@ -12,14 +14,14 @@   ) where import Data.Maybe (fromMaybe, mapMaybe, listToMaybe)-import Data.List (foldl')+import qualified Data.List as L import Text.Pandoc.Walk (walk) import Text.Pandoc.Builder as B import qualified Data.Sequence as Seq import Text.Pandoc.Readers.LaTeX.Parsing import Text.Pandoc.TeX import Text.Pandoc.Class-import Text.Pandoc.Shared (trimMath, stripTrailingNewlines)+import Text.Pandoc.Shared (trimMath, trimr) import Text.Pandoc.Parsing hiding (blankline, mathDisplay, mathInline,                             optional, space, spaces, withRaw, (<|>)) import Control.Applicative ((<|>), optional)@@ -27,11 +29,19 @@ import qualified Data.Map as M import Data.Text (Text) +withMathMode :: PandocMonad m => LP m a -> LP m a+withMathMode p = do+  oldMathMode <- sMathMode <$> getState+  updateState $ \s -> s{ sMathMode = True }+  result <- p+  updateState $ \s -> s{ sMathMode = oldMathMode }+  return result+ dollarsMath :: PandocMonad m => LP m Inlines dollarsMath = do   symbol '$'   display <- option False (True <$ symbol '$')-  (do contents <- try $ untokenize <$> pDollarsMath 0+  (do contents <- try $ untokenize <$> withMathMode (pDollarsMath 0)       if display          then mathDisplay contents <$ symbol '$'          else return $ mathInline contents)@@ -69,11 +79,10 @@                                    "\n\\end{" <> y <> "}"  mathEnv :: PandocMonad m => Text -> LP m Text-mathEnv name = do-  skipopts+mathEnv name = withMathMode $ do   optional blankline   res <- manyTill anyTok (end_ name)-  return $ stripTrailingNewlines $ untokenize res+  return $ trimr $ untokenize res  inlineEnvironment :: PandocMonad m => LP m Inlines inlineEnvironment = try $ do@@ -81,22 +90,29 @@   name <- untokenize <$> braced   M.findWithDefault mzero name inlineEnvironments +inlineEnvironmentNames :: [Text]+inlineEnvironmentNames =+  M.keys (inlineEnvironments :: M.Map Text (LP PandocPure Inlines))+ inlineEnvironments :: PandocMonad m => M.Map Text (LP m Inlines) inlineEnvironments = M.fromList [     ("displaymath", mathEnvWith id Nothing "displaymath")   , ("math", math <$> mathEnv "math")-  , ("equation", mathEnvWith id Nothing "equation")-  , ("equation*", mathEnvWith id Nothing "equation*")-  , ("gather", mathEnvWith id (Just "gathered") "gather")-  , ("gather*", mathEnvWith id (Just "gathered") "gather*")-  , ("multline", mathEnvWith id (Just "gathered") "multline")-  , ("multline*", mathEnvWith id (Just "gathered") "multline*")-  , ("eqnarray", mathEnvWith id (Just "aligned") "eqnarray")-  , ("eqnarray*", mathEnvWith id (Just "aligned") "eqnarray*")-  , ("align", mathEnvWith id (Just "aligned") "align")-  , ("align*", mathEnvWith id (Just "aligned") "align*")-  , ("alignat", mathEnvWith id (Just "aligned") "alignat")-  , ("alignat*", mathEnvWith id (Just "aligned") "alignat*")+  , ("equation", mathEnvWith id (Just "equation") "equation")+  , ("equation*", mathEnvWith id (Just "equation*") "equation*")+  , ("gather", mathEnvWith id (Just "gather") "gather")+  , ("gather*", mathEnvWith id (Just "gather*") "gather*")+  , ("multline", mathEnvWith id (Just "multline") "multline")+  , ("multline*", mathEnvWith id (Just "multline*") "multline*")+  , ("eqnarray", mathEnvWith id (Just "eqnarray") "eqnarray")+  , ("eqnarray*", mathEnvWith id (Just "eqnarray*") "eqnarray*")+  , ("align", mathEnvWith id (Just "align") "align")+  , ("align*", mathEnvWith id (Just "align*") "align*")+  , ("alignat", mathEnvWith id (Just "alignat") "alignat")+  , ("alignat*", mathEnvWith id (Just "alignat*") "alignat*")+  , ("flalign", mathEnvWith id (Just "flalign") "flalign")+  , ("flalign*", mathEnvWith id (Just "flalign*") "flalign*")+  -- the following are not yet handled by texmath, so we use substitutes:   , ("dmath", mathEnvWith id Nothing "dmath")   , ("dmath*", mathEnvWith id Nothing "dmath*")   , ("dgroup", mathEnvWith id (Just "aligned") "dgroup")@@ -119,14 +135,14 @@     Just sty -> updateState $ \s -> s{ sLastTheoremStyle = sty }   return mempty -newtheorem :: PandocMonad m => LP m Inlines -> LP m Blocks-newtheorem inline = do+newtheorem :: PandocMonad m => LP m Blocks+newtheorem = do   number <- option True (False <$ symbol '*' <* sp)   name <- untokenize <$> braced   sp   series <- option Nothing $ Just . untokenize <$> bracketedToks   sp-  showName <- tokWith inline+  showName <- braced <|> ((:[]) <$> anyTok)   sp   syncTo <- option Nothing $ Just . untokenize <$> bracketedToks   sty <- sLastTheoremStyle <$> getState@@ -144,7 +160,7 @@ extractLabelFromBlock :: Block -> Maybe Text extractLabelFromBlock (Para inlines) = extractLabel Nothing inlines   where-    extractLabel = foldl' go+    extractLabel = L.foldl' go     go :: Maybe Text -> Inline -> Maybe Text     go (Just t) _ = Just t     go Nothing (Span (_, _, attrs) _) = lookup "label" attrs@@ -152,8 +168,12 @@ extractLabelFromBlock _ = Nothing  theoremEnvironment :: PandocMonad m-                   => LP m Blocks -> LP m Inlines -> Text -> LP m Blocks-theoremEnvironment blocks opt name = do+                   => LP m Blocks+                   -> LP m Inlines+                   -> LP m Inlines+                   -> Text+                   -> LP m Blocks+theoremEnvironment blocks inlines opt name = do   resetCaption   tmap <- sTheoremMap <$> getState   case M.lookup name tmap of@@ -190,7 +210,8 @@                          PlainStyle      -> B.strong                          DefinitionStyle -> B.strong                          RemarkStyle     -> B.emph-       let title = titleEmph (theoremName tspec <> number)+       tname <- parseFromToks inlines (theoremName tspec)+       let title = titleEmph (tname <> number)                       <> optTitle <> "." <> space        return $ divWith (fromMaybe "" mblabel, [name], [])               $ addTitle title
src/Text/Pandoc/Readers/LaTeX/Parsing.hs view
@@ -7,7 +7,7 @@ {-# LANGUAGE ScopedTypeVariables   #-} {- |    Module      : Text.Pandoc.Readers.LaTeX.Parsing-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -141,7 +141,7 @@  data TheoremSpec =   TheoremSpec-    { theoremName    :: Inlines+    { theoremName    :: [Tok]     , theoremStyle   :: TheoremStyle     , theoremSeries  :: Maybe Text     , theoremSyncTo  :: Maybe Text@@ -157,6 +157,7 @@                             , sLogMessages   :: [LogMessage]                             , sIdentifiers   :: Set.Set Text                             , sVerbatimMode  :: Bool+                            , sMathMode      :: Bool                             , sCaption       :: Maybe Caption                             , sInListItem    :: Bool                             , sInTableCell   :: Bool@@ -164,6 +165,7 @@                             , sLastFigureNum :: DottedNum                             , sLastTableNum  :: DottedNum                             , sLastNoteNum   :: Int+                            , sFootnoteTexts :: M.Map Int Blocks                             , sTheoremMap    :: M.Map Text TheoremSpec                             , sLastTheoremStyle :: TheoremStyle                             , sLastLabel     :: Maybe Text@@ -173,6 +175,7 @@                             , sFileContents  :: M.Map Text Text                             , sEnableWithRaw :: Bool                             , sRawTokens     :: IntMap.IntMap [Tok]+                            , sLigatures     :: Bool                             }      deriving Show @@ -185,6 +188,7 @@                               , sLogMessages   = []                               , sIdentifiers   = Set.empty                               , sVerbatimMode  = False+                              , sMathMode      = False                               , sCaption       = Nothing                               , sInListItem    = False                               , sInTableCell   = False@@ -192,6 +196,7 @@                               , sLastFigureNum = DottedNum []                               , sLastTableNum  = DottedNum []                               , sLastNoteNum   = 0+                              , sFootnoteTexts = M.empty                               , sTheoremMap    = M.empty                               , sLastTheoremStyle = PlainStyle                               , sLastLabel     = Nothing@@ -201,6 +206,7 @@                               , sFileContents  = M.empty                               , sEnableWithRaw = True                               , sRawTokens     = IntMap.empty+                              , sLigatures     = True                               }  instance PandocMonad m => HasQuoteContext LaTeXState m where@@ -275,7 +281,7 @@        return result  rawLaTeXParser :: (PandocMonad m, HasMacros s, HasReaderOptions s, Show a)-               => [Tok] -> LP m a -> LP m a+               => [Tok] -> LP m () -> LP m a                -> ParsecT Sources s m (a, Text) rawLaTeXParser toks parser valParser = do   pstate <- getState@@ -297,14 +303,14 @@               Left _    -> mzero               Right ((val, raw), st) -> do                 updateState (updateMacros ((NonEmpty.head (sMacros st)) <>))-                let skipTilPos stopPos = do-                      anyChar+                let rawChar = do                       pos <- getPosition-                      if pos >= stopPos-                         then return ()-                         else skipTilPos stopPos-                skipTilPos endpos-                let result = untokenize raw+                      if pos >= endpos+                         then mzero+                         else anyChar+                result <- (guardEnabled Ext_latex_macros+                             >> (untokenize raw <$ skipMany rawChar))+                          <|> T.pack <$> many rawChar                 -- ensure we end with space if input did, see #4442                 let result' =                       case reverse toks' of@@ -646,13 +652,30 @@     Tok pos Word t : _       | startsWithAlphaNum t -> return $ Tok pos Spaces " " : ts'     _ -> return ts'-trySpecialMacro "iftrue" ts = handleIf True ts-trySpecialMacro "iffalse" ts = handleIf False ts+trySpecialMacro "iftrue" ts = handleIf (ifParser True) ts+trySpecialMacro "iffalse" ts = handleIf (ifParser False) ts+trySpecialMacro "ifmmode" ts = do+  mathMode <- sMathMode <$> getState+  handleIf (ifParser mathMode) ts+trySpecialMacro "ifstrequal" ts = do+  handleIf ifStrequalParser ts trySpecialMacro _ _ = mzero -handleIf :: PandocMonad m => Bool -> [Tok] -> LP m [Tok]-handleIf b ts = do-  res' <- lift $ runParserT (ifParser b) defaultLaTeXState "tokens"+ifStrequalParser :: PandocMonad m => LP m [Tok]+ifStrequalParser = do+  str1 <- braced <|> count 1 anyTok+  str2 <- braced <|> count 1 anyTok+  ifequal <- withVerbatimMode (braced <|> count 1 anyTok)+  ifnotequal <- withVerbatimMode (braced <|> count 1 anyTok)+  TokStream _ ts <- getInput+  return $+    if untokenize str1 == untokenize str2+       then ifequal ++ ts+       else ifnotequal ++ ts++handleIf :: PandocMonad m => LP m [Tok] -> [Tok] -> LP m [Tok]+handleIf parser ts = do+  res' <- lift $ runParserT parser defaultLaTeXState "tokens"                $ TokStream False ts   case res' of     Left _ -> Prelude.fail "Could not parse conditional"@@ -885,7 +908,12 @@   optional sp   ch  <- option False $ True <$ symbol '='   minus <- option "" $ "-" <$ symbol '-'-  Tok _ _ s1 <- satisfyTok isWordTok+  s1 <- option ""+        (do Tok _ _ s1 <- satisfyTok isWordTok+            guard (case T.uncons s1 of+                     Just (c,_) -> isDigit c+                     Nothing -> False)+            pure s1)   s2 <- option "" $ try $ do           symbol '.'           Tok _ _ t <-  satisfyTok isWordTok@@ -893,7 +921,11 @@   let s = s1 <> s2   let (num, rest) = T.span (\c -> isDigit c || c == '.') s   guard $ T.length num > 0-  guard $ rest `elem` ["", "pt","pc","in","bp","cm","mm","dd","cc","sp"]+  guard $ rest `elem`+    ["", "pt","pc","in","bp","cm","mm","dd","cc","sp","ex","em",+     "mu", -- "mu" in math mode only+     "px" -- "px" with pdftex and luatex only+    ]   return $ T.pack ['=' | ch] <> minus <> s  ignore :: (Monoid a, PandocMonad m) => Text -> ParsecT s u m a@@ -925,6 +957,7 @@  keyval :: PandocMonad m => LP m (Text, Text) keyval = try $ do+  sp   key <- untokenize <$> many1 (notFollowedBy (symbol '=') >>                          (symbol '-' <|> symbol '_' <|> satisfyTok isWordTok))   sp@@ -943,6 +976,7 @@                                 Tok _ Symbol "{" -> False                                 Tok _ Symbol "}" -> False                                 _                -> True)))))+  sp   optional (symbol ',')   sp   return (key, T.strip val)
src/Text/Pandoc/Readers/LaTeX/Table.hs view
@@ -25,17 +25,21 @@                   => LP m Blocks                   -> LP m Inlines                   -> M.Map Text (LP m Blocks)-tableEnvironments blocks inline =+tableEnvironments block inline =   M.fromList   [ ("longtable",  env "longtable" $           resetCaption *>-            simpTable blocks inline "longtable" False >>= addTableCaption)+            simpTable block inline "longtable" False >>= addTableCaption)   , ("table",  env "table" $           skipopts *> resetCaption *> blocks >>= addTableCaption)-  , ("tabular*", env "tabular*" $ simpTable blocks inline "tabular*" True)-  , ("tabularx", env "tabularx" $ simpTable blocks inline "tabularx" True)-  , ("tabular", env "tabular"  $ simpTable blocks inline "tabular" False)+  , ("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  hline :: PandocMonad m => LP m () hline = try $ do@@ -55,7 +59,7 @@  lbreak :: PandocMonad m => LP m Tok lbreak = (controlSeq "\\" <|> controlSeq "tabularnewline")-         <* skipopts <* spaces+         <* optional (void rawopt) <* spaces  amp :: PandocMonad m => LP m Tok amp = symbol '&'@@ -137,7 +141,7 @@               -> Text   -- ^ table environment name               -> [([Tok], [Tok])] -- ^ pref/suffixes               -> LP m Row-parseTableRow blocks inline envname prefsufs = do+parseTableRow block inline envname prefsufs = do   notFollowedBy (spaces *> end_ envname)   -- contexts that can contain & that is not colsep:   let canContainAmp (Tok _ (CtrlSeq "begin") _) = True@@ -150,10 +154,13 @@         contents <- mconcat <$>             many ( snd <$> withRaw                      ((lookAhead (controlSeq "parbox") >>-                       void blocks) -- #5711+                       void block) -- #5711                       <|>                       (lookAhead (satisfyTok canContainAmp) >> void inline)                       <|>+                      (lookAhead (controlSeq "begin") >>+                       void block) -- #4746+                      <|>                       (lookAhead (symbol '$') >> void inline))                   <|>                    (do notFollowedBy@@ -164,16 +171,16 @@         option [] (count 1 amp)         return $ map (setpos prefpos) pref ++ contents ++ map (setpos suffpos) suff   rawcells <- mapM celltoks prefsufs-  cells <- mapM (parseFromToks (parseTableCell blocks)) rawcells+  cells <- mapM (parseFromToks (parseTableCell block)) rawcells   spaces   return $ Row nullAttr cells  parseTableCell :: PandocMonad m => LP m Blocks -> LP m Cell-parseTableCell blocks = do+parseTableCell block = do   spaces   updateState $ \st -> st{ sInTableCell = True }-  cell' <-   multicolumnCell blocks-         <|> multirowCell blocks+  cell' <-   multicolumnCell block+         <|> multirowCell block          <|> parseSimpleCell          <|> parseEmptyCell   updateState $ \st -> st{ sInTableCell = False }@@ -183,7 +190,7 @@     -- The parsing of empty cells is important in LaTeX, especially when dealing     -- with multirow/multicolumn. See #6603.     parseEmptyCell = spaces $> emptyCell-    parseSimpleCell = simpleCell <$> (plainify <$> blocks)+    parseSimpleCell = simpleCell <$> (plainify . mconcat <$> many block)   cellAlignment :: PandocMonad m => LP m Alignment@@ -204,7 +211,7 @@                 _          -> bs  multirowCell :: PandocMonad m => LP m Blocks -> LP m Cell-multirowCell blocks = controlSeq "multirow" >> do+multirowCell block = controlSeq "multirow" >> do   -- Full prototype for \multirow macro is:   --     \multirow[vpos]{nrows}[bigstruts]{width}[vmove]{text}   -- However, everything except `nrows` and `text` make@@ -214,16 +221,16 @@   _ <- optional $ symbol '[' *> manyTill anyTok (symbol ']')  -- bigstrut-related   _ <- symbol '{' *> manyTill anyTok (symbol '}')             -- Cell width   _ <- optional $ symbol '[' *> manyTill anyTok (symbol ']')  -- Length used for fine-tuning-  content <- symbol '{' *> (plainify <$> blocks) <* symbol '}'+  content <- symbol '{' *> (plainify . mconcat <$> many block) <* symbol '}'   return $ cell AlignDefault (RowSpan nrows) (ColSpan 1) content  multicolumnCell :: PandocMonad m => LP m Blocks -> LP m Cell-multicolumnCell blocks = controlSeq "multicolumn" >> do+multicolumnCell block = controlSeq "multicolumn" >> do   span' <- fmap (fromMaybe 1 . safeRead . untokenize) braced   alignment <- symbol '{' *> cellAlignment <* symbol '}'    let singleCell = do-        content <- plainify <$> blocks+        content <- plainify . mconcat <$> many block         return $ cell alignment (RowSpan 1) (ColSpan span') content    -- Two possible contents: either a \multirow cell, or content.@@ -231,7 +238,7 @@   -- Note that a \multirow cell can be nested in a \multicolumn,   -- but not the other way around. See #6603   let nestedCell = do-        (Cell _ _ (RowSpan rs) _ bs) <- multirowCell blocks+        (Cell _ _ (RowSpan rs) _ bs) <- multirowCell block         return $ cell                   alignment                   (RowSpan rs)@@ -320,7 +327,7 @@           -> Text           -> Bool           -> LP m Blocks-simpTable blocks inline envname hasWidthParameter = try $ do+simpTable block inline envname hasWidthParameter = try $ do   when hasWidthParameter $ () <$ tokWith inline   skipopts   colspecs <- parseAligns@@ -334,10 +341,10 @@   skipMany hline   spaces   header' <- option [] . try . fmap (:[]) $-             parseTableRow blocks inline envname prefsufs <*+             parseTableRow block inline envname prefsufs <*                lbreak <* many1 hline   spaces-  rows <- sepEndBy (parseTableRow blocks inline envname prefsufs)+  rows <- sepEndBy (parseTableRow block inline envname prefsufs)                     (lbreak <* optional (skipMany hline))   spaces   optional $ controlSeq "caption" *> setCaption inline@@ -372,14 +379,6 @@                         ((_,classes,kvs), Just ident) ->                            (ident,classes,kvs)                         _ -> attr-          return $ addAttrDiv attr'-                 $ maybe id removeLabel mblabel-                 $ Table nullAttr capt spec th tb tf+          return $ maybe id removeLabel mblabel+                 $ Table attr' capt spec th tb tf         go x = return x---- TODO: For now we add a Div to contain table attributes, since--- most writers don't do anything yet with attributes on Table.--- This can be removed when that changes.-addAttrDiv :: Attr -> Block -> Block-addAttrDiv ("",[],[]) b = b-addAttrDiv attr b       = Div attr [b]
src/Text/Pandoc/Readers/Man.hs view
@@ -26,23 +26,40 @@ import Text.Pandoc.Class.PandocMonad (PandocMonad(..), report) import Text.Pandoc.Logging (LogMessage(..)) import Text.Pandoc.Options+import Text.Pandoc.Parsing.Capabilities import Text.Pandoc.Parsing import Text.Pandoc.Walk (query) import Text.Pandoc.Readers.Roff  -- TODO explicit imports import qualified Text.Pandoc.Parsing as P import qualified Data.Foldable as Foldable+import qualified Data.Set as Set import Text.Pandoc.Shared (extractSpaces)  data ManState = ManState { readerOptions   :: ReaderOptions+                         , manLogMessages  :: []LogMessage+                         , manIdentifiers  :: Set.Set T.Text                          , metadata        :: Meta                          , tableCellsPlain :: Bool                          } deriving Show  instance Default ManState where   def = ManState { readerOptions   = def+                 , manLogMessages  = []+                 , manIdentifiers  = Set.empty                  , metadata        = nullMeta                  , tableCellsPlain = True } +instance HasReaderOptions ManState where+  extractReaderOptions = readerOptions++instance HasLogMessages ManState where+  addLogMessage msg st = st{ manLogMessages = msg : manLogMessages st }+  getLogMessages st = reverse $ manLogMessages st++instance HasIdentifierList ManState where+  extractIdentifierList = manIdentifiers+  updateIdentifierList f st = st{ manIdentifiers = f $ manIdentifiers st }+ type ManParser m = P.ParsecT [RoffToken] ManState m  @@ -74,6 +91,7 @@   bs <- many parseBlock <* eof   meta <- metadata <$> getState   let (Pandoc _ blocks) = doc $ mconcat bs+  reportLogMessages   return $ Pandoc meta blocks  parseBlock :: PandocMonad m => ManParser m Blocks@@ -200,9 +218,11 @@   isEmptyLine _ = False  mmacro :: PandocMonad m => T.Text -> ManParser m RoffToken-mmacro mk = msatisfy isControlLine where-  isControlLine (ControlLine mk' _ _) | mk == mk' = True-                            | otherwise = False+mmacro mk = mmacroMatching (== mk)++mmacroMatching :: PandocMonad m => (T.Text -> Bool) -> ManParser m RoffToken+mmacroMatching f = msatisfy isControlLine where+  isControlLine (ControlLine mk _ _) = f mk   isControlLine _ = False  mmacroAny :: PandocMonad m => ManParser m RoffToken@@ -219,8 +239,17 @@   (ControlLine _ args _) <- mmacro "TH"   let adjustMeta =        case args of-         (x:y:z:_) -> setMeta "title" (linePartsToInlines x) .+         (x:y:z:a:b:_) -> setMeta "title" (linePartsToInlines x) .+                          setMeta "section" (linePartsToInlines y) .+                          setMeta "date" (linePartsToInlines z) .+                          setMeta "footer" (linePartsToInlines a) .+                          setMeta "header" (linePartsToInlines b)+         [x,y,z,a] -> setMeta "title" (linePartsToInlines x) .                       setMeta "section" (linePartsToInlines y) .+                      setMeta "date" (linePartsToInlines z) .+                      setMeta "footer" (linePartsToInlines a)+         [x,y,z]   -> setMeta "title" (linePartsToInlines x) .+                      setMeta "section" (linePartsToInlines y) .                       setMeta "date" (linePartsToInlines z)          [x,y]     -> setMeta "title" (linePartsToInlines x) .                       setMeta "section" (linePartsToInlines y)@@ -406,8 +435,10 @@                  else return $ mconcat $ intersperse B.space                              $ map linePartsToInlines args   let lvl = if name == "SH" then 1 else 2-  return $ header lvl contents+  attr <- registerHeader nullAttr contents +  return $ B.headerWith attr lvl contents+ parseBlockQuote :: PandocMonad m => ManParser m Blocks parseBlockQuote = blockQuote <$>    (  (mmacro "RS" *> (mconcat <$> manyTill parseBlock (endmacro "RE")))@@ -470,7 +501,12 @@ continuation :: PandocMonad m => ManParser m Blocks continuation =       (mmacro "RS" *> (mconcat <$> manyTill parseBlock (endmacro "RE")))-  <|> try ((memptyLine <|> bareIP) *> (parsePara <|> parseCodeBlock))+  <|> (bareIP *> parsePara)+  <|> (notFollowedBy (mmacroMatching+                      (`elem` ["TP","IP","LP","P","PP","HP",+                               "RE","RS","SH","SS","SV","YS","TH",+                               "TQ","YS","AT","DT","OP","PD","UC"]))+                                *> parseBlock)  definitionListItem :: PandocMonad m                    => ManParser m (Inlines, [Blocks])
src/Text/Pandoc/Readers/Markdown.hs view
@@ -6,7 +6,7 @@ {-# LANGUAGE ViewPatterns        #-} {- |    Module      : Text.Pandoc.Readers.Markdown-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -22,12 +22,14 @@  import Control.Monad import Control.Monad.Except (throwError)-import Data.Bifunctor (second)+import qualified Data.Bifunctor as Bifunctor import Data.Char (isAlphaNum, isPunctuation, isSpace)-import Data.List (transpose, elemIndex, sortOn, foldl')+import Data.List (transpose, elemIndex, sortOn)+import qualified Data.List as L import qualified Data.Map as M import Data.Maybe import qualified Data.Set as Set+import qualified Data.Attoparsec.Text as A import Data.Text (Text) import qualified Data.Text as T import qualified Data.ByteString as BS@@ -41,17 +43,16 @@ import Text.Pandoc.Class.PandocMonad (PandocMonad (..), report) import Text.Pandoc.Definition as Pandoc import Text.Pandoc.Emoji (emojiToInline)-import Text.Pandoc.Error import Safe.Foldable (maximumBounded) import Text.Pandoc.Logging import Text.Pandoc.Options import Text.Pandoc.Walk (walk) import Text.Pandoc.Parsing hiding (tableCaption) import Text.Pandoc.Readers.HTML (htmlInBalanced, htmlTag, isBlockTag,-                                 isCommentTag, isInlineTag, isTextTag)+                                 isInlineTag, isTextTag) import Text.Pandoc.Readers.LaTeX (applyMacros, rawLaTeXBlock, rawLaTeXInline) import Text.Pandoc.Shared-import Text.Pandoc.URI (escapeURI, isURI)+import Text.Pandoc.URI (escapeURI, isURI, pBase64DataURI) import Text.Pandoc.XML (fromEntities) import Text.Pandoc.Readers.Metadata (yamlBsToMeta, yamlBsToRefs, yamlMetaBlock) -- import Debug.Trace (traceShowId)@@ -189,12 +190,37 @@        <|> T.singleton <$> noneOf "\n"        <|> try (newline >> notFollowedBy blankline >> return " ") --- | Parse a sequence of inline elements between square brackets,--- including inlines between balanced pairs of square brackets.-inlinesInBalancedBrackets :: PandocMonad m => MarkdownParser m (F Inlines)-inlinesInBalancedBrackets =+litBetween :: PandocMonad m => Char -> Char -> MarkdownParser m Text+litBetween op cl = try $ do+  char op+  mconcat <$> (manyTill litChar (char cl))++litCharNoSpace :: PandocMonad m => MarkdownParser m Text+litCharNoSpace = T.singleton <$> escapedChar''+       <|> characterReference+       <|> (snd <$> withRaw attributes)+       <|> T.singleton <$> noneOf "\n \r\t"+ where+   escapedChar'' = do+     c <- escapedChar'+     pure $ case c of+       ' ' -> '\160'+       _ -> c++litBetweenNoSpace :: PandocMonad m => Char -> Char -> MarkdownParser m Text+litBetweenNoSpace op cl = try $ do+  char op+  mconcat <$> (manyTill litCharNoSpace (char cl))++-- | Parse a sequence of elements between square brackets,+-- including between balanced pairs of square brackets.+-- Skip brackets in standard inline escapes, code, raw HTML or LaTeX.+inBalancedBrackets :: PandocMonad m+                   => MarkdownParser m (F a)+                   -> MarkdownParser m (F a)+inBalancedBrackets innerParser =   try $ char '[' >> withRaw (go 1) >>=-          parseFromString inlines . stripBracket . snd+          parseFromString innerParser . stripBracket . snd   where stripBracket t = case T.unsnoc t of           Just (t', ']') -> t'           _              -> t@@ -326,13 +352,9 @@ checkNotes = do   st <- getState   let notesUsed = stateNoteRefs st-  let notesDefined = M.keys (stateNotes' st)-  mapM_ (\n -> unless (n `Set.member` notesUsed) $-                case M.lookup n (stateNotes' st) of-                   Just (pos, _) -> report (NoteDefinedButNotUsed n pos)-                   Nothing -> throwError $-                     PandocShouldNeverHappenError "note not found")-         notesDefined+  forM_ (M.toList (stateNotes' st)) $ \(n, (pos, _)) ->+    unless (n `Set.member` notesUsed) $+      report (NoteDefinedButNotUsed n pos)   referenceKey :: PandocMonad m => MarkdownParser m (F Blocks)@@ -352,11 +374,9 @@                                      try (spnl <* keyValAttr)                     notFollowedBy' (() <$ reference)                     mconcat <$> many1 (notFollowedBy space *> litChar)-  let betweenAngles = try $ char '<' >>-                             mconcat <$> (manyTill litChar (char '>'))   rebase <- option False (True <$ guardEnabled Ext_rebase_relative_paths)   src <- (if rebase then rebasePath pos else id) <$>-             (try betweenAngles <|> sourceURL)+             (try (litBetween '<' '>') <|> sourceURL)   tit <- option "" referenceTitle   attr   <- option nullAttr $ try $               do guardEnabled Ext_link_attributes@@ -365,7 +385,7 @@   addKvs <- option [] $ guardEnabled Ext_mmd_link_attributes                           >> many (try $ spnl >> keyValAttr)   blanklines-  let attr'  = extractIdClass $ foldl' (\x f -> f x) attr addKvs+  let attr'  = extractIdClass $ L.foldl' (\x f -> f x) attr addKvs       target = (escapeURI $ trimr src, tit)   st <- getState   let oldkeys = stateKeys st@@ -625,7 +645,7 @@   spnl   attrs <- many (attribute <* spnl)   char '}'-  return $ foldl' (\x f -> f x) nullAttr attrs+  return $ L.foldl' (\x f -> f x) nullAttr attrs  attribute :: PandocMonad m => MarkdownParser m (Attr -> Attr) attribute = identifierAttr <|> classAttr <|> keyValAttr <|> specialAttr@@ -757,7 +777,7 @@   when (sourceColumn pos /= 1) $ Prelude.fail "Not in first column"   lns <- many1 $ birdTrackLine c   -- if (as is normal) there is always a space after >, drop it-  let lns' = if all (\ln -> T.null ln || T.take 1 ln == " ") lns+  let lns' = if all (\ln -> T.null ln || T.head ln == ' ') lns                 then map (T.drop 1) lns                 else lns   blanklines@@ -794,9 +814,28 @@ blockQuote :: PandocMonad m => MarkdownParser m (F Blocks) blockQuote = do   raw <- emailBlockQuote+  (mbAlert, raw') <-+    (do guardEnabled Ext_alerts+        case raw of+          (t:ts) | "[!" `T.isPrefixOf` t ->+              case T.strip t of+                "[!TIP]" -> pure (Just "tip", ts)+                "[!WARNING]" -> pure (Just "warning", ts)+                "[!IMPORTANT]" -> pure (Just "important", ts)+                "[!CAUTION]" -> pure (Just "caution", ts)+                "[!NOTE]" -> pure (Just "note", ts)+                _ -> pure (Nothing, raw)+          _ -> pure (Nothing, raw))+      <|> pure (Nothing, raw)   -- parse the extracted block, which may contain various block elements:-  contents <- parseFromString' parseBlocks $ T.intercalate "\n" raw <> "\n\n"-  return $ B.blockQuote <$> contents+  contents <- parseFromString' parseBlocks $ T.intercalate "\n" raw' <> "\n\n"+  return $+    case mbAlert of+      Nothing -> B.blockQuote <$> contents+      Just alert ->+        (B.divWith ("", [alert], [])+          . (B.divWith ("", ["title"], []) (B.para (B.str (T.toTitle alert))) <>))+           <$> contents  -- -- list blocks@@ -841,7 +880,9 @@        return (num, style, delim))  listStart :: PandocMonad m => MarkdownParser m ()-listStart = bulletListStart <|> Control.Monad.void (orderedListStart Nothing)+listStart = bulletListStart+        <|> Control.Monad.void (orderedListStart Nothing)+        <|> defListStart  listLine :: PandocMonad m => Int -> MarkdownParser m Text listLine continuationIndent = try $ do@@ -851,15 +892,7 @@   notFollowedByHtmlCloser   notFollowedByDivCloser   optional (() <$ gobbleSpaces continuationIndent)-  listLineCommon--listLineCommon :: PandocMonad m => MarkdownParser m Text-listLineCommon = T.concat <$> manyTill-              (  many1Char (satisfy $ \c -> c `notElem` ['\n', '<', '`'])-             <|> fmap snd (withRaw code)-             <|> fmap (renderTags . (:[]) . fst) (htmlTag isCommentTag)-             <|> countChar 1 anyChar-              ) newline+  anyLine  -- parse raw text for one list item, excluding start marker and continuations rawListItem :: PandocMonad m@@ -873,7 +906,7 @@   let continuationIndent = if fourSpaceRule                               then 4                               else sourceColumn pos2 - sourceColumn pos1-  first <- listLineCommon+  first <- anyLine   rest <- many (do notFollowedBy listStart                    notFollowedBy (() <$ codeBlockFenced)                    notFollowedBy blankline@@ -971,67 +1004,39 @@  -- definition lists -defListMarker :: PandocMonad m => MarkdownParser m ()-defListMarker = do-  sps <- nonindentSpaces+defListStart :: PandocMonad m => MarkdownParser m ()+defListStart = do+  nonindentSpaces   char ':' <|> char '~'-  tabStop <- getOption readerTabStop-  let remaining = tabStop - (T.length sps + 1)-  if remaining > 0-     then try (count remaining (char ' ')) <|> string "\t" <|> many1 spaceChar-     else mzero-  return ()+  gobbleSpaces 1 <|> () <$ lookAhead newline+  try (gobbleAtMostSpaces 3 >> notFollowedBy spaceChar) <|> return () -definitionListItem :: PandocMonad m => Bool -> MarkdownParser m (F (Inlines, [Blocks]))-definitionListItem compact = try $ do+definitionListItem :: PandocMonad m => MarkdownParser m (F (Inlines, [Blocks]))+definitionListItem = try $ do   rawLine' <- anyLine-  raw <- many1 $ defRawBlock compact   term <- parseFromString' (trimInlinesF <$> inlines) rawLine'-  contents <- mapM (parseFromString' parseBlocks . (<> "\n")) raw+  isTight <- (False <$ blanklines) <|> pure True+  fourSpaceRule <- (True <$ guardEnabled Ext_four_space_rule) <|> pure False+  contents <- many1 $ listItem fourSpaceRule defListStart   optional blanklines-  return $ liftM2 (,) term (sequence contents)+  return $ liftM2 (,)+              term+              ((if isTight+                   then fmap (fmap (fmap paraToPlain))+                   else id) (sequence contents)) -defRawBlock :: PandocMonad m => Bool -> MarkdownParser m Text-defRawBlock compact = try $ do-  hasBlank <- option False $ blankline >> return True-  defListMarker-  firstline <- anyLineNewline-  let dline = try-               ( do notFollowedBy blankline-                    notFollowedByHtmlCloser-                    notFollowedByDivCloser-                    if compact -- laziness not compatible with compact-                       then () <$ indentSpaces-                       else (() <$ indentSpaces)-                             <|> notFollowedBy defListMarker-                    anyLine )-  rawlines <- many dline-  cont <- fmap T.concat $ many $ try $ do-            trailing <- option "" blanklines-            ln <- indentSpaces >> notFollowedBy blankline >> anyLine-            lns <- many dline-            return $ trailing <> T.unlines (ln:lns)-  return $ trimr (firstline <> T.unlines rawlines <> cont) <>-            if hasBlank || not (T.null cont) then "\n\n" else ""+paraToPlain :: Block -> Block+paraToPlain (Para ils) = Plain ils+paraToPlain x = x  definitionList :: PandocMonad m => MarkdownParser m (F Blocks) definitionList = try $ do+  guardEnabled Ext_definition_lists   lookAhead (anyLine >>              optional (blankline >> notFollowedBy (Control.Monad.void table)) >>              -- don't capture table caption as def list!-             defListMarker)-  compactDefinitionList <|> normalDefinitionList--compactDefinitionList :: PandocMonad m => MarkdownParser m (F Blocks)-compactDefinitionList = do-  guardEnabled Ext_compact_definition_lists-  items <- fmap sequence $ many1 $ definitionListItem True-  return $ B.definitionList <$> fmap compactifyDL items--normalDefinitionList :: PandocMonad m => MarkdownParser m (F Blocks)-normalDefinitionList = do-  guardEnabled Ext_definition_lists-  items <- fmap sequence $ many1 $ definitionListItem False+             defListStart)+  items <- fmap sequence $ many1 definitionListItem   return $ B.definitionList <$> items  --@@ -1064,8 +1069,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@@ -1087,8 +1091,12 @@   let alt = case "alt" `lookup` attribs of               Just alt'       -> B.text alt'               _               -> capt-      attribs' = filter ((/= "alt") . fst) attribs-      figattr = (ident, mempty, mempty)+      attribs' = filter ((/= "latex-placement") . fst)+                    (filter ((/= "alt") . fst) attribs)+      figattribs = case lookup "latex-placement" attribs of+        Just p -> [("latex-placement", p)]+        _      -> mempty+      figattr = (ident, mempty, figattribs)       caption = B.simpleCaption $ B.plain capt       figbody = B.plain $ B.imageWith ("", classes, attribs') url title alt   in B.figureWith figattr caption figbody@@ -1155,7 +1163,7 @@                 many1 ((<>) <$> rawLaTeXBlock <*> spnl'))   return $ case B.toList result of                 [RawBlock _ cs]-                  | T.all (`elem` [' ','\t','\n']) cs -> return mempty+                  | T.all (\c -> c == ' ' || c == '\t' || c == '\n') cs -> return mempty                 -- don't create a raw block for suppressed macro defs                 _ -> return result @@ -1191,7 +1199,9 @@         return (return (B.rawBlock "html" $ stripMarkdownAttribute raw) <>                 contents <>                 return (B.rawBlock "html" rawcloser)))-      <|> return (return (B.rawBlock "html" raw) <> contents)+      <|> if T.all isSpace raw+             then return mempty+             else return (return (B.rawBlock "html" raw) <> contents)   updateState $ \st -> st{ stateInHtmlBlock = oldInHtmlBlock }   return result @@ -1234,7 +1244,7 @@ -- one (or zero) line of text. simpleTableHeader :: PandocMonad m                   => Bool  -- ^ Headerless table-                  -> MarkdownParser m (F [Blocks], [Alignment], [Int])+                  -> MarkdownParser m (F [[Blocks]], [Alignment], [Int]) simpleTableHeader headless = try $ do   rawContent  <- if headless                     then return ""@@ -1245,7 +1255,7 @@   let (lengths, lines') = unzip dashes   let indices  = scanl (+) (T.length initSp) lines'   -- If no header, calculate alignment on basis of first row of text-  rawHeads <- fmap (tail . splitTextByIndices (init indices)) $+  rawHeads <- fmap (drop 1 . splitTextByIndices (init indices)) $               if headless                  then lookAhead anyLine                  else return rawContent@@ -1256,7 +1266,7 @@   heads <- fmap sequence            $             mapM (parseFromString' (mconcat <$> many plain).trim) rawHeads'-  return (heads, aligns, indices)+  return (fmap (:[]) heads, aligns, indices)  -- Returns an alignment type for a table, based on a list of strings -- (the rows of the column header) and a number (the length of the@@ -1269,7 +1279,7 @@   let nonempties = filter (not . T.null) $ map trimr strLst       (leftSpace, rightSpace) =            case sortOn T.length nonempties of-                 (x:_) -> (T.head x `elem` [' ', '\t'], T.length x < len)+                 (x:_) -> (T.head x `elem` [' ', '\t'], realLength x < len)                  []    -> (False, False)   in  case (leftSpace, rightSpace) of         (True,  False) -> AlignRight@@ -1292,8 +1302,7 @@ rawTableLine indices = do   notFollowedBy' (blanklines' <|> tableFooter)   line <- anyLine-  return $ map trim $ tail $-           splitTextByIndices (init indices) line+  return $ map trim $ drop 1 $ splitTextByIndices (init indices) line  -- Parse a table line and return a list of lists of blocks (columns). tableLine :: PandocMonad m@@ -1313,14 +1322,19 @@  -- Parses a table caption:  inlines beginning with 'Table:' -- and followed by blank lines.-tableCaption :: PandocMonad m => MarkdownParser m (F Inlines)+tableCaption :: PandocMonad m => MarkdownParser m (F Inlines, Attr) tableCaption = do   guardEnabled Ext_table_captions   try $ do     skipNonindentSpaces     (string ":" <* notFollowedBy (satisfy isPunctuation)) <|>       (oneOf ['T','t'] >> string "able:")-    trimInlinesF <$> inlines1 <* blanklines+    let attributes' = guardEnabled Ext_table_attributes *> attributes+    ils <- trimInlinesF . mconcat <$>+               many (notFollowedBy (attributes' *> blanklines) *> inline)+    attr <- option nullAttr attributes'+    blanklines+    pure (ils, attr)  -- Parse a simple table with '---' header and one line per row. simpleTable :: PandocMonad m@@ -1334,7 +1348,8 @@               (if headless then tableFooter else tableFooter <|> blanklines')   -- All columns in simple tables have default widths.   let useDefaultColumnWidths tc =-        let cs' = map (second (const ColWidthDefault)) $ tableColSpecs tc+        let cs' = map (Bifunctor.second (const ColWidthDefault)) $+                   tableColSpecs tc         in tc {tableColSpecs = cs'}   return $ useDefaultColumnWidths <$> tableComponents @@ -1351,7 +1366,7 @@  multilineTableHeader :: PandocMonad m                      => Bool -- ^ Headerless table-                     -> MarkdownParser m (F [Blocks], [Alignment], [Int])+                     -> MarkdownParser m (F [[Blocks]], [Alignment], [Int]) multilineTableHeader headless = try $ do   unless headless $      tableSep >> notFollowedBy blankline@@ -1369,10 +1384,10 @@                       []     -> []                       (x:xs) -> reverse (x+1:xs)   rawHeadsList <- if headless-                     then map (:[]) . tail . splitTextByIndices (init indices')+                     then map (:[]) . drop 1 . splitTextByIndices (init indices')                           <$> lookAhead anyLine                      else return $ transpose $ map-                           (tail . splitTextByIndices (init indices'))+                           (drop 1 . splitTextByIndices (init indices'))                            rawContent   let aligns   = zipWith alignType rawHeadsList lengths   let rawHeads = if headless@@ -1380,7 +1395,7 @@                     else map (T.unlines . map trim) rawHeadsList   heads <- fmap sequence $             mapM (parseFromString' (mconcat <$> many plain).trim) rawHeads-  return (heads, aligns, indices')+  return (fmap (:[]) heads, aligns, indices')  -- Parse a grid table:  starts with row of '-' on top, then header -- (which may be grid), then the rows,@@ -1388,7 +1403,20 @@ -- ending with a footer (dashed line followed by blank line). gridTable :: PandocMonad m           => MarkdownParser m (F TableComponents)-gridTable = gridTableWith' NormalizeHeader parseBlocks+gridTable = try $ do+  -- Like other block-level constructs, a grid table may be indented by+  -- up to three spaces.  The underlying grid-table parser expects the+  -- table to begin at the left margin, so strip a uniform indentation+  -- from every line before handing it off.+  indent <- T.length <$> lookAhead nonindentSpaces+  if indent == 0+     then gridTableWith' NormalizeHeader parseBlocks+     else do+       let gridLine = try $ count indent (char ' ')+                              *> lookAhead (oneOf "+|")+                              *> anyLineNewline+       rawTable <- T.concat <$> many1 gridLine+       parseFromString' (gridTableWith' NormalizeHeader parseBlocks) rawTable  pipeBreak :: PandocMonad m => MarkdownParser m ([Alignment], [Int]) pipeBreak = try $ do@@ -1425,7 +1453,7 @@   (rows :: F [[Blocks]]) <- sequence <$>                             mapM (fmap sequence . mapM cellContents) lines''   return $-    toTableComponents' NormalizeHeader aligns widths <$> headCells <*> rows+    toTableComponents' NormalizeHeader aligns widths <$> fmap (:[]) headCells <*> rows  sepPipe :: PandocMonad m => MarkdownParser m () sepPipe = try $ do@@ -1484,7 +1512,8 @@  table :: PandocMonad m => MarkdownParser m (F Blocks) table = try $ do-  frontCaption <- option Nothing (Just <$> tableCaption)+  (frontCaption, frontAttr) <- option (Nothing, nullAttr)+                               (Bifunctor.first Just <$> tableCaption)   tableComponents <-          (guardEnabled Ext_pipe_tables >> try (scanForPipe >> pipeTable)) <|>          (guardEnabled Ext_multiline_tables >> try (multilineTable False)) <|>@@ -1495,13 +1524,14 @@          (guardEnabled Ext_grid_tables >>                 try gridTable) <?> "table"   optional blanklines-  caption <- case frontCaption of-                  Nothing -> option (return mempty) tableCaption-                  Just c  -> return c+  (caption, attr) <- case frontCaption of+                        Nothing -> option (return mempty, nullAttr) tableCaption+                        Just c  -> return (c, frontAttr)   return $ do     caption' <- caption     (TableComponents _attr _capt colspecs th tb tf) <- tableComponents-    return $ B.table (B.simpleCaption $ B.plain caption') colspecs th tb tf+    return $ B.tableWith attr+                (B.simpleCaption $ B.plain caption') colspecs th tb tf  -- -- inline@@ -1523,7 +1553,7 @@      '`'     -> code      '_'     -> strongOrEmph      '*'     -> strongOrEmph-     '^'     -> superscript <|> inlineNote -- in this order bc ^[link](/foo)^+     '^'     -> inlineNote <|> superscript      '['     -> note <|> cite <|> bracketedSpan <|> wikilink B.linkWith <|> link      '!'     -> image      '$'     -> math@@ -1538,7 +1568,7 @@      '\145'  -> smart      '\8220' -> smart      '\147'  -> smart-     '-'     -> smart+     '-'     -> cite <|> smart      '.'     -> smart      '&'     -> return . B.singleton <$> charRef      ':'     -> emoji@@ -1550,7 +1580,8 @@ escapedChar' :: PandocMonad m => MarkdownParser m Char escapedChar' = try $ do   char '\\'-  (guardEnabled Ext_all_symbols_escapable >> satisfy (not . isAlphaNum))+  (guardEnabled Ext_all_symbols_escapable >>+     satisfy (\c -> c /= '\n' && c /= '\r' && not (isAlphaNum c)))      <|> (guardEnabled Ext_angle_brackets_escapable >>             oneOf "\\`*_{}[]()>#+-.!~\"<>")      <|> oneOf "\\`*_{}[]()>#+-.!"@@ -1587,7 +1618,7 @@   guardEnabled Ext_example_lists   try $ do     char '@'-    lab <- mconcat . map T.pack <$>+    lab <- T.pack . concat <$>                       many (many1 alphaNum <|>                             try (do c <- char '_' <|> char '-'                                     cs <- many1 alphaNum@@ -1728,29 +1759,29 @@  superscript :: PandocMonad m => MarkdownParser m (F Inlines) superscript = do-  fmap B.superscript <$> try (do-    char '^'-    mconcat <$> (try regularSuperscript <|> try mmdShortSuperscript))-      where regularSuperscript = many1Till (do guardEnabled Ext_superscript-                                               notFollowedBy spaceChar-                                               notFollowedBy newline-                                               inline) (char '^')-            mmdShortSuperscript = do guardEnabled Ext_short_subsuperscripts-                                     result <- T.pack <$> many1 alphaNum-                                     return $ return $ return $ B.str result+  fmap B.superscript <$> (regularSuperscript <|> mmdShortSuperscript)+      where+        regularSuperscript = do+          guardEnabled Ext_superscript+          litBetweenNoSpace '^' '^' >>= parseFromString inlines+        mmdShortSuperscript = try $ do+          guardEnabled Ext_short_subsuperscripts+          char '^'+          result <- T.pack <$> many1 alphaNum+          return $ return $ B.str result  subscript :: PandocMonad m => MarkdownParser m (F Inlines) subscript = do-  fmap B.subscript <$> try (do-    char '~'-    mconcat <$> (try regularSubscript <|> mmdShortSubscript))-      where regularSubscript = many1Till (do guardEnabled Ext_subscript-                                             notFollowedBy spaceChar-                                             notFollowedBy newline-                                             inline) (char '~')-            mmdShortSubscript = do guardEnabled Ext_short_subsuperscripts-                                   result <- T.pack <$> many1 alphaNum-                                   return $ return $ return $ B.str result+  fmap B.subscript <$> (regularSubscript <|> mmdShortSubscript)+      where+        regularSubscript = do+          guardEnabled Ext_subscript+          litBetweenNoSpace '~' '~' >>= parseFromString inlines+        mmdShortSubscript = try $ do+          guardEnabled Ext_short_subsuperscripts+          char '~'+          result <- T.pack <$> many1 alphaNum+          return $ return $ B.str result  whitespace :: PandocMonad m => MarkdownParser m (F Inlines) whitespace = spaceChar >> return <$> (lb <|> regsp) <?> "whitespace"@@ -1813,31 +1844,40 @@ reference :: PandocMonad m => MarkdownParser m (F Inlines, Text) reference = do   guardDisabled Ext_footnotes <|> notFollowedBy' noteMarker-  withRaw $ trimInlinesF <$> inlinesInBalancedBrackets--parenthesizedChars :: PandocMonad m => MarkdownParser m Text-parenthesizedChars = do-  result <- charsInBalanced '(' ')' litChar-  return $ "(" <> result <> ")"+  withRaw $ trimInlinesF <$> inBalancedBrackets inlines  -- source for a link, with optional title source :: PandocMonad m => MarkdownParser m (Text, Text) source = do   char '('   skipSpaces-  let urlChunk =-            try parenthesizedChars-        <|> (notFollowedBy (oneOf " )") >> litChar)-        <|> try (many1Char spaceChar <* notFollowedBy (oneOf "\"')"))+  let parenthesizedChars = do+        result <- charsInBalanced '(' ')' litChar+        return $ "(" <> result <> ")"+  let linkTitle' = try $ spnl >> linkTitle+  let urlChunk = do+        try parenthesizedChars+          <|> (notFollowedBy (oneOf "\n\r )") >> litChar)+          <|> (lookAhead (oneOf "\n\r") >> notFollowedBy linkTitle' >> litChar)+          <|> try (many1Char spaceChar <* notFollowedBy (oneOf "\"')"))   let sourceURL = T.unwords . T.words . T.concat <$> many urlChunk-  let betweenAngles = try $-         char '<' >> mconcat <$> (manyTill litChar (char '>'))-  src <- try betweenAngles <|> sourceURL-  tit <- option "" $ try $ spnl >> linkTitle+  src <- try (litBetween '<' '>') <|> try base64DataURI <|> sourceURL+  tit <- option "" linkTitle'   skipSpaces   char ')'   return (escapeURI $ trimr src, tit) +base64DataURI :: PandocMonad m => ParsecT Sources s m Text+base64DataURI = do+  Sources ((pos, txt):rest) <- getInput+  let r = A.parse (fst <$> A.match pBase64DataURI) txt+  case r of+    A.Done remaining consumed -> do+      let pos' = incSourceColumn pos (T.length consumed)+      setInput $ Sources ((pos', remaining):rest)+      return consumed+    _ -> mzero+ linkTitle :: PandocMonad m => MarkdownParser m Text linkTitle = quotedTitle '"' <|> quotedTitle '\'' @@ -1845,6 +1885,7 @@   => (Attr -> Text -> Text -> Inlines -> Inlines)   -> MarkdownParser m (F Inlines) wikilink constructor = do+  let attr = (mempty, ["wikilink"], mempty)   titleAfter <-     (True <$ guardEnabled Ext_wikilinks_title_after_pipe) <|>     (False <$ guardEnabled Ext_wikilinks_title_before_pipe)@@ -1856,8 +1897,8 @@           (before, after)             | titleAfter -> (T.drop 1 after, before)             | otherwise -> (before, T.drop 1 after)-    guard $ T.all (`notElem` ['\n','\r','\f','\t']) url-    return . pure . constructor nullAttr url "wikilink" $+    guard $ T.all (\c -> c /= '\n' && c /= '\r' && c /= '\f' && c /= '\t') url+    return . pure . constructor attr url "" $        B.text $ fromEntities title  link :: PandocMonad m => MarkdownParser m (F Inlines)@@ -1901,7 +1942,7 @@  isSmallCapsFontVariant :: Text -> Bool isSmallCapsFontVariant s =-  T.toLower (T.filter (`notElem` [' ', '\t', ';']) s) ==+  T.toLower (T.filter (\c -> c /= ' ' && c /= '\t' && c /= ';') s) ==   "font-variant:small-caps"  regLink :: PandocMonad m@@ -2060,7 +2101,9 @@     char '^'     updateState $ \st -> st{ stateInNote = True                            , stateNoteNumber = stateNoteNumber st + 1 }-    contents <- inlinesInBalancedBrackets+    contents <- withQuoteContext NoQuote $ inBalancedBrackets inlines+    notFollowedBy (char '(' <|> char '[' <|> ('{' <$ attributes))+      -- ^[link](foo)^ is superscript     updateState $ \st -> st{ stateInNote = False }     return $ B.note . B.para <$> contents @@ -2102,30 +2145,29 @@ divHtml = do   guardEnabled Ext_native_divs   try $ do-    (TagOpen _ attrs, rawtag) <- htmlTag (~== TagOpen ("div" :: Text) [])+    openpos <- getPosition+    (TagOpen _ attrs, _) <- htmlTag (~== TagOpen ("div" :: Text) [])     -- we set stateInHtmlBlock so that closing tags that can be either block     -- or inline will not be parsed as inline tags     oldInHtmlBlock <- stateInHtmlBlock <$> getState     updateState $ \st -> st{ stateInHtmlBlock = Just "div" }-    bls <- option "" (blankline >> option "" blanklines)+    optional blanklines     contents <- mconcat <$>                 many (notFollowedBy' (htmlTag (~== TagClose ("div" :: Text)))                       >> block)-    closed <- option False (True <$ htmlTag (~== TagClose ("div" :: Text)))-    if closed-       then do-         updateState $ \st -> st{ stateInHtmlBlock = oldInHtmlBlock }-         let ident = fromMaybe "" $ lookup "id" attrs-         let classes = maybe [] T.words $ lookup "class" attrs-         let keyvals = [(k,v) | (k,v) <- attrs, k /= "id" && k /= "class"]-         return $ B.divWith (ident, classes, keyvals) <$> contents-       else -- avoid backtracing-         return $ return (B.rawBlock "html" (rawtag <> bls)) <> contents+    void (htmlTag (~== TagClose ("div" :: Text))) <|>+       (getPosition >>= report . UnclosedDiv openpos)+    let ident = fromMaybe "" $ lookup "id" attrs+    let classes = maybe [] T.words $ lookup "class" attrs+    let keyvals = [(k,v) | (k,v) <- attrs, k /= "id" && k /= "class"]+    updateState $ \st -> st{ stateInHtmlBlock = oldInHtmlBlock }+    return $ B.divWith (ident, classes, keyvals) <$> contents  divFenced :: PandocMonad m => MarkdownParser m (F Blocks) divFenced = do   guardEnabled Ext_fenced_divs   try $ do+    openpos <- getPosition     string ":::"     skipMany (char ':')     skipMany spaceChar@@ -2135,7 +2177,8 @@     blankline     updateState $ \st ->       st{ stateFencedDivLevel = stateFencedDivLevel st + 1 }-    bs <- mconcat <$> manyTill block divFenceEnd+    bs <- mconcat <$> many (notFollowedBy divFenceEnd >> block)+    divFenceEnd <|> (getPosition >>= report . UnclosedDiv openpos)     updateState $ \st ->       st{ stateFencedDivLevel = stateFencedDivLevel st - 1 }     return $ B.divWith attribs <$> bs@@ -2162,7 +2205,9 @@                              then (\x -> isInlineTag x &&                                          not (isCloseBlockTag x))                              else not . isTextTag-  return $ return $ B.rawInline "html" result+  return $ if T.all isSpace result+              then return mempty+              else return $ B.rawInline "html" result  -- Emoji @@ -2245,7 +2290,7 @@   rest <- option (return []) $ try $ char ';' >> spnl >> citeList   spnl   char ']'-  notFollowedBy $ oneOf "[("+  notFollowedBy $ oneOf "[({"   return $ do     suff' <- suff     rest' <- rest@@ -2268,8 +2313,9 @@ suffix = try $ do   hasSpace <- option False (notFollowedBy nonspaceChar >> return True)   spnl-  rest <- trimInlinesF . mconcat <$> many (notFollowedBy (oneOf ";]") >> inline)-  return $ if hasSpace+  ils <- many (notFollowedBy (oneOf ";]") >> inline)+  let rest = trimInlinesF (mconcat ils)+  return $ if hasSpace && not (null ils)               then (B.space <>) <$> rest               else rest 
+ src/Text/Pandoc/Readers/Mdoc.hs view
@@ -0,0 +1,1469 @@+{-# LANGUAGE CPP  #-}+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE ViewPatterns #-}+{- |+   Module      : Text.Pandoc.Readers.Mdoc+   Copyright   : © 2024 Evan Silberman+   License     : GNU GPL, version 2 or above++   Maintainer  : Evan Silberman <evan@jklol.net>+   Stability   : WIP+   Portability : portable++Conversion of mdoc to 'Pandoc' document.+-}+module Text.Pandoc.Readers.Mdoc (readMdoc) where++import Data.Char (isAsciiLower, toUpper)+import Data.Default (Default)+import Data.Either (fromRight)+import Data.Functor (($>))+import Data.Maybe (catMaybes)+import Control.Monad (mplus, guard, void, when, unless)+import Control.Monad.Except (throwError)+#if MIN_VERSION_base(4,19,0)+import Data.List (intersperse, unsnoc)+#else+import Data.List (intersperse)+#endif+import qualified Data.Map.Strict as M+import qualified Data.Text as T+import Text.Pandoc.Definition (Pandoc(Pandoc), Meta)+import Text.Pandoc.Builder (Blocks, Inlines)+import qualified Text.Pandoc.Builder as B+import Text.Pandoc.Class.PandocMonad (PandocMonad(..))+import Text.Pandoc.Options+import Text.Pandoc.Parsing hiding (uncons)+import Text.Pandoc.Logging+import Text.Pandoc.Readers.Mdoc.Lex+import Text.Pandoc.Readers.Mdoc.Standards+import Text.Parsec (modifyState)+import qualified Text.Pandoc.Parsing as P+import qualified Data.Foldable as Foldable+import Text.Pandoc.Shared (stringify)++#if !MIN_VERSION_base(4,19,0)+unsnoc :: [a] -> Maybe ([a], a)+unsnoc = foldr (\x -> Just . maybe ([], x) (\(~(a, b)) -> (x : a, b))) Nothing+#endif++  {- As a general principle, if mandoc -T lint issues a WARNING admonition+     or worse about a construct, I consider it fair game for this reader to+     do something different than what mandoc does with it, including bailing+     out instead of recovering. -}++data MdocSection+  = ShName+  | ShSynopsis+  | ShAuthors+  | ShSeeAlso+  | ShOther+  deriving (Show, Eq)++-- Declaration order is important: this is the order fields of a reference+-- are printed by mandoc+data ReferenceField =+  Author+  | ArticleTitle+  | BookTitle+  | Publisher+  | Journal+  | TechReportTitle+  | IssueNumber+  | VolumeNumber+  | Url+  | Pages+  | Institution+  | PubLocation+  | PubDate+  | Optional+  deriving (Show, Eq, Ord, Enum)++-- mandoc allows specifying multiple of _any_ reference field, and just+-- prints them all out in document order, even though authors are the only+-- field where this is the documented behavior. There's no lint warning+-- about this either. I'd prefer to do last-one-wins for the non-author+-- fields, which would presumably make it easier to transform the+-- bibliographic data into something else, but for now all I'm doing is+-- printing the references out the same way mandoc does.+type MdocReference = M.Map ReferenceField [T.Text]++data MdocState = MdocState+    { readerOptions :: ReaderOptions+    , metadata :: Meta+    , tableCellsPlain :: Bool+    , spacingMode :: Bool+    , authorNameSplit :: Bool+    , inLineEnclosure :: Bool+    , progName :: Maybe T.Text+    , currentSection :: MdocSection+    , currentReference :: MdocReference+    , logMessages :: [LogMessage]+    }+    deriving (Show)++instance Default MdocState where+    def =+        MdocState+            { readerOptions = def+            , metadata = B.nullMeta+            , tableCellsPlain = True+            , spacingMode = True+            , authorNameSplit = False+            , inLineEnclosure = False+            , currentSection = ShOther+            , currentReference = M.empty+            , progName = Nothing+            , logMessages = []+            }++instance HasLogMessages MdocState where+  addLogMessage msg st = st{ logMessages = msg : logMessages st }+  getLogMessages st = reverse $ logMessages st++type MdocParser m = P.ParsecT [MdocToken] MdocState m+++-- | Read mdoc from an input string and return a Pandoc document.+readMdoc :: (PandocMonad m, ToSources a)+        => ReaderOptions+        -> a+        -> m Pandoc+readMdoc opts s = do+  let Sources inps = toSources s+  tokenz <- mconcat <$> mapM (uncurry lexMdoc) inps+  let state = def {readerOptions = opts} :: MdocState+  eitherdoc <- readWithMTokens parseMdoc state+     (Foldable.toList . unMdocTokens $ tokenz)+  either (throwError . fromParsecError (Sources inps)) return eitherdoc+++readWithMTokens :: PandocMonad m+        => ParsecT [MdocToken] MdocState m a  -- ^ parser+        -> MdocState                         -- ^ initial state+        -> [MdocToken]                       -- ^ input+        -> m (Either ParseError a)+readWithMTokens parser state input =+  runParserT parser state "source" input+++parseMdoc :: PandocMonad m => MdocParser m Pandoc+parseMdoc = do+  optional parsePrologue+  bs <- many parseBlock <* eof+  meta <- metadata <$> getState+  let (Pandoc _ blocks) = B.doc $ mconcat bs+  reportLogMessages+  return $ Pandoc meta blocks++msatisfy :: Monad m+         => (MdocToken -> Bool) -> P.ParsecT [MdocToken] st m MdocToken+msatisfy predic = P.tokenPrim show nextPos testTok+  where+    testTok t     = if predic t then Just t else Nothing+    nextPos _ _ (Macro _ pos':_) = pos'+    nextPos _ _ (Lit _ pos':_) = pos'+    nextPos _ _ (Str _ pos':_) = pos'+    nextPos _ _ (Delim _ _ pos':_) = pos'+    nextPos _ _ (Blank pos':_) = pos'+    nextPos a _ (Eol{}:x:xs) = nextPos a x xs+    nextPos pos _ [Eol] = pos+    nextPos pos _ [] = pos++macro :: PandocMonad m => T.Text -> MdocParser m MdocToken+macro name = msatisfy t where+  t (Macro n _) = n == name+  t _ = False++anyMacro :: PandocMonad m => MdocParser m MdocToken+anyMacro = msatisfy t where+  t (Macro _ _) = True+  t _ = False++emptyMacro :: PandocMonad m => T.Text -> MdocParser m MdocToken+emptyMacro n = macro n <* eol++delim :: PandocMonad m => DelimSide -> MdocParser m MdocToken+delim side = msatisfy t where+  t (Delim s _ _) = side == s+  t _ = False++str :: PandocMonad m => MdocParser m MdocToken+str = msatisfy t where+  t Str{} = True+  t _ = False++lit :: PandocMonad m => MdocParser m MdocToken+lit = msatisfy t where+  t Lit{} = True+  t _ = False++arg :: PandocMonad m => MdocParser m MdocToken+arg = msatisfy t where+  t Lit{} = True+  t Macro{} = True+  t _ = False++literal :: PandocMonad m => T.Text -> MdocParser m MdocToken+literal n = msatisfy t where+  t (Lit n' _) = n == n'+  t _ = False++blank :: PandocMonad m => MdocParser m MdocToken+blank = msatisfy t where+  t Blank{} = True+  t _ = False++eol :: PandocMonad m => MdocParser m ()+eol = void $ msatisfy t where+  t Eol{} = True+  t _ = False++newControlContext :: MdocToken -> Bool+newControlContext Eol{} = True+newControlContext Macro{} = True+newControlContext Str{} = True+newControlContext Blank{} = True+newControlContext Lit{} = False+newControlContext Delim{} = False+++inlineContextEnd :: PandocMonad m => MdocParser m ()+inlineContextEnd = eof <|> (void . lookAhead $ msatisfy newControlContext)++sectionEnd :: PandocMonad m => MdocParser m ()+sectionEnd = eof <|> (void . lookAhead $ macro "Sh")++argsToInlines :: PandocMonad m => MdocParser m Inlines+argsToInlines = do+  ls <- manyTill arg eol+  let strs = map (B.str . toString) ls+  spacify strs++parsePrologue :: PandocMonad m => MdocParser m ()+parsePrologue = do+  macro "Dd"+  date <- argsToInlines+  macro "Dt"+  (Lit title _) <- lit+  (Lit section _) <- lit+  arch <- optionMaybe (toString <$> lit)+  eol+  emptyMacro "Os"+  let adjust = B.setMeta "title" (B.str title)+             . B.setMeta "date" date+             . B.setMeta "section" (B.str section)+             . maybe id (B.setMeta "architecture" . B.str) arch+  modifyState $ \s -> s{metadata = adjust $ metadata s}++shToSectionMode :: T.Text -> MdocSection+shToSectionMode "NAME" = ShName+shToSectionMode "SYNOPSIS" = ShSynopsis+shToSectionMode "AUTHORS" = ShAuthors+shToSectionMode "SEE ALSO" = ShSeeAlso+shToSectionMode _ = ShOther++parseHeader :: PandocMonad m => MdocParser m Blocks+parseHeader = do+  (Macro m _) <- lookAhead $ macro "Sh" <|> macro "Ss"+  txt <- lineEnclosure m id+  let lvl = if m == "Sh" then 1 else 2+  when (lvl == 1) $ modifyState $ \s -> s{currentSection = (shToSectionMode . stringify) txt}+  return $ B.header lvl txt++parseNameSection :: PandocMonad m => MdocParser m Blocks+parseNameSection = do+  sec <- currentSection <$> getState+  guard $ sec == ShName+  nms <- mconcat . intersperse B.space <$> many nameNm+  macro "Nd"+  desc <- argsToInlines+  return $ B.para $ nms <> B.space <> "—" <> B.space <> desc+ where+   nameNm = do+     macro "Nm"+     nms <- many1 aNm+     eol+     return $ mconcat $ intersperse B.space nms+   comma = msatisfy $ \case+     (Delim _ "," _) -> True+     _ -> False+   aNm = do+     nm <- toString <$> lit+     c <- option mempty (toString <$> comma)+     modifyState $ \s -> s{progName = mplus (progName s) (Just nm)}+     return $ B.code nm <> B.str c++parseSynopsisSection :: PandocMonad m => MdocParser m Blocks+parseSynopsisSection = do+  sec <- currentSection <$> getState+  guard $ sec == ShSynopsis+  parseSynopsis sectionEnd++parseMiniSynopsis :: PandocMonad m => MdocParser m Blocks+parseMiniSynopsis = do+  macro "nr"+  literal "nS"+  literal "1"+  eol+  parseSynopsis (sectionEnd <|> end)+  where+    end = do+      macro "nr"+      literal "nS"+      literal "0"+      eol+      return ()++parseSynopsis :: PandocMonad m => MdocParser m () -> MdocParser m Blocks+parseSynopsis end = do+  bs <- manyTill synopsisBlock end+  return $ mconcat bs+  where+    synopsisGroup p = B.lineBlock <$> many1 p <* optional (emptyMacro "Pp")+    synopsisBlock = synopsisGroup parseInvocation+                <|> synopsisGroup (parseCd <* optional eol)+                <|> synopsisGroup (parseIn <* optional eol)+                <|> synopsisGroup (parseFd <* optional eol)+                <|> synopsisGroup (parseVt <* optional eol)+                <|> try parseSignature+                <|> parseWeirdSignature+                <|> parseRegularBlock+    parseInvocation = do+      nm <- parseNm+      optional eol+      rest <- many synopsisInline+      spacify (nm:rest)+    parseSignature = do+      ft <- parseFt <* optional eol+      sig <- (parseFn <|> parseFo) <* optional eol+      return $ B.lineBlock [ft, sig <> ";"]+    -- e.g. OpenBSD MB_CUR_MAX(3), mild abuse of notation for Ft+    parseWeirdSignature = do+      ft <- parseFt <* optional eol+      rest <- many synopsisInline+      line <- spacify (ft:rest)+      return $ B.lineBlock [line]+    synopsisInline = parseSmToggle <|> parseStrs <|> (controlLine >>= spacify) <?> "synopsis inlines"+    safeEol = do+      amNested <- inLineEnclosure <$> getState+      unless amNested $ optional eol+    controlLine = many1 ((choice otherInlineMacros <|> litsAndDelimsToInlines) <* safeEol)++parseSeeAlsoSection :: PandocMonad m => MdocParser m Blocks+parseSeeAlsoSection = do+  sec <- currentSection <$> getState+  guard $ sec == ShSeeAlso+  blocks <- many1Till parseSeeAlsoBlock sectionEnd+  return $ mconcat blocks+  where+    parseSeeAlsoBlock = parseRegularBlock <|> (B.para <$> parseRs)++-- roff(7) says "In text lines, whitespace is preserved within a line." I+-- considered following this rule but it really cuts against the grain of what+-- Pandoc writers want to work with, for no clear benefit. This isn't wholly+-- inconsistent with mandoc, because it makes no effort to render multiple+-- consecutive spaces from the source document in HTML. Hence I call B.text+-- instead of B.str+parseStr :: PandocMonad m => MdocParser m Inlines+parseStr = do+  (Str txt _) <- str+  return $ B.text txt++-- It's unclear whether consecutive text lines ought to be affected by the+-- spacing mode. mdoc(7) claims that:+--+-- > By default, spacing is on. When switched off, no white space is+-- > inserted between macro arguments and between the output generated from+-- > adjacent macros, but text lines still get normal spacing between words+-- > **and sentences.**+--+-- (emphasis added)+-- This implied to me that while spacing is off, consecutive text lines+-- would have spacing between them as normal. In fact, in mandoc's+-- implementation, they do not:+--+--     text+--     .Sm off+--     text.+--     text+--     .Sm on+--     text+--+-- renders as+--+--     text text.text text+--+-- (The "." is in there since the allusion in the documentation to+-- sentences made me wonder if that made a difference; it doesn't.)+--+-- I've chosen to adopt my interpretation of the documented behavior, rather+-- than mandoc's implementation. Multiple consecutive strs within a block get+-- spaces between them and then packed up together, and text lines are not+-- affected by the spacing mode.+--+-- Reported at https://inbox.vuxu.org/mandoc-discuss/369KFE6SHMXSE.3PS4387AYEFB5@silby.fyi/T/+parseStrs :: PandocMonad m => MdocParser m Inlines+parseStrs = do+  txt <- many1 parseStr+  return $ mconcat $ intersperse B.space txt++parseDelim :: PandocMonad m => DelimSide -> MdocParser m Inlines+parseDelim pos = do+  (Delim _ txt _) <- delim pos+  return $ B.str txt++litsToText :: PandocMonad m => MdocParser m [T.Text]+litsToText = do+  ls <- many1 lit+  return $ map toString ls++litsToInlines :: PandocMonad m => MdocParser m Inlines+litsToInlines = do+  ls <- many1 lit+  let strs = map (B.str . toString) ls+  spacify strs++litsAndDelimsToInlines :: PandocMonad m => MdocParser m Inlines+litsAndDelimsToInlines = do+  (o, ls, c) <- delimitedArgs $ many lit+  guard $ not (null o && null ls && null c)+  strs <- spacify $ map (B.str . toString) ls+  return $ o <> strs <> c++openingDelimiters :: PandocMonad m => MdocParser m Inlines+openingDelimiters = do+    openDelim <- mconcat <$> many (parseDelim Open)+    omids <- pipes+    addSpace <- spacingMode <$> getState+    let omid | null omids = mempty+             | addSpace = omids <> B.space+             | otherwise = omids+    return $ openDelim <> omid++pipes :: PandocMonad m => MdocParser m Inlines+pipes = many (parseDelim Middle) >>= spacify++closingDelimiters :: PandocMonad m => MdocParser m Inlines+closingDelimiters = do+    cmids <- pipes+    addSpace <- spacingMode <$> getState+    let cmid | null cmids = mempty+             | addSpace = B.space <> cmids+             | otherwise = cmids+    closeDelim <- mconcat <$> many (parseDelim Close)+    return $ cmid <> closeDelim++delimitedArgs :: PandocMonad m => MdocParser m x -> MdocParser m (Inlines, x, Inlines)+delimitedArgs p = do+    openDelim <- openingDelimiters+    inlines <- p+    closeDelim <- closingDelimiters+    return (openDelim, inlines, closeDelim)++simpleInline :: PandocMonad m => T.Text -> (Inlines -> Inlines) -> MdocParser m Inlines+simpleInline nm xform = do+  macro nm+  segs <- manyTill segment inlineContextEnd+  spacify segs+ where+   segment = do+      (openDelim, inlines, closeDelim) <- delimitedArgs $ option mempty litsToInlines+      return $ openDelim <> xform inlines <> closeDelim++codeLikeInline' :: PandocMonad m => T.Text -> T.Text -> MdocParser m Inlines+codeLikeInline' nm cl = simpleInline nm (eliminateEmpty (B.codeWith (cls cl) . stringify))++codeLikeInline :: PandocMonad m => T.Text -> MdocParser m Inlines+codeLikeInline nm = codeLikeInline' nm nm++spanLikeInline :: PandocMonad m => T.Text -> MdocParser m Inlines+spanLikeInline nm = simpleInline nm (eliminateEmpty (B.spanWith (cls nm)))++-- One-line enclosures need a little bit of state so that we don't parse+-- the closing delimiters that follow nested one-line or multiline+-- enclosures; the closing delimiters are meant to go after the close of+-- the outermost enclosure. Hence we respect and set inLineEnclosure.+lineEnclosure :: PandocMonad m => T.Text -> (Inlines -> Inlines) -> MdocParser m Inlines+lineEnclosure nm xform = do+  macro nm+  amNested <- inLineEnclosure <$> getState+  modifyState $ \s -> s{inLineEnclosure = True}+  first <- openingDelimiters+  further <-+    (manyTill+      (parseInlineMacro+        <|> (try (litsAndDelimsToInlines <* notFollowedBy eol))+        <|> litsToInlines+        <|> openingDelimiters)+      lineEnclosureContextEnd)+  further' <- spacify further+  finally <- if amNested then mempty else closingDelimiters <* optional eol+  modifyState $ \s -> s{inLineEnclosure = amNested}+  return $ first <> xform further' <> finally+  where+    lineEnclosureContextEnd =+      try $+        void (lookAhead (macro "Ta"))+        <|> lookAhead (many (macro "Ns" <|> delim Close) *> eol)+++-- The Ns, Ap, and Sm macros affect the automatic insertion of spaces between+-- macro arguments that occurs by default. We parse these macros to RawInlines+-- that we then eliminate in foldNoSpaces. If any of these macros end up+-- in the final AST returned by readMdoc, it's a bug.++noSpace :: Inlines+noSpace = B.rawInline "mdoc" "Ns"++apMacro :: Inlines+apMacro = B.rawInline "mdoc" "Ap"++smOff :: Inlines+smOff = B.rawInline "mdoc" "Sm off"++smOn :: Inlines+smOn = B.rawInline "mdoc" "Sm on"++-- Accumulator for eliminating of Ns, Ap, and Sm macros from a list of 'Inlines'+data SpacifyState = SpacifyState+  { accum :: [Inlines],  -- already-folded 'Inlines'+    prev :: Inlines,  -- content we might be appending further content to+    ns :: Bool,  -- True when we've read an Ns and are waiting to concatenate content to prev+    sm :: Bool  -- True when spacing mode is on+  }++instance Default SpacifyState where+  def = SpacifyState [] mempty False True++-- Given a list of 'Inlines'es, concatenate consecutive elements that shouldn't+-- have a 'Space' inserted between them based on changes to the spacing mode,+-- Ap macros, and Ns macros.+foldNoSpaces :: [Inlines] -> [Inlines]+foldNoSpaces xs = (finalize . foldl go def) xs+  where+    go :: SpacifyState -> Inlines -> SpacifyState+    go s x+      | ns s && x == noSpace = s+      |         x == apMacro = s{prev = prev s <> "'", ns = True}+      |         x == noSpace = s{ns = True}+      |         x == smOn    = s{sm = True}+      | sm s && x == smOff   = s{accum = accum s <> [prev s], prev = mempty, sm = False}+      | ns s                 = s{prev = prev s <> x, ns = False}+      | not (sm s)           = s{prev = prev s <> x}+      | null (prev s)        = s{prev = x}+      | otherwise            = s{accum = accum s <> [prev s], prev = x}+    finalize s+      | null (prev s) = accum s+      | otherwise     = accum s <> [prev s]++-- Add any necessary spaces between individual 'Inlines' in a list.+-- Respects the spacing mode status. This should more or less+-- always get applied to any list of 'Inlines' before doing anything+-- else with it.+spacify :: PandocMonad m => [Inlines] -> MdocParser m Inlines+spacify x = do+  mode <- spacingMode <$> getState+  return (go mode x)+  where+    go True = mconcat . intersperse B.space . foldNoSpaces+    go False = mconcat . foldNoSpaces++-- Compatibility note: mandoc permits, and doesn't warn on, "vertical" macros+-- (Pp, Bl/El, Bd/Ed) inside of "horizontal" block partial-explicit quotations+-- like Do/Dc. However there are no OpenBSD manual pages that employ such markup+-- and it doesn't look right when rendered. We don't attempt to consume anything+-- but pandoc inlines inside of these multiline enclosures.+multilineEnclosure :: PandocMonad m => T.Text -> T.Text -> (Inlines -> Inlines) -> MdocParser m Inlines+multilineEnclosure op cl xform = do+  macro op+  amNested <- inLineEnclosure <$> getState+  -- we're now "protected" from any outer enclosure or .It+  modifyState $ \s -> s{inLineEnclosure = False}+  openDelim <- mconcat <$> many (parseDelim Open)+  optional eol+  contents <- parseInlines+  (macro cl <?> show cl)+  closeDelim <-+    if amNested+       then mempty+       else mconcat <$> many (parseDelim Close) <* optional eol+  modifyState $ \s -> s{inLineEnclosure = amNested}+  return $ openDelim <> xform contents <> closeDelim++parseEo :: PandocMonad m => MdocParser m Inlines+parseEo = do+  macro "Eo"+  odel <- del+  optional eol+  inner <- parseInlines+  macro "Ec"+  cdel <- del+  optional eol+  return $ odel <> inner <> cdel+  where+    del = B.str . toString <$> (arg <|> delim Open <|> delim Middle <|> delim Close)++eliminateEmpty :: (Inlines -> Inlines) -> Inlines -> Inlines+eliminateEmpty x y = if null y then mempty else x y++cls :: T.Text -> B.Attr+cls x = (mempty, [x], mempty)++-- mandoc -T html formats Sy with a <b> tag, since it's not really+-- semantically <strong>, but Strong is our best option in Pandoc+parseSy :: PandocMonad m => MdocParser m Inlines+parseSy = simpleInline "Sy" (eliminateEmpty B.strong)++parseEm :: PandocMonad m => MdocParser m Inlines+parseEm = simpleInline "Em" (eliminateEmpty B.emph)++parseNo :: PandocMonad m => MdocParser m Inlines+parseNo = simpleInline "No" (eliminateEmpty id)++-- Deprecated, mandoc doesn't style this at all+parseTn :: PandocMonad m => MdocParser m Inlines+parseTn = simpleInline "Tn" (eliminateEmpty id)++parseLi :: PandocMonad m => MdocParser m Inlines+parseLi = codeLikeInline "Li"++parseEv :: PandocMonad m => MdocParser m Inlines+parseEv = codeLikeInline "Ev"++parseDv :: PandocMonad m => MdocParser m Inlines+parseDv = codeLikeInline "Dv"++parseAd :: PandocMonad m => MdocParser m Inlines+parseAd = spanLikeInline "Ad"++parseVa :: PandocMonad m => MdocParser m Inlines+parseVa = codeLikeInline' "Va" "variable"++parseVt :: PandocMonad m => MdocParser m Inlines+parseVt = codeLikeInline' "Vt" "variable"++parseAn :: PandocMonad m => MdocParser m Inlines+parseAn = try anSplit <|> anRegular+  where+    anSplit = do+      macro "An"+      mode <- literal "-split" $> True <|> literal "-nosplit" $> False+      modifyState $ \s -> s{authorNameSplit = mode}+      return mempty+    anRegular = do+      an <- spanLikeInline "An"+      spl <- authorNameSplit <$> getState+      return $ (if spl then B.linebreak else mempty) <> an++parseMs :: PandocMonad m => MdocParser m Inlines+parseMs = spanLikeInline "Ms"++-- TODO implement internal reference links+parseSx :: PandocMonad m => MdocParser m Inlines+parseSx = spanLikeInline "Sx"++-- I'm not sure why mandoc inserts a ~ when Mt is missing an argument,+-- but it does, and it doesn't issue a warning, so that quirk is+-- retained.+parseMt :: PandocMonad m => MdocParser m Inlines+parseMt = simpleInline "Mt" mailto+  where mailto x | null x = B.link ("mailto:~") "" "~"+                 | otherwise = B.link ("mailto:" <> stringify x) "" x++parsePa :: PandocMonad m => MdocParser m Inlines+parsePa = simpleInline "Pa" p+  where p x | null x = B.spanWith (cls "Pa") "~"+            | otherwise = B.spanWith (cls "Pa") x++-- There's a number of unique-looking cases for Fl parsing so I am just+-- handling them very explicitly instead of trying to generalize anything+-- enough to handle it. Could conceivably be better.+parseFl :: PandocMonad m => MdocParser m Inlines+parseFl = do+  macro "Fl"+  start <- option mempty (emptyWithDelim <|> flfl <|> emptyWithMacro <|> emptyEmpty)+  segs <- manyTill segment inlineContextEnd+  spacify ([start] <> segs)+ where+   emptyWithDelim = do+     lookAhead $ many1 (delim Middle <|> delim Close)+     ds <- closingDelimiters+     return $ fl "-" <> ds+   flfl = do+     lookAhead (macro "Fl")+     x:xs <- B.toList <$> parseFl+     let xx = B.codeWith (cls "Fl") $ "-" <> stringify x+     return $ xx <> B.fromList xs+   emptyWithMacro = do+     lookAhead anyMacro+     rest <- parseInline+     return $ fl "-" <> rest+   emptyEmpty = lookAhead eol $> fl "-"+   segment = do+      (openDelim, inlines, closeDelim) <- delimitedArgs $ option mempty litsToText+      inner <- (spacify . (map fl) . flags) inlines+      return $ openDelim <> inner <> closeDelim+   fl = B.codeWith (cls "Fl")+   flags [] = ["-"]+   flags xs = map ("-" <>) xs++parseAr :: PandocMonad m => MdocParser m Inlines+parseAr = simpleInline "Ar" ar+  where ar x | null x = B.codeWith (cls "variable") "file ..."+             | otherwise = B.codeWith (cls "variable") $ stringify x+++parseCm :: PandocMonad m => MdocParser m Inlines+parseCm = codeLikeInline "Cm"++parseIc :: PandocMonad m => MdocParser m Inlines+parseIc = codeLikeInline "Ic"++parseEr :: PandocMonad m => MdocParser m Inlines+parseEr = codeLikeInline "Er"++parseCd :: PandocMonad m => MdocParser m Inlines+parseCd = codeLikeInline "Cd"++parseQl :: PandocMonad m => MdocParser m Inlines+parseQl = lineEnclosure "Ql" $ B.codeWith (cls "Ql") . stringify++parseDq :: PandocMonad m => MdocParser m Inlines+parseDq = lineEnclosure "Dq" B.doubleQuoted++parseDo :: PandocMonad m => MdocParser m Inlines+parseDo = multilineEnclosure "Do" "Dc" B.doubleQuoted++parseSq :: PandocMonad m => MdocParser m Inlines+parseSq = lineEnclosure "Sq" B.singleQuoted++parseSo :: PandocMonad m => MdocParser m Inlines+parseSo = multilineEnclosure "So" "Sc" B.singleQuoted++parseQq :: PandocMonad m => MdocParser m Inlines+parseQq = lineEnclosure "Qq" $ \x -> "\"" <> x <> "\""++parseQo :: PandocMonad m => MdocParser m Inlines+parseQo = multilineEnclosure "Qo" "Qc" $ \x -> "\"" <> x <> "\""++parsePq :: PandocMonad m => MdocParser m Inlines+parsePq = lineEnclosure "Pq" $ \x -> "(" <> x <> ")"++parsePo :: PandocMonad m => MdocParser m Inlines+parsePo = multilineEnclosure "Po" "Pc" $ \x -> "(" <> x <> ")"++parseBq :: PandocMonad m => MdocParser m Inlines+parseBq = lineEnclosure "Bq" $ \x -> "[" <> x <> "]"++parseBo :: PandocMonad m => MdocParser m Inlines+parseBo = multilineEnclosure "Bo" "Bc" $ \x -> "[" <> x <> "]"++-- For our purposes this probably behaves identically to Bq+-- in most circumstances but I might need to do something+-- special with it in SYNOPSIS+parseOp :: PandocMonad m => MdocParser m Inlines+parseOp = lineEnclosure "Op" $ \x -> "[" <> x <> "]"++parseOo :: PandocMonad m => MdocParser m Inlines+parseOo =  multilineEnclosure "Oo" "Oc" $ \x -> "[" <> x <> "]"++parseBrq :: PandocMonad m => MdocParser m Inlines+parseBrq = lineEnclosure "Brq" $ \x -> "{" <> x <> "}"++parseBro :: PandocMonad m => MdocParser m Inlines+parseBro = multilineEnclosure "Bro" "Brc" $ \x -> "{" <> x <> "}"++parseAq :: PandocMonad m => MdocParser m Inlines+parseAq = lineEnclosure "Aq" $ \x -> "⟨" <> x <> "⟩"++parseAo :: PandocMonad m => MdocParser m Inlines+parseAo = multilineEnclosure "Ao" "Ac" $ \x -> "⟨" <> x <> "⟩"++parseDl :: PandocMonad m => MdocParser m Blocks+parseDl = do+  inner <- lineEnclosure "Dl" id+  return $ B.codeBlock (stringify inner)++parseD1 :: PandocMonad m => MdocParser m Blocks+parseD1 = do+  inner <- lineEnclosure "D1" id+  return $ B.divWith (cls "display") $ B.plain inner++parseNm :: PandocMonad m => MdocParser m Inlines+parseNm = do+  macro "Nm"+  mnm <- (progName <$> getState)+  (op, rg, cl) <- delimitedArgs $ option mempty litsToInlines+  return $ case (mnm, rg) of+    (Just nm, x) | null x ->+      op <> ok nm <> cl+    (_, x) ->+      op <> (ok . stringify) x <> cl+  where+    ok = B.codeWith (cls "Nm")+++parseXr :: PandocMonad m => MdocParser m Inlines+parseXr = do+  macro "Xr"+  (open, (name, section), close) <- delimitedArgs f+  let ref = name <> "(" <> section <> ")"+  return $ open <> B.spanWith (cls "Xr") (B.str ref) <> close+    where+      f = do+        n <- lit <?> "Xr manual name"+        s <- lit <?> "Xr manual section"+        return (toString n, toString s)++parseIn :: PandocMonad m => MdocParser m Inlines+parseIn = do+  macro "In"+  openClose <- closingDelimiters+  openOpen <- openingDelimiters+  header <- toString <$> lit+  close <- closingDelimiters+  return $ open openClose openOpen <> B.codeWith (cls "In") ("<" <> header <> ">") <> close+  where+    open a b+      | null a = b+      | null b = a+      | otherwise = a <> B.space <> b++parseFd :: PandocMonad m => MdocParser m Inlines+parseFd = codeLikeInline "Fd"++parseFt :: PandocMonad m => MdocParser m Inlines+parseFt = codeLikeInline' "Ft" "variable"++-- The output here is comparable to mandoc's HTML output, which doesn't tag+-- the commas/parentheses. Is this questionable from a pandoc POV?+formatFunction :: T.Text -> [Inlines] -> Inlines+formatFunction nm args = B.codeWith (cls "Fn") nm <> "(" <> args' <> ")"+  where+    args' = mconcat $ intersperse (", ") args++parseFn :: PandocMonad m => MdocParser m Inlines+parseFn = do+  macro "Fn"+  (op, (nm, args), cl) <- delimitedArgs f+  return $ op <> formatFunction nm (fmap (B.codeWith (cls "variable")) args) <> cl+  where+    f = do+      nm <- toString <$> lit+      args <- option [] litsToText+      return (nm, args)++parseFa :: PandocMonad m => MdocParser m Inlines+parseFa = codeLikeInline' "Fa" "variable"++parseFo :: PandocMonad m => MdocParser m Inlines+parseFo = do+  macro "Fo"+  nm <- toString <$> lit+  eol+  args <- many (parseFa <* eol)+  macro "Fc"+  return $ formatFunction nm args++parseLk :: PandocMonad m => MdocParser m Inlines+parseLk = do+  macro "Lk"+  openClose <- closingDelimiters+  openOpen <- openingDelimiters+  url <- toString <$> lit+  inner <- many segment >>= spacify+  close <- closingDelimiters+  let label | null inner = B.str url+            | otherwise = inner+  return $ open openClose openOpen <> B.link url "" label <> close+  where+    open a b+      | null a = b+      | null b = a+      | otherwise = a <> B.space <> b+    end = msatisfy newControlContext+    segment = do+      a <- openingDelimiters+      m <- option mempty litsToInlines+      z <-+        try (closingDelimiters <* notFollowedBy end)+          <|> option mempty pipes+      guard $ not $ all null [a, m, z]+      return $ a <> m <> z++-- This is a raw roff request but it appears sometimes in mdoc+-- manuals and is easy enough to handle+parsebr :: PandocMonad m => MdocParser m Inlines+parsebr = emptyMacro "br" >> return B.linebreak++parseNs :: PandocMonad m => MdocParser m Inlines+parseNs = macro "Ns" >> return noSpace++-- Per mdoc(7), Pf prefix macro [argument ...] is equivalent to+-- No \&prefix Ns macro [argument ...] and because of the way+-- spacify works, the easiest thing to do is just push an Ns onto+-- the input+parsePf :: PandocMonad m => MdocParser m Inlines+parsePf = do+  macro "Pf"+  t <- toString <$> anyToken+  rest <- getInput+  pos <- getPosition+  setInput $ (Macro "Ns" pos):rest+  return $ B.str t++parseAp :: PandocMonad m => MdocParser m Inlines+parseAp = macro "Ap" >> return apMacro++parseEx :: PandocMonad m => MdocParser m Inlines+parseEx = do+  macro "Ex"+  literal "-std"+  args <- fmap toString <$> many lit+  pn <- progName <$> getState+  eol+  return $ "The"+          <> B.space+          <> utils pn args+          <> B.space+          <> "0 on success, and >0 if an error occurs."+  where+    nm = B.codeWith (cls "Nm")+    sing = "utility exits"+    plur = "utilities exit"+    utils (Just x) [] = nm x <> B.space <> sing+    utils _ [x] = nm x <> B.space <> sing+    utils _ [x,y] = nm x <> B.space <> "and" <> B.space <> nm y <> B.space <> plur+    utils pn xs =+      case (pn, unsnoc xs) of+        (Nothing, Nothing) -> sing+        (_, Just (hd, end)) -> mconcat ((intersperse (", ") . fmap nm) hd) <> ", and " <> nm end <> B.space <> plur+        (Just p, Nothing) -> nm p <> B.space <> sing+++parseRv :: (PandocMonad m) => MdocParser m Inlines+parseRv = do+  macro "Rv"+  literal "-std"+  args <- fmap toString <$> many lit+  pn <- progName <$> getState+  eol+  return $ go pn args+  where+    nm a = B.codeWith (cls "Fn") a <> "()"+    nothing = "Upon successful completion, the value 0 is returned;"+    sing = "function returns"+    plur = "functions return"+    success = "the value 0 if successful;"+    errno =+      "otherwise the value -1 is returned and the global variable"+        <> B.codeWith (cls "variable") "errno"+        <> "is set to indicate the error."+    message conj =+      "The"+        <> B.space+        <> conj+        <> B.space+        <> success+        <> B.space+        <> errno+    go (Just x) [] = message (nm x <> B.space <> sing)+    go _ [x] = message (nm x <> B.space <> sing)+    go _ [x, y] = message (nm x <> B.space <> "and" <> B.space <> nm y <> B.space <> plur)+    go pn xs =+      case (pn, unsnoc xs) of+        (Nothing, Nothing) -> nothing <> B.space <> errno+        (_, Just (hd, end)) -> message (mconcat ((intersperse (", ") . fmap nm) hd) <> ", and " <> nm end <> B.space <> plur)+        (Just p, Nothing) -> message (nm p <> B.space <> sing)++parseSt :: PandocMonad m => MdocParser m Inlines+parseSt = do+  macro "St"+  (Lit std pos) <- lit+  case standard std of+    Nothing -> do+      logMessage $ SkippedContent ("unrecognized argument to St: " <> std) pos+      return mempty+    Just t -> return $ B.text t++-- TODO incorporate well-known library description and linker options+-- from mandoc lib.in expected in FreeBSD LIBRARY section, at minimum.+parseLb :: PandocMonad m => MdocParser m Inlines+parseLb = do+  macro "Lb"+  library <- toString <$> lit+  return $ "library" <> B.space <> B.doubleQuoted (B.str library)++unixVersion :: PandocMonad m => T.Text -> T.Text -> MdocParser m Inlines+unixVersion m s = do+  macro m+  (o, v, c) <- delimitedArgs (option mempty (toString <$> lit))+  return $ o <> B.str s <> f v <> c+  where+    f v | T.null v = mempty+        | otherwise = B.space <> B.str v++parseAt :: PandocMonad m => MdocParser m Inlines+parseAt = do+  macro "At"+  (o, v, c) <-  delimitedArgs (optionMaybe (toString <$> lit))+  let v' = maybe "AT&T UNIX" attVer v+  return $ o <> B.text v' <> c+  where+    isVersion x = x `elem` ["1", "2", "3", "4", "5", "6", "7"]+    isRelease x = x `elem` ["1", "2", "3", "4"]+    attVer (T.stripPrefix "v" -> Just ver)+      | isVersion ver = "Version " <> ver <> " AT&T UNIX"+    attVer "32v" = "Version 7 AT&T UNIX/32V"+    attVer "III" = "AT&T System III UNIX"+    attVer (T.stripPrefix "V." -> Just release)+      | isRelease release = "AT&T System V Release " <> release <> " UNIX"+    attVer "V" = "AT&T System V UNIX"+    attVer x = "AT&T UNIX " <> x++parseBsx :: PandocMonad m => MdocParser m Inlines+parseBsx = unixVersion "Bsx" "BSD/OS"++parseBx :: PandocMonad m => MdocParser m Inlines+parseBx = do+  macro "Bx"+  (o, v, c) <- delimitedArgs zeroToTwoLits+  return $ o <> bsd v <> c+  where+    zeroToTwoLits = do+      toks <- try (count 2 lit) <|> count 1 lit <|> count 0 lit+      return $ toString <$> toks+    bsd [] = B.str "BSD"+    bsd [x] = B.str $ x <> "BSD"+    bsd (x:y:_) = B.str (x <> "BSD" <> "-" <> T.toTitle y)++parseDx :: PandocMonad m => MdocParser m Inlines+parseDx = unixVersion "Dx" "DragonFly"++parseFx :: PandocMonad m => MdocParser m Inlines+parseFx = unixVersion "Fx" "FreeBSD"++-- This dance to capitalize a letter at the end of a NetBSD+-- version matches what mandoc does to the argument of .Nx.+-- See mandoc mdoc_validate.c r1.350+-- Curiously, there's little easy-to-find evidence of what+-- these lettered releases actually are, other than+-- references in man page history sections to 0.9A etc.+parseNx :: PandocMonad m => MdocParser m Inlines+parseNx = do+  macro "Nx"+  (o, v, c) <-  delimitedArgs (option mempty (toString <$> lit))+  return $ o <> "NetBSD" <> f v <> c+  where+    f v | T.null v = mempty+        | otherwise = B.space <> B.str (fromRight v $ readWith earlyNetBSDVersion () v)+    earlyNetBSDVersion = do+      major <- oneOf "01"+      dot <- char '.'+      minor <- digit+      ltr <- satisfy isAsciiLower+      return $ T.pack [major, dot, minor, toUpper ltr]++parseOx :: PandocMonad m => MdocParser m Inlines+parseOx = unixVersion "Ox" "OpenBSD"++parseUx :: PandocMonad m => MdocParser m Inlines+parseUx = macro "Ux" >> return (B.str "UNIX")++parseInlineMacro :: PandocMonad m => MdocParser m Inlines+parseInlineMacro = choice (synopsisTopicMacros <> otherInlineMacros) <?> "inline macro"++-- These macros always start a new line in SYNOPSIS+synopsisTopicMacros :: PandocMonad m => [MdocParser m Inlines]+synopsisTopicMacros =+    [parseNm, parseCd, parseFd, parseFn, parseFo, parseIn, parseVt, parseFt]++otherInlineMacros :: PandocMonad m => [MdocParser m Inlines]+otherInlineMacros =+    [ parseSy,+      parseEm,+      parseLk,+      parseLi,+      parseEv,+      parseDv,+      parseMt,+      parsePa,+      parseFl,+      parseCm,+      parseIc,+      parseEr,+      parseAd,+      parseVa,+      parseAn,+      parseMs,+      parseSx,+      parseAr,+      parseFa,+      parseNo,+      parseTn,+      parseXr,+      parseQl,+      parseOp,+      parseSq,+      parseDq,+      parseQq,+      parsePq,+      parseBq,+      parseBrq,+      parseAq,+      parseEo,+      parseSo,+      parseDo,+      parseQo,+      parsePo,+      parseBo,+      parseBro,+      parseAo,+      parseOo,+      parseBf,+      parseRsInline,+      parseEx,+      parseRv,+      parseSt,+      parseLb,+      parseAt,+      parseBsx,+      parseBx,+      parseDx,+      parseFx,+      parseNx,+      parseOx,+      parseUx,+      parsebr,+      parseAp,+      parsePf,+      parseNs,+      skipUnsupportedInlines+    ]++parseInline :: PandocMonad m => MdocParser m Inlines+parseInline = parseStrs <|> (controlLine >>= spacify) <?> "text lines or inline macros"+  where+    safeEol = do+      amNested <- inLineEnclosure <$> getState+      unless amNested $ optional eol+    controlLine = many1 ((parseInlineMacro <|> litsAndDelimsToInlines) <* safeEol)++parseInlines :: PandocMonad m => MdocParser m Inlines+parseInlines = many1 (parseSmToggle <|> parseInline) >>= spacify++-- Lp is a deprecated synonym for Pp+parsePara :: PandocMonad m => MdocParser m Blocks+parsePara = B.para . B.trimInlines <$> parseInlines <*+    optional (emptyMacro "Pp" <|> emptyMacro "Lp")++-- Indented display blocks are visually similar to block quotes+-- but rarely carry those semantics. I'm just putting things in+-- divs. Centered is discouraged and rarely seen.+parseDisplay :: PandocMonad m => MdocParser m Blocks+parseDisplay = do+  literal "-filled" <|> literal "-ragged" <|> literal "-centered"+  many $ (literal "-offset" *> lit) <|> (literal "-compact")+  eol+  B.divWith (cls "display") . mconcat <$> many parseRegularBlock++-- This is something of a best-effort interpretation of the -unfilled+-- display block type. The main difference with mandoc is probably+-- that newlines inside of multiline enclosures won't be preserved.+parseUnfilled :: PandocMonad m => MdocParser m Blocks+parseUnfilled = do+  literal "-unfilled"+  many $ (literal "-offset" *> lit) <|> (literal "-compact")+  eol+  lns <- many $ Just <$> parseStrPreserveSpace+            <|> Nothing <$ parseSmToggle+            <|> Just <$> parseInline+            <|> Just "" <$ emptyMacro "Pp"+  return $ B.lineBlock (catMaybes lns)+  where+    parseStrPreserveSpace = (B.str . toString) <$> str <|> (blank *> mempty)++parseCodeBlock :: PandocMonad m => MdocParser m Blocks+parseCodeBlock = do+  literal "-literal"+  many $ (literal "-offset" *> lit) <|> (literal "-compact")+  eol+  lns <- many $ Just . toString <$> (str <|> blank)+            <|> Nothing <$ parseSmToggle+            <|> Just . stringify <$> parseInline+            <|> Just "" <$ emptyMacro "Pp"+  return $ B.codeBlock (T.unlines (catMaybes lns))++parseBd :: PandocMonad m => MdocParser m Blocks+parseBd = do+  macro "Bd"+  blk <- parseCodeBlock <|> parseDisplay <|> parseUnfilled+  emptyMacro "Ed"+  return blk++-- This is a bit of a best effort version. Hypothetically multiple blocks+-- could occur inside a Bf and this should be a stateful thing but I don't+-- know if that's observed in the wild.+parseBf :: PandocMonad m => MdocParser m Inlines+parseBf = do+  macro "Bf"+  xform <-   B.strong <$ (literal "Sy" <|> literal "-symbolic")+         <|> B.emph   <$ (literal "Em" <|> literal "-emphasis")+         <|> code     <$ (literal "Li" <|> literal "-literal")+  eol+  ins <- parseInlines+  emptyMacro "Ef"+  return $ xform ins+  where+    code = B.code . stringify++skipListArgument :: (PandocMonad m) => MdocParser m ()+skipListArgument =+  void $ choice+    [ literal "-width" *> lit,+      literal "-offset" *> lit,+      literal "-compact"+    ]++parseItemList :: PandocMonad m => MdocParser m Blocks+parseItemList = do+  f <- (choice (map literal ["-bullet", "-dash", "-hyphen", "-item"]) $> B.bulletList)+       <|> literal "-enum" $> B.orderedList+  many skipListArgument+  eol+  items <- many bulletItem+  return $ f items+  where+    bulletItem = do+      emptyMacro "It"+      mconcat <$> many parseRegularBlock++-- Despite some ambiguous documentation to the contrary the Xo/Xc macros+-- only seem genuinely useful in an .It head, and it's not clear what if+-- anything it means to use them somewhere else in a contemporary mdoc manual.+-- See https://inbox.vuxu.org/mandoc-discuss/2UKLZW0DL8BSM.2IIO9W4HSUSRR@silby.fyi/T/+-- for more blathering.+parseDefinitionList :: PandocMonad m => MdocParser m Blocks+parseDefinitionList = do+  headParser <- (choice . map literal) ["-hang", "-inset", "-ohang", "-tag"] $> parsedHead <|> literal "-diag" $> diagHead+  many skipListArgument+  eol+  items <- many (parseSmToggle *> mempty <|> dlItem headParser)+  return $ B.definitionList items+  where+    parsedHead = try xoListHead <|> eolListHead+    eolListHead = do+      modifyState $ \s -> s{inLineEnclosure = True}+      inner <- parseInlines+      eol+      modifyState $ \s -> s{inLineEnclosure = False}+      return inner+    diagHead = argsToInlines+    dlItem hed = do+      -- Some manuals have an evidently useless .Pp before .It+      -- e.g. OpenBSD ld(1), just deal with it.+      many ((void . emptyMacro) "Pp" <|> skipUnsupportedMacro "Tg")+      macro "It"+      dt <- hed+      dd <- mconcat <$> many parseRegularBlock+      return (dt, [dd])+    xoListHead = do+      before <- option mempty parseInline+      macro "Xo"+      optional eol+      after <- many1Till parseInlines (emptyMacro "Xc")+      spacify (before:after)++-- TODO support implicit rows:+--   If the first line of the body of a -column list is not an It macro line,+--   It contexts spanning one input line each are implied until an It macro+--   line is encountered+-- and support literal tabs+parseColumnList :: PandocMonad m => MdocParser m Blocks+parseColumnList = do+  literal "-column"+  many skipListArgument+  many $ arg <|> delim Open <|> delim Middle <|> delim Close+  eol+  rows <- many listRow+  return $ B.simpleTable [] rows+  where+    listRow = do+      optional (emptyMacro "Pp")+      macro "It"+      fmap B.plain <$> sepBy (parseInlines <|> pure mempty) (macro "Ta" <* optional eol)++parseBl :: PandocMonad m => MdocParser m Blocks+parseBl = do+  macro "Bl"+  blk <- parseItemList <|> parseDefinitionList <|> parseColumnList+  emptyMacro "El"+  return blk++referenceField :: PandocMonad m => T.Text -> ReferenceField -> MdocParser m ()+referenceField m field = do+  macro m+  reference <- currentReference <$> getState+  contents <- stringify <$> litsAndDelimsToInlines+  eol+  modifyState $ \s -> s{currentReference = M.insertWith (++) field [contents] reference}+  return ()++parsePercentA :: PandocMonad m => MdocParser m ()+parsePercentA = referenceField "%A" Author++parsePercentB :: PandocMonad m => MdocParser m ()+parsePercentB = referenceField "%B" BookTitle++parsePercentC :: PandocMonad m => MdocParser m ()+parsePercentC = referenceField "%C" PubLocation++parsePercentD :: PandocMonad m => MdocParser m ()+parsePercentD = referenceField "%D" PubDate++parsePercentI :: PandocMonad m => MdocParser m ()+parsePercentI = referenceField "%I" Publisher++parsePercentJ :: PandocMonad m => MdocParser m ()+parsePercentJ = referenceField "%J" Journal++parsePercentN :: PandocMonad m => MdocParser m ()+parsePercentN = referenceField "%N" IssueNumber++parsePercentO :: PandocMonad m => MdocParser m ()+parsePercentO = referenceField "%O" Optional++parsePercentP :: PandocMonad m => MdocParser m ()+parsePercentP = referenceField "%P" Pages++parsePercentQ :: PandocMonad m => MdocParser m ()+parsePercentQ = referenceField "%Q" Institution++parsePercentR :: PandocMonad m => MdocParser m ()+parsePercentR = referenceField "%R" TechReportTitle++parsePercentT :: PandocMonad m => MdocParser m ()+parsePercentT = referenceField "%T" ArticleTitle++parsePercentU :: PandocMonad m => MdocParser m ()+parsePercentU = referenceField "%U" Url++parsePercentV :: PandocMonad m => MdocParser m ()+parsePercentV = referenceField "%V" VolumeNumber++parseReferenceField :: PandocMonad m => MdocParser m ()+parseReferenceField =+  choice [+      parsePercentA,+      parsePercentB,+      parsePercentC,+      parsePercentD,+      parsePercentI,+      parsePercentJ,+      parsePercentN,+      parsePercentO,+      parsePercentP,+      parsePercentQ,+      parsePercentR,+      parsePercentT,+      parsePercentU,+      parsePercentV+    ]++parseRsInline :: PandocMonad m => MdocParser m Inlines+parseRsInline = do+  sec <- currentSection <$> getState+  guard $ sec /= ShSeeAlso+  parseRs++parseRs :: PandocMonad m => MdocParser m Inlines+parseRs = do+  emptyMacro "Rs"+  modifyState $ \s -> s{currentReference = M.empty}+  many1 parseReferenceField+  emptyMacro "Re"+  ref <- currentReference <$> getState+  -- TODO formatting fields correctly+  return $ B.text $ (M.foldl f mempty ref) <> "."+  where join v = T.concat (intersperse ", " v)+        f a v | T.null a = join v+              | otherwise = a <> ", " <> join v++-- mandoc's roff(7) says "Blank text lines, which may include whitespace,+-- are only permitted within literal contexts." mandoc -T lint warns about+-- blank lines and inserts a roff `sp` request, which is handled+-- differently depending on the output format. My read is that mandoc+-- considers the handling of a blank line in non-literal context in mdoc(7)+-- to be undefined. The Mdoc reader thus ignores blank input lines outside+-- of -literal and -unfilled displays.+skipBlanks :: PandocMonad m => MdocParser m Blocks+skipBlanks = many1 blank *> mempty++-- By default, mdoc is in "spacing mode", where horizontal space is added+-- between macro contents. The Sm macro turns it off and on. When we encounter+-- the Sm macro, we both modify the parser state and we emit a sentinel value+-- that spacify/foldNoSpaces uses to handle cases where spacing mode gets+-- turned off and on within a stretch of inlines.+parseSmToggle :: PandocMonad m => MdocParser m Inlines+parseSmToggle = do+  macro "Sm"+  cur <- spacingMode <$> getState+  mode <- optionMaybe (literal "on" $> True <|> literal "off" $> False)+  eol+  let newMode = update mode cur+  modifyState $ \s -> s{spacingMode = newMode}+  return $ if newMode then smOn else smOff+  where+    update = \case+      Nothing -> not+      Just x -> const x++skipUnsupportedMacro :: PandocMonad m => T.Text -> MdocParser m ()+skipUnsupportedMacro nm = do+  (Macro _ pos) <- macro nm+  manyTill anyToken eol+  logMessage $ SkippedContent ("unsupported macro: " <> nm) pos+++skipUnsupportedInlines :: PandocMonad m => MdocParser m Inlines+skipUnsupportedInlines = choice+      [ skipUnsupportedMacro "Tg",+        skipUnsupportedMacro "Bk",+        skipUnsupportedMacro "Ek"+      ] *> mempty++skipUnknownMacro :: PandocMonad m => MdocParser m Blocks+skipUnknownMacro = do+  pos <- getPosition+  m <- anyMacro+  manyTill anyToken eol+  logMessage $ SkippedContent ("unsupported macro: " <> toString m) pos+  return mempty+++parseRegularBlock :: PandocMonad m => MdocParser m Blocks+parseRegularBlock =+  choice+    [ parseDl+    , parseD1+    , parsePara+    , emptyMacro "Pp" *> mempty+    , parseBd+    , parseBl+    , skipBlanks+    ]++parseBlock :: (PandocMonad m) => MdocParser m Blocks+parseBlock =+  choice+    [ parseHeader+    , parseNameSection+    , parseSynopsisSection+    , parseSeeAlsoSection+    , parseMiniSynopsis+    , parseRegularBlock+    , skipUnknownMacro+    ]
+ src/Text/Pandoc/Readers/Mdoc/Lex.hs view
@@ -0,0 +1,225 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeFamilies #-}+{- |+   Module      : Text.Pandoc.Readers.Mdoc.Lex+   Copyright   : Copyright (C) 2024 Evan Silberman+   License     : GNU GPL, version 2 or above++   Maintainer  : Evan Silberman <evan@jklol.net>+   Stability   : WIP+   Portability : portable++Tokenizer for mdoc+-}+module Text.Pandoc.Readers.Mdoc.Lex+  ( MdocToken(..)+  , MdocTokens(..)+  , DelimSide(..)+  , lexMdoc+  , toString+  )+where++import Control.Monad (void, guard, when)+import Control.Monad.Except (throwError)+import Text.Pandoc.Class.PandocMonad (PandocMonad(..))+import Data.Char (isAlphaNum)+import Data.Maybe (isJust)+import qualified Data.Text as T+import Text.Pandoc.Options+import Text.Pandoc.Parsing+import Text.Pandoc.Readers.Roff.Escape+import Text.Pandoc.Readers.Mdoc.Macros+import qualified Data.Sequence as Seq++-- As a higher level language with a wealth of semantic macros, mdoc+-- discourages authors from falling back to low-level roff features like font+-- selection, custom macros, defined strings, etc. Pandoc's mdoc reader is+-- accordingly implemented as a high-level interpreter of mdoc's semantic macros+-- and almost no raw roff requests are supported.+--+-- tbl(7) and eqn(7) macros are rare but not completely unseen in mdoc manuals.+-- they are not yet implemented. most use of tbl macros in mdoc could probably+-- be replaced with .Bl -column++data DelimSide = Open | Middle | Close deriving (Show, Eq)++-- | Tokens for Mdoc documents+data MdocToken = Str T.Text SourcePos -- ^ The contents of a text line+               | Macro T.Text SourcePos  -- ^ A macro to be processed+               | Lit T.Text SourcePos  -- ^ Literal text on a control line+               | Blank SourcePos  -- ^ A blank line+               | Delim DelimSide T.Text SourcePos  -- ^ A delimiter character+               | Eol  -- ^ The end of a control line+               deriving Show++toString :: MdocToken -> T.Text+toString (Str x _) = x+toString (Macro x _) = x+toString (Lit x _) = x+toString (Delim _ x _) = x+toString Blank{} = mempty+toString Eol = mempty++newtype MdocTokens = MdocTokens { unMdocTokens :: Seq.Seq MdocToken }+        deriving (Show, Semigroup, Monoid)++singleTok :: MdocToken -> MdocTokens+singleTok t = MdocTokens (Seq.singleton t)++type Lexer m = ParsecT Sources () m++instance RoffLikeLexer MdocTokens where+  -- This is a bit confusing. We're lexing to MdocTokens, but for escaping+  -- purposes we just want Texts.+  type Token MdocTokens = T.Text+  -- We don't need a state+  type State MdocTokens = ()+  -- We don't support predefined string expansion+  expandString = return ()+  escString = return mempty+  -- what token type the unescaped text gets wrapped in is decided by other+  -- parts of the lexer.+  emit = id+  -- All escapes are resolved in the lexer and we never need to emit anything,+  -- vs. the roff lexer which has to push the backlashes to the output while+  -- in copy mode.+  backslash = (mempty <* char '\\') <|> (mempty <* string "\\E")+  -- We don't support macro definition and we don't output anything for \A+  checkDefined = const mempty+  -- We don't support copy mode and \E is treated as backslash+  escE = return mempty+  -- We don't support low-level font selection+  escFont = escIgnore 'f' [escapeArg, countChar 1 (satisfy (/='\n'))]++eofline :: (Stream s m Char, UpdateSourcePos s Char) => ParsecT s u m MdocToken+eofline = do+  void newline <|> eof+  return Eol++lexComment :: PandocMonad m => Lexer m MdocTokens+lexComment = do+  try $ string ".\\\""+  skipMany $ noneOf "\n"+  eofline+  return mempty++argText :: PandocMonad m => Lexer m T.Text+argText = do+  beg <- escape <|> regularText+  end <- mconcat <$> many (escape <|> regularText <|> quoteChar)+  return $ beg <> end++spaceTabChar :: PandocMonad m => Lexer m T.Text+spaceTabChar = T.singleton <$> spaceChar++quotedArg :: PandocMonad m => Lexer m T.Text+quotedArg = do+  quoteChar+  t <- mconcat <$> many (try innerQuote <|> escape <|> regularText <|> spaceTabChar)+  quoteChar+  notFollowedBy quoteChar+  return t+  where+    innerQuote = do+      string "\"\""+      return "\""++anyText :: PandocMonad m => Lexer m T.Text+anyText = escape <|> regularText <|> quoteChar <|> spaceTabChar++regularText :: PandocMonad m => Lexer m T.Text+regularText = many1Char $ noneOf "\n\r\t \\\""++quoteChar :: PandocMonad m => Lexer m T.Text+quoteChar = T.singleton <$> char '"'++mdocToken :: PandocMonad m => Lexer m MdocTokens+mdocToken = lexComment <|> lexControlLine <|> lexTextLine++lexMacroName :: PandocMonad m => Lexer m T.Text+lexMacroName = many1Char (satisfy isMacroChar)+  where+    isMacroChar '%' = True+    isMacroChar x = isAlphaNum x++lexMacro :: PandocMonad m => Lexer m MdocToken+lexMacro = do+  pos <- getPosition+  name <- lexMacroName+  eof <|> void (lookAhead (spaceChar <|> newline))+  skipSpaces+  return $ Macro name pos++lexCallableMacro :: PandocMonad m => Lexer m MdocToken+lexCallableMacro = do+  pos <- getPosition+  q <- optionMaybe quoteChar+  name <- lexMacroName+  when (isJust q) (void quoteChar)+  eof <|> void (lookAhead (spaceChar <|> newline))+  skipSpaces+  guard $ isCallableMacro name+  return $ Macro name pos++lexDelim :: (PandocMonad m) => Lexer m MdocToken+lexDelim = do+  pos <- getPosition+  q <- optionMaybe quoteChar+  t <-+    Delim Open <$> oneOfStrings ["(", "["]+      <|> Delim Close <$> oneOfStrings [".", ",", ":", ";", ")", "]", "?", "!"]+      <|> Delim Middle <$> textStr "|"+  when (isJust q) (void quoteChar)+  eof <|> void (lookAhead (spaceChar <|> newline))+  skipSpaces+  return $ t pos++lexLit :: PandocMonad m => Lexer m MdocToken+lexLit = do+  pos <- getPosition+  t <- argText <|> quotedArg+  skipSpaces+  return $ Lit t pos++lexTextLine :: PandocMonad m => Lexer m MdocTokens+lexTextLine = do+  pos <- getPosition+  guard $ sourceColumn pos == 1+  t <- mconcat <$> many anyText+  eofline+  if T.null $ T.strip t+     then return $ singleTok $ Blank pos+     else return $ singleTok $ Str t pos++lexControlLine :: PandocMonad m => Lexer m MdocTokens+lexControlLine = do+  pos <- getPosition+  guard $ sourceColumn pos == 1+  char '.'+  eofline *> mempty <|> do+    m@(Macro name _) <- lexMacro+    -- .Ns macros at the start of a line are ignored. We'd have to look behind+    -- to keep track of the "start of the line" in the parser, so we'll drop+    -- those macros in lexing.+    let start | name == "Ns" = []+              | otherwise = [m]+    let parsed = isParsedMacro name+    (wds, e) <- manyUntil (l parsed) eofline+    return $ MdocTokens $ Seq.fromList $ start <> wds <> [e]+      where+        l True = try lexDelim <|> try lexCallableMacro <|> lexLit+        l False = try lexDelim <|> lexLit++-- | Tokenize a string as a sequence of mdoc tokens.+lexMdoc :: PandocMonad m => SourcePos -> T.Text -> m MdocTokens+lexMdoc pos txt = do+  eithertokens <- readWithM (do setPosition pos+                                mconcat <$> manyTill mdocToken eof) def txt+  case eithertokens of+    Left e       -> throwError e+    Right tokenz -> return tokenz
+ src/Text/Pandoc/Readers/Mdoc/Macros.hs view
@@ -0,0 +1,183 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+   Module      : Text.Pandoc.Readers.Mdoc.Macros+   Copyright   : © 2024 Evan Silberman+   License     : GNU GPL, version 2 or above++   Maintainer  : Evan Silberman <evan@jklol.net>+   Stability   : WIP+   Portability : portable++-}+module Text.Pandoc.Readers.Mdoc.Macros (isParsedMacro, isCallableMacro) where++import Data.Set (member, fromList, Set)+import Data.Text++isParsedMacro :: Text -> Bool+isParsedMacro a = member a parsedMacros++isCallableMacro :: Text -> Bool+isCallableMacro a = member a callableMacros++parsedMacros :: Set Text+parsedMacros = fromList [+  "Ac",+  "Ad",+  "An",+  "Ao",+  "Ap",+  "Aq",+  "Ar",+  "At",+  "Bc",+  "Bo",+  "Bq",+  "Brc",+  "Bro",+  "Brq",+  "Bsx",+  "Bx",+  "Cd",+  "Cm",+  "D1",+  "Dc",+  "Dl",+  "Do",+  "Dq",+  "Dv",+  "Dx",+  "Ec",+  "Em",+  "En",+  "Eo",+  "Er",+  "Es",+  "Ev",+  "Fa",+  "Fc",+  "Fl",+  "Fn",+  "Fr",+  "Ft",+  "Fx",+  "Ic",+  "In",+  "It",+  "Li",+  "Lk",+  "Ms",+  "Mt",+  "Nm",+  "No",+  "Ns",+  "Nx",+  "Oc",+  "Oo",+  "Op",+  "Ot",+  "Ox",+  "Pa",+  "Pc",+  "Pf",+  "Po",+  "Pq",+  "Qc",+  "Ql",+  "Qo",+  "Qq",+  "Sc",+  "Sh",+  "So",+  "Sq",+  "Ss",+  "St",+  "Sx",+  "Sy",+  "Ta",+  "Tn",+  "Ux",+  "Va",+  "Vt",+  "Xc",+  "Xo",+  "Xr"]++callableMacros :: Set Text+callableMacros = fromList [+  "Ac",+  "Ad",+  "An",+  "Ao",+  "Ap",+  "Aq",+  "Ar",+  "At",+  "Bc",+  "Bo",+  "Bq",+  "Brc",+  "Bro",+  "Brq",+  "Bsx",+  "Bx",+  "Cd",+  "Cm",+  "Dc",+  "Do",+  "Dq",+  "Dv",+  "Dx",+  "Ec",+  "Em",+  "En",+  "Eo",+  "Er",+  "Es",+  "Ev",+  "Fa",+  "Fc",+  "Fl",+  "Fn",+  "Fo",+  "Fr",+  "Ft",+  "Fx",+  "Ic",+  "In",+  "Li",+  "Lk",+  "Ms",+  "Mt",+  "Nm",+  "No",+  "Ns",+  "Nx",+  "Oc",+  "Oo",+  "Op",+  "Ot",+  "Ox",+  "Pa",+  "Pc",+  "Pf",+  "Po",+  "Pq",+  "Qc",+  "Ql",+  "Qo",+  "Qq",+  "Sc",+  "So",+  "Sq",+  "St",+  "Sx",+  "Sy",+  "Ta",+  "Tn",+  "Ux",+  "Va",+  "Vt",+  "Xc",+  "Xo",+  "Xr"]
+ src/Text/Pandoc/Readers/Mdoc/Standards.hs view
@@ -0,0 +1,70 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+   Module      : Text.Pandoc.Readers.Mdoc.Standards+   Copyright   : © 2024 Evan Silberman+   License     : GNU GPL, version 2 or above++   Maintainer  : Evan Silberman <evan@jklol.net>+   Stability   : WIP+   Portability : portable++-}+module Text.Pandoc.Readers.Mdoc.Standards (standard) where++import Data.Map (fromList, Map)+import qualified Data.Map as M+import Data.Text++standard :: Text -> Maybe Text+standard = flip M.lookup standards++standards :: Map Text Text+standards = fromList [+  ("-p1003.1-88",    "IEEE Std 1003.1-1988 (“POSIX.1”)"),+  ("-p1003.1-90",    "IEEE Std 1003.1-1990 (“POSIX.1”)"),+  ("-p1003.1-96",    "ISO/IEC 9945-1:1996 (“POSIX.1”)"),+  ("-p1003.1-2001",  "IEEE Std 1003.1-2001 (“POSIX.1”)"),+  ("-p1003.1-2004",  "IEEE Std 1003.1-2004 (“POSIX.1”)"),+  ("-p1003.1-2008",  "IEEE Std 1003.1-2008 (“POSIX.1”)"),+  ("-p1003.1-2024",  "IEEE Std 1003.1-2024 (“POSIX.1”)"),+  ("-p1003.1",       "IEEE Std 1003.1 (“POSIX.1”)"),+  ("-p1003.1b",      "IEEE Std 1003.1b (“POSIX.1b”)"),+  ("-p1003.1b-93",   "IEEE Std 1003.1b-1993 (“POSIX.1b”)"),+  ("-p1003.1c-95",   "IEEE Std 1003.1c-1995 (“POSIX.1c”)"),+  ("-p1003.1g-2000", "IEEE Std 1003.1g-2000 (“POSIX.1g”)"),+  ("-p1003.1i-95",   "IEEE Std 1003.1i-1995 (“POSIX.1i”)"),+  ("-p1003.2",       "IEEE Std 1003.2 (“POSIX.2”)"),+  ("-p1003.2-92",    "IEEE Std 1003.2-1992 (“POSIX.2”)"),+  ("-p1003.2a-92",   "IEEE Std 1003.2a-1992 (“POSIX.2”)"),+  ("-isoC",          "ISO/IEC 9899:1990 (“ISO C90”)"),+  ("-isoC-90",       "ISO/IEC 9899:1990 (“ISO C90”)"),+  ("-isoC-amd1",     "ISO/IEC 9899/AMD1:1995 (“ISO C90, Amendment 1”)"),+  ("-isoC-tcor1",    "ISO/IEC 9899/TCOR1:1994 (“ISO C90, Technical Corrigendum 1”)"),+  ("-isoC-tcor2",    "ISO/IEC 9899/TCOR2:1995 (“ISO C90, Technical Corrigendum 2”)"),+  ("-isoC-99",       "ISO/IEC 9899:1999 (“ISO C99”)"),+  ("-isoC-2011",     "ISO/IEC 9899:2011 (“ISO C11”)"),+  ("-isoC-2023",     "ISO/IEC 9899:2024 (“ISO C23”)"),+  ("-iso9945-1-90",  "ISO/IEC 9945-1:1990 (“POSIX.1”)"),+  ("-iso9945-1-96",  "ISO/IEC 9945-1:1996 (“POSIX.1”)"),+  ("-iso9945-2-93",  "ISO/IEC 9945-2:1993 (“POSIX.2”)"),+  ("-ansiC",         "ANSI X3.159-1989 (“ANSI C89”)"),+  ("-ansiC-89",      "ANSI X3.159-1989 (“ANSI C89”)"),+  ("-ieee754",       "IEEE Std 754-1985"),+  ("-iso8802-3",     "ISO 8802-3: 1989"),+  ("-iso8601",       "ISO 8601"),+  ("-ieee1275-94",   "IEEE Std 1275-1994 (“Open Firmware”)"),+  ("-xpg3",          "X/Open Portability Guide Issue 3 (“XPG3”)"),+  ("-xpg4",          "X/Open Portability Guide Issue 4 (“XPG4”)"),+  ("-xpg4.2",        "X/Open Portability Guide Issue 4, Version 2 (“XPG4.2”)"),+  ("-xbd5",          "X/Open Base Definitions Issue 5 (“XBD5”)"),+  ("-xcu5",          "X/Open Commands and Utilities Issue 5 (“XCU5”)"),+  ("-xsh5",          "X/Open System Interfaces and Headers Issue 5 (“XSH5”)"),+  ("-xns5",          "X/Open Networking Services Issue 5 (“XNS5”)"),+  ("-xns5.2",        "X/Open Networking Services Issue 5.2 (“XNS5.2”)"),+  ("-xcurses4.2",    "X/Open Curses Issue 4, Version 2 (“XCURSES4.2”)"),+  ("-susv1",         "Version 1 of the Single UNIX Specification (“SUSv1”)"),+  ("-susv2",         "Version 2 of the Single UNIX Specification (“SUSv2”)"),+  ("-susv3",         "Version 3 of the Single UNIX Specification (“SUSv3”)"),+  ("-susv4",         "Version 4 of the Single UNIX Specification (“SUSv4”)"),+  ("-svid4",         "System V Interface Definition, Fourth Edition (“SVID4”)")+  ]
src/Text/Pandoc/Readers/MediaWiki.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Readers.MediaWiki-   Copyright   : Copyright (C) 2012-2023 John MacFarlane+   Copyright   : Copyright (C) 2012-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -13,7 +13,7 @@ {- TODO: _ correctly handle tables within tables-_ parse templates?+_ parse templates(?) and built-in magic words -} module Text.Pandoc.Readers.MediaWiki ( readMediaWiki ) where @@ -28,16 +28,17 @@ import Data.Text (Text) import qualified Data.Text as T import Text.HTML.TagSoup-import Text.Pandoc.Builder (Blocks, Inlines, trimInlines) import qualified Text.Pandoc.Builder as B+import Text.Pandoc.Builder (Blocks, Inlines, trimInlines)+import Text.Pandoc.Char (isCJK) import Text.Pandoc.Class.PandocMonad (PandocMonad (..)) import Text.Pandoc.Definition import Text.Pandoc.Logging import Text.Pandoc.Options import Text.Pandoc.Parsing hiding (tableCaption)-import Text.Pandoc.Readers.HTML (htmlTag, isBlockTag, isCommentTag, toAttr)-import Text.Pandoc.Shared (safeRead, stringify, stripTrailingNewlines,-                           trim, splitTextBy, tshow, formatCode)+import Text.Pandoc.Readers.HTML (htmlTag, isCommentTag, toAttr)+import Text.Pandoc.Shared (formatCode, safeRead, splitTextBy, stringify,+                           stripTrailingNewlines, trim, tshow) import Text.Pandoc.XML (fromEntities)  -- | Read mediawiki from an input string and return a Pandoc document.@@ -54,6 +55,8 @@                                             , mwIdentifierList = Set.empty                                             , mwLogMessages = []                                             , mwInTT = False+                                            , mwAllowNewlines = True+                                            , mwMeta = nullMeta                                             }             sources   case parsed of@@ -67,6 +70,8 @@                        , mwIdentifierList  :: Set.Set Text                        , mwLogMessages     :: [LogMessage]                        , mwInTT            :: Bool+                       , mwAllowNewlines   :: Bool+                       , mwMeta            :: Meta                        }  type MWParser m = ParsecT Sources MWState m@@ -87,7 +92,7 @@ --  specialChars :: [Char]-specialChars = "'[]<=&*{}|\":\\"+specialChars = "'[]<=&*{}|\":\\_"  spaceChars :: [Char] spaceChars = " \n\t"@@ -99,21 +104,86 @@ newBlockTags = ["haskell","syntaxhighlight","source","gallery","references"]  isBlockTag' :: Tag Text -> Bool-isBlockTag' tag@(TagOpen t _) = (isBlockTag tag || t `elem` newBlockTags) &&-  t `notElem` eitherBlockOrInline-isBlockTag' (TagClose "ref") = True -- needed so 'special' doesn't parse it-isBlockTag' tag@(TagClose t) = (isBlockTag tag || t `elem` newBlockTags) &&-  t `notElem` eitherBlockOrInline-isBlockTag' tag = isBlockTag tag+isBlockTag' (TagOpen t _) = isBlockTagName t+isBlockTag' (TagClose t) = isBlockTagName t+isBlockTag' _ = False +isBlockTagName :: Text -> Bool+isBlockTagName t =+  t `elem` [ "blockquote"+           , "caption"+           , "col"+           , "colgroup"+           , "dd"+           , "div"+           , "dl"+           , "dt"+           , "h1"+           , "h2"+           , "h3"+           , "h4"+           , "h5"+           , "h6"+           , "hr"+           , "li"+           , "meta"+           , "ol"+           , "p"+           , "pre"+           , "rp"+           , "table"+           , "td"+           , "th"+           , "time"+           , "tr"+           , "ul"+           , "center"+           ] || t `elem` newBlockTags+ isInlineTag' :: Tag Text -> Bool isInlineTag' (TagComment _) = True-isInlineTag' (TagClose "ref") = False -- see below inlineTag-isInlineTag' t              = not (isBlockTag' t)+isInlineTag' (TagOpen t _) = isInlineTagName t+isInlineTag' (TagClose t) = isInlineTagName t+isInlineTag' _ = False -eitherBlockOrInline :: [Text]-eitherBlockOrInline = ["applet", "button", "del", "iframe", "ins",-                               "map", "area", "object"]+isInlineTagName :: Text -> Bool+isInlineTagName t =+  t `elem` [ "abbr"+           , "b"+           , "bdi"+           , "bdo"+           , "big"+           , "br"+           , "cite"+           , "code"+           , "data"+           , "del"+           , "dfn"+           , "em"+           , "i"+           , "ins"+           , "kbd"+           , "link"+           , "mark"+           , "q"+           , "rt"+           , "ruby"+           , "s"+           , "samp"+           , "small"+           , "span"+           , "strong"+           , "sub"+           , "sup"+           , "u"+           , "var"+           , "wbr"+           , "font"+           , "rb"+           , "rtc"+           , "strike"+           , "tt"+           ]  htmlComment :: PandocMonad m => MWParser m () htmlComment = () <$ htmlTag isCommentTag@@ -157,11 +227,12 @@   spaces   eof   categoryLinks <- reverse . mwCategoryLinks <$> getState+  meta <- mwMeta <$> getState   let categories = if null categoryLinks                       then mempty                       else B.para $ mconcat $ intersperse B.space categoryLinks   reportLogMessages-  return $ B.doc $ bs <> categories+  return $ Pandoc meta (B.toList bs <> B.toList categories)  -- -- block parsers@@ -208,10 +279,11 @@                          Just w  -> fromMaybe 1.0 $ parseWidth w                          Nothing -> 1.0   caption <- option mempty tableCaption+  optional newline   optional rowsep   hasheader <- option False $ True <$ lookAhead (skipSpaces *> char '!')-  (cellspecs',hdr) <- unzip <$> tableRow-  let widths = map (tableWidth *) cellspecs'+  (cellwidths,hdr) <- unzip <$> tableRow+  let widths = map (tableWidth *) (concat cellwidths)   let restwidth = tableWidth - sum widths   let zerocols = length $ filter (==0.0) widths   let defaultwidth = if zerocols == 0 || zerocols == length widths@@ -234,10 +306,10 @@                    (TableFoot nullAttr [])  calculateAlignments :: [Cell] -> [Alignment]-calculateAlignments = map cellAligns+calculateAlignments = concatMap cellAligns   where-    cellAligns :: Cell -> Alignment-    cellAligns (Cell _ align _ _ _) = align+    cellAligns :: Cell -> [Alignment]+    cellAligns (Cell _ align _ (ColSpan colspan) _) = replicate colspan align  parseAttrs :: PandocMonad m => MWParser m [(Text,Text)] parseAttrs = many1 parseAttr@@ -251,7 +323,7 @@   skipMany spaceChar   char '='   skipMany spaceChar-  v <- (char '"' >> many1TillChar (satisfy (/='\n')) (char '"'))+  v <- (char '"' >> manyTillChar (satisfy (/='\n')) (char '"'))        <|> many1Char (satisfy $ \c -> not (isSpace c) && c /= '|')   return (k,v) @@ -268,22 +340,16 @@                                <* skipMany htmlComment                                <* blanklines -cellsep :: PandocMonad m => MWParser m ()+cellsep :: PandocMonad m => MWParser m [(Text,Text)] cellsep = try $ do   col <- sourceColumn <$> getPosition-  skipSpaces-  let pipeSep = do-        char '|'-        notFollowedBy (oneOf "-}+")-        if col == 1-           then optional (char '|')-           else void (char '|')-  let exclSep = do-        char '!'-        if col == 1-           then optional (char '!')-           else void (char '!')-  pipeSep <|> exclSep+  skipMany spaceChar+  c <- oneOf "|!"+  when (col > 1) $ void $ char c+  notFollowedBy (oneOf "-}")+  attribs <- option [] (parseAttrs <* skipMany spaceChar <* char '|')+  skipMany spaceChar+  pure attribs  tableCaption :: PandocMonad m => MWParser m Inlines tableCaption = try $ do@@ -293,20 +359,17 @@   sym "|+"   optional (try $ parseAttrs *> skipSpaces *> char '|' *> blanklines)   trimInlines . mconcat <$>-    many (notFollowedBy (cellsep <|> rowsep) *> inline)+    many (notFollowedBy (void cellsep <|> rowsep) *> inline) -tableRow :: PandocMonad m => MWParser m [(Double, Cell)]+tableRow :: PandocMonad m => MWParser m [([Double], Cell)] tableRow = try $ skipMany htmlComment *> many tableCell -tableCell :: PandocMonad m => MWParser m (Double, Cell)+-- multiple widths because cell might have colspan+tableCell :: PandocMonad m => MWParser m ([Double], Cell) tableCell = try $ do-  cellsep-  skipMany spaceChar-  attribs <- option [] $ try $ parseAttrs <* skipSpaces <* char '|' <*-                                 notFollowedBy (char '|')-  skipMany spaceChar+  attribs <- cellsep   pos' <- getPosition-  ls <- T.concat <$> many (notFollowedBy (cellsep <|> rowsep <|> tableEnd) *>+  ls <- T.concat <$> many (notFollowedBy (void cellsep <|> rowsep <|> tableEnd) *>                             ((snd <$> withRaw table) <|> countChar 1 anyChar))   bs <- parseFromString (do setPosition pos'                             mconcat <$> many block) ls@@ -315,18 +378,22 @@                     Just "right"  -> AlignRight                     Just "center" -> AlignCenter                     _             -> AlignDefault-  let width = case lookup "width" attribs of-                    Just xs -> fromMaybe 0.0 $ parseWidth xs-                    Nothing -> 0.0   let rowspan = RowSpan . fromMaybe 1 $                 safeRead =<< lookup "rowspan" attribs   let colspan = ColSpan . fromMaybe 1 $                 safeRead =<< lookup "colspan" attribs+  let ColSpan rawcolspan = colspan   let handledAttribs = ["align", "colspan", "rowspan"]       attribs' = [ (k, v) | (k, v) <- attribs                           , k `notElem` handledAttribs                  ]-  return (width, B.cellWith (toAttr attribs') align rowspan colspan bs)+  let widths = case lookup "width" attribs of+                    Just xs -> maybe (replicate rawcolspan 0.0)+                                 (\w -> replicate rawcolspan+                                    (w / fromIntegral rawcolspan))+                                 (parseWidth xs)+                    Nothing -> replicate rawcolspan 0.0+  return (widths, B.cellWith (toAttr attribs') align rowspan colspan bs)  parseWidth :: Text -> Maybe Double parseWidth s =@@ -456,9 +523,8 @@   guardColumnOne   char ';'   skipMany spaceChar-  pos' <- getPosition-  anyLine >>= parseFromString (do setPosition pos'-                                  trimInlines . mconcat <$> many inline)+  trimInlines . mconcat <$> many (notFollowedBy (oneOf ":\r\n") *> inline) <*+    optional newline  listStart :: PandocMonad m => Char -> MWParser m () listStart c = char c *> notFollowedBy listStartChar@@ -475,7 +541,7 @@  listItem :: PandocMonad m => Char -> MWParser m Blocks listItem c = try $ do-  guardColumnOne+  guardColumnOne <|> guard (c == ':') -- def can start on same line as term   extras <- many (try $ char c <* lookAhead listStartChar)   if null extras      then listItem' c@@ -535,6 +601,7 @@       <|> doubleQuotes       <|> strong       <|> emph+      <|> behaviorSwitch       <|> image       <|> internalLink       <|> externalLink@@ -573,7 +640,11 @@  inlineTag :: PandocMonad m => MWParser m Inlines inlineTag = do-  (tag, _) <- lookAhead $ htmlTag isInlineTag'+  (tag, _) <- lookAhead $ htmlTag (\tag -> case tag of+                                      TagOpen "hask" _ -> True+                                      TagOpen "ref" _ -> True+                                      TagOpen "nowiki" _ -> True+                                      _ -> isInlineTag' tag)   case tag of        TagOpen "ref" _ -> B.note . singleParaToPlain <$> blocksInTags "ref"        TagOpen "nowiki" _ -> try $ do@@ -588,6 +659,10 @@        TagOpen "del" _ -> B.strikeout <$> inlinesInTags "del"        TagOpen "sub" _ -> B.subscript <$> inlinesInTags "sub"        TagOpen "sup" _ -> B.superscript <$> inlinesInTags "sup"+       TagOpen "var" _ -> B.codeWith ("",["variable"],[]) <$> textInTags "var"+       TagOpen "samp" _ -> B.codeWith ("",["sample"],[]) <$> textInTags "samp"+       TagOpen "kbd" _ -> B.spanWith ("",["kbd"],[]) <$> inlinesInTags "kbd"+       TagOpen "mark" _ -> B.spanWith ("",["mark"],[]) <$> inlinesInTags "mark"        TagOpen "code" _ -> encode <$> inlinesInTags "code"        TagOpen "tt" _ -> do          inTT <- mwInTT <$> getState@@ -599,8 +674,15 @@        _ -> B.rawInline "html" . snd <$> htmlTag (~== tag)  special :: PandocMonad m => MWParser m Inlines-special = B.str <$> countChar 1 (notFollowedBy' (htmlTag isBlockTag') *>-                                  oneOf specialChars)+special = B.str . T.singleton <$>+  (notFollowedBy' (htmlTag (\t -> isInlineTag' t ||+                                  isBlockTag' t ||+                                  case t of+                                    TagClose "ref" -> True+                                    TagClose "hask" -> True+                                    TagClose "nowiki" -> True+                                    _ -> False)+                                  ) *> oneOf specialChars)  inlineHtml :: PandocMonad m => MWParser m Inlines inlineHtml = B.rawInline "html" . snd <$> htmlTag isInlineTag'@@ -610,13 +692,14 @@          <|> B.softbreak <$ endline  endline :: PandocMonad m => MWParser m ()-endline = () <$ try (newline <*-                     notFollowedBy spaceChar <*-                     notFollowedBy newline <*-                     notFollowedBy' hrule <*-                     notFollowedBy tableStart <*-                     notFollowedBy' header <*-                     notFollowedBy anyListStart)+endline = do+ getState >>= guard . mwAllowNewlines+ () <$ try (newline <* notFollowedBy spaceChar <*+                       notFollowedBy newline <*+                       notFollowedBy' hrule <*+                       notFollowedBy tableStart <*+                       notFollowedBy' header <*+                       notFollowedBy anyListStart)  imageIdentifier :: PandocMonad m => MWParser m () imageIdentifier = try $ do@@ -670,30 +753,13 @@   sym "]]"   -- see #8525:   linktrail <- B.text <$> manyChar (satisfy (\c -> isLetter c && not (isCJK c)))-  let link = B.link (addUnderscores pagename) "wikilink" (label <> linktrail)+  let link = B.linkWith (mempty, ["wikilink"], mempty) (addUnderscores pagename) (stringify label) (label <> linktrail)   if "Category:" `T.isPrefixOf` pagename      then do        updateState $ \st -> st{ mwCategoryLinks = link : mwCategoryLinks st }        return mempty      else return link -isCJK :: Char -> Bool-isCJK c =-  (c >= '\x3400' && c <= '\x4DBF') ||-  (c >= '\x4E00' && c <= '\x9FFF') ||-  (c >= '\x20000' && c <= '\x2A6DF') ||-  (c >= '\x2A700' && c <= '\x2B73F') ||-  (c >= '\x2B740' && c <= '\x2B81F') ||-  (c >= '\x2B820' && c <= '\x2CEAF') ||-  (c >= '\x2CEB0' && c <= '\x2EBEF') ||-  (c >= '\x30000' && c <= '\x3134F') ||-  (c >= '\x31350' && c <= '\x323AF') ||-  (c >= '\xF900' && c <= '\xFAFF') ||-  (c >= '\x2F800' && c <= '\x2FA1F') ||-  (c >= '\x2F00' && c <= '\x2FDF') ||-  (c >= '\x2E80' && c <= '\x2EFF') ||-  (c >= '\x3000' && c <= '\x303F')- externalLink :: PandocMonad m => MWParser m Inlines externalLink = try $ do   char '['@@ -734,3 +800,37 @@   B.doubleQuoted <$> inlinesBetween openDoubleQuote closeDoubleQuote     where openDoubleQuote = sym "\"" >> lookAhead nonspaceChar           closeDoubleQuote = try $ sym "\""++behaviorSwitch :: PandocMonad m => MWParser m Inlines+behaviorSwitch = try $ do+  let reservedMagicWords = [ "NOTOC"+              , "FORCETOC"+              , "TOC"+              , "NOEDITSECTION"+              , "NEWSECTIONLINK"+              , "NONEWSECTIONLINK"+              , "NOGALLERY"+              , "HIDDENCAT"+              , "EXPECTUNUSEDCATEGORY"+              , "NOCONTENTCONVERT"+              , "NOCC"+              , "NOTITLECONVERT"+              , "NOTC"+              , "INDEX"+              , "NOINDEX"+              , "STATICREDIRECT"+              , "EXPECTUNUSEDTEMPLATE"+              -- From popular extensions+              , "NOGLOBAL"+              , "DISAMBIG"+              , "ARCHIVEDTALK"+              , "NOTALK"+              ]+  string "__"+  name <- many1 alphaNum+  string "__"+  case name `elem` reservedMagicWords of+    True -> do+      updateState $ \st -> st{ mwMeta = B.setMeta (T.toLower $ T.pack name) True (mwMeta st) }+      return mempty+    False -> return $ B.str $ "__" <> T.pack name <> "__"
src/Text/Pandoc/Readers/Metadata.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE ScopedTypeVariables #-} {- |    Module      : Text.Pandoc.Readers.Metadata-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -21,36 +21,62 @@ import Control.Monad.Except (throwError) import qualified Data.ByteString as B import qualified Data.Map as M+import qualified Data.Vector as V import Data.Text (Text) import qualified Data.Text as T import qualified Data.Yaml as Yaml-import Data.Aeson (Value(..), Object, Result(..), fromJSON, (.:?), withObject)-import Data.Aeson.Types (parse)+import qualified Data.Yaml.Internal as Yaml+import qualified Text.Libyaml as Y+import Data.Aeson (Value(..), Object, Result(..), fromJSON, (.:?), withObject,+                   FromJSON)+import Data.Aeson.Types (formatRelativePath, parse) import Text.Pandoc.Shared (tshow, blocksToInlines)-import Text.Pandoc.Class.PandocMonad (PandocMonad (..))+import Text.Pandoc.Class (PandocMonad (..), report) import Text.Pandoc.Definition import Text.Pandoc.Error+import Text.Pandoc.Logging (LogMessage(YamlWarning)) import Text.Pandoc.Parsing hiding (tableWith, parse) import qualified Text.Pandoc.UTF8 as UTF8+import System.IO.Unsafe (unsafePerformIO)  yamlBsToMeta :: (PandocMonad m, HasLastStrPosition st)              => ParsecT Sources st m (Future st MetaValue)              -> B.ByteString              -> ParsecT Sources st m (Future st Meta) yamlBsToMeta pMetaValue bstr = do-  case Yaml.decodeAllEither' bstr of-       Right (Object o:_) -> fmap Meta <$> yamlMap pMetaValue o-       Right [] -> return . return $ mempty-       Right [Null] -> return . return $ mempty-       Right _  -> Prelude.fail "expected YAML object"+  pos <- getPosition+  case decodeAllWithWarnings bstr of+       Right (warnings, xs) -> do+         mapM_ (\(Yaml.DuplicateKey jpath) ->+                          report (YamlWarning pos $ "Duplicate key: " <>+                                  T.pack (formatRelativePath jpath)))+           warnings+         case xs of+           (Object o : _) -> fmap Meta <$> yamlMap pMetaValue o+           [Null] -> return . return $ mempty+           [] -> return . return $ mempty+           _  -> Prelude.fail "expected YAML object"        Left err' -> do-         let msg = T.pack $ Yaml.prettyPrintParseException err'+         let msg = T.pack $ "Error parsing YAML metadata at " <>+                             show pos <> ":\n" <>+                             Yaml.prettyPrintParseException err'          throwError $ PandocParseError $            if "did not find expected key" `T.isInfixOf` msg               then msg <>                    "\nConsider enclosing the entire field in 'single quotes'"               else msg +decodeAllWithWarnings :: FromJSON a+                      => B.ByteString+                      -> (Either Yaml.ParseException ([Yaml.Warning], [a]))+decodeAllWithWarnings = either Left (\(ws,res)+                       -> case res of+                            Left s  -> Left (Yaml.AesonException s)+                            Right v -> Right (ws, v))+                   . unsafePerformIO+                   . Yaml.decodeAllHelper+                   . Y.decode+ -- Returns filtered list of references. yamlBsToRefs :: (PandocMonad m, HasLastStrPosition st)              => ParsecT Sources st m (Future st MetaValue)@@ -60,20 +86,24 @@ yamlBsToRefs pMetaValue idpred bstr =   case Yaml.decodeAllEither' bstr of        Right (Object m : _) -> do-         let isSelected (String t) = idpred t-             isSelected _ = False-         let hasSelectedId (Object o) =-               case parse (withObject "ref" (.:? "id")) (Object o) of-                 Success (Just id') -> isSelected id'-                 _ -> False-             hasSelectedId _ = False          case parse (withObject "metadata" (.:? "references")) (Object m) of            Success (Just refs) -> sequence <$>                  mapM (yamlToMetaValue pMetaValue) (filter hasSelectedId refs)            _ -> return $ return []+       Right (Array v : _) -> do+         let refs = filter hasSelectedId $ V.toList v+         sequence <$> mapM (yamlToMetaValue pMetaValue) (filter hasSelectedId refs)        Right _ -> return . return $ []        Left err' -> throwError $ PandocParseError                                $ T.pack $ Yaml.prettyPrintParseException err'+ where+   isSelected (String t) = idpred t+   isSelected _ = False+   hasSelectedId (Object o) =+     case parse (withObject "ref" (.:? "id")) (Object o) of+       Success (Just id') -> isSelected id'+       _ -> False+   hasSelectedId _ = False  normalizeMetaValue :: (PandocMonad m, HasLastStrPosition st)                    => ParsecT Sources st m (Future st MetaValue)@@ -142,6 +172,7 @@               => ParsecT Sources st m (Future st MetaValue)               -> ParsecT Sources st m (Future st Meta) yamlMetaBlock parser = try $ do+  pos <- getPosition   string "---"   blankline   notFollowedBy blankline  -- if --- is followed by a blank it's an HRULE@@ -149,7 +180,11 @@   -- by including --- and ..., we allow yaml blocks with just comments:   let rawYaml = T.unlines ("---" : (rawYamlLines ++ ["..."]))   optional blanklines-  yamlBsToMeta parser $ UTF8.fromText rawYaml+  oldPos <- getPosition+  setPosition pos+  res <- yamlBsToMeta parser $ UTF8.fromText rawYaml+  setPosition oldPos+  pure res  stopLine :: Monad m => ParsecT Sources st m () stopLine = try $ (string "---" <|> string "...") >> blankline >> return ()
src/Text/Pandoc/Readers/Native.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Readers.Native-   Copyright   : Copyright (C) 2011-2023 John MacFarlane+   Copyright   : Copyright (C) 2011-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>
src/Text/Pandoc/Readers/ODT.hs view
@@ -15,7 +15,9 @@  import Codec.Archive.Zip import Text.Pandoc.XML.Light+import Text.Pandoc.Walk +import Data.Char (isDigit) import qualified Data.ByteString.Lazy as B  import System.FilePath@@ -46,8 +48,23 @@ readODT opts bytes = case readODT' opts bytes of   Right (doc, mb) -> do     P.setMediaBag mb-    return doc+    return $ walk makeFigure doc   Left e -> throwError e++-- the ODT parser uses old-style figures: an image with title beginning+-- "fig:" in a paragraph by itself.  Convert these to new Figure elements.+makeFigure :: Block -> Block+makeFigure (Para [ Image (ident, classes, kvs) capt (src, tit) ])+  | "fig:" `T.isPrefixOf` tit+  = Figure (ident, [], []) (Caption Nothing [Plain capt'])+      [Plain [Image ("", classes, kvs) capt (src, "")]]+   where+     capt' = case capt of -- strip "Figure 1:" for consistency+                 (Str _ : Space : Str t : Space : xs)+                    | T.all (\c -> isDigit c || c == ':') t+                    , ":" `T.isSuffixOf` t -> xs+                 xs -> xs+makeFigure x = x  -- readODT' :: ReaderOptions
src/Text/Pandoc/Readers/ODT/Arrows/State.hs view
@@ -17,12 +17,26 @@ faster and easier to implement this way. -} -module Text.Pandoc.Readers.ODT.Arrows.State where+module Text.Pandoc.Readers.ODT.Arrows.State+  ( ArrowState(..)+  , withState+  , modifyState+  , ignoringState+  , fromState+  , extractFromState+  , tryModifyState+  , withSubStateF+  , withSubStateF'+  , foldS+  , iterateS+  , iterateSL+  , iterateS'+  ) where +import qualified Data.List as L import Control.Arrow import qualified Control.Category as Cat import Control.Monad-import Data.List (foldl') import Text.Pandoc.Readers.ODT.Arrows.Utils import Text.Pandoc.Readers.ODT.Generic.Fallible @@ -122,7 +136,7 @@ iterateSL :: (Foldable f, MonadPlus m)           => ArrowState s    x     y           -> ArrowState s (f x) (m y)-iterateSL a = ArrowState $ \(s,f) -> foldl' a' (s,mzero) f+iterateSL a = ArrowState $ \(s,f) -> L.foldl' a' (s,mzero) f   where a' (s',m) x = second (mplus m.return) $ runArrowState a (s',x)  
src/Text/Pandoc/Readers/ODT/Arrows/Utils.hs view
@@ -19,7 +19,40 @@ -}  -- We export everything-module Text.Pandoc.Readers.ODT.Arrows.Utils where+module Text.Pandoc.Readers.ODT.Arrows.Utils+  ( and2+  , and3+  , and4+  , and5+  , and6+  , liftA2+  , liftA3+  , liftA4+  , liftA5+  , liftA6+  , liftA+  , duplicate+  , (>>%)+  , keepingTheValue+  , (^|||)+  , (|||^)+  , (^|||^)+  , (^&&&)+  , (&&&^)+  , choiceToMaybe+  , maybeToChoice+  , returnV+  , FallibleArrow+  , liftAsSuccess+  , (>>?)+  , (>>?^)+  , (>>?^?)+  , (^>>?)+  , (>>?!)+  , (>>?%)+  , (>>?%?)+  , ifFailedDo+  ) where  import Prelude hiding (Applicative(..)) import Control.Arrow
src/Text/Pandoc/Readers/ODT/Base.hs view
@@ -10,7 +10,11 @@ Core types of the odt reader. -} -module Text.Pandoc.Readers.ODT.Base where+module Text.Pandoc.Readers.ODT.Base+  ( ODTConverterState+  , XMLReader+  , XMLReaderSafe+  ) where  import Text.Pandoc.Readers.ODT.Generic.XMLConverter import Text.Pandoc.Readers.ODT.Namespaces
src/Text/Pandoc/Readers/ODT/ContentReader.hs view
@@ -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@@ -393,44 +396,29 @@  -- | Returns either 'id' or 'blockQuote' depending if any of the StyleProperties -- are indented at quote level.-getParaModifier :: [StyleProperties] -> ParaModifier-getParaModifier props | any isBlockQuote props-                       = blockQuote-                       | otherwise-                       = id+getParaModifier :: ListLevel -> [StyleProperties] -> ParaModifier+getParaModifier listLevel props+  | listLevel > 0 = id -- see #9505, list paragraphs need indentation+  | any isBlockQuote props = blockQuote+  | otherwise = id   where   isBlockQuote SProps {..} | Just paraProps <- paraProperties-                                    , isQuoteWidth (indentation paraProps)-                                                  (margin_left paraProps)+                                    , isQuoteWidth (margin_left paraProps)                                     = True                                     | otherwise                                     = False-  isQuoteWidth mIndent mMargin-    | LengthValueMM indent <- mIndent-    ,  indent          > _MINIMUM_INDENTATION_FOR_BLOCKQUOTES_IN_MM_-     = True+  isQuoteWidth mMargin     | LengthValueMM margin <- mMargin     ,           margin > _MINIMUM_INDENTATION_FOR_BLOCKQUOTES_IN_MM_      = True-    | LengthValueMM indent <- mIndent-    , LengthValueMM margin <- mMargin-     = indent + margin > _MINIMUM_INDENTATION_FOR_BLOCKQUOTES_IN_MM_--    | PercentValue  indent <- mIndent-    ,  indent          > _MINIMUM_INDENTATION_FOR_BLOCKQUOTES_IN_PERCENT_-     = True     | PercentValue  margin <- mMargin     ,           margin > _MINIMUM_INDENTATION_FOR_BLOCKQUOTES_IN_PERCENT_      = True-    | PercentValue  indent <- mIndent-    , PercentValue  margin <- mMargin-     = indent + margin > _MINIMUM_INDENTATION_FOR_BLOCKQUOTES_IN_PERCENT_-     | otherwise      = 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@@ -440,7 +428,8 @@       arr tableCaptionP  -< blocks'     Right (_, style) -> do       props <- fromStyles extendedStylePropertyChain -< [style]-      let modifier = getParaModifier props+      listLevel <- getCurrentListLevel -< ()+      let modifier = getParaModifier listLevel props       blocks' <- reader   -<  blocks       arr modifier        -<< blocks'   where@@ -560,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@@ -573,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  --------------------------------------------@@ -648,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@@ -697,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@@ -720,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+                                            ]   ----------------------@@ -782,7 +798,7 @@  read_note_body   :: BlockMatcher read_note_body    = matchingElement NsText "note-body"-                    $ matchChildContent' [ read_paragraph ]+                    $ matchSmushedChildBlocks' [ read_paragraph ]  ------------------------- -- Citations@@ -806,33 +822,48 @@ ----------------------  ---read_table        :: BlockMatcher+read_table        :: ElementMatcher CombiningBlocks read_table         = matchingElement NsTable "table"-                     $ liftA simpleTable'-                     $ matchChildContent'  [ read_table_row-                                           ]+                     $ liftA (CombiningBlocks . table')+                     $ (matchChildContent' [read_table_header]) &&&+                       (matchChildContent' [read_table_row]) --- | A simple table without a caption or headers--- | Infers the number of headers from rows-simpleTable' :: [[Blocks]] -> Blocks-simpleTable' []         = simpleTable [] []-simpleTable' (x : rest) = simpleTable (fmap (const defaults) x) (x : rest)-  where defaults = fromList []+-- | A table without a caption.+table' :: ([[Cell]], [[Cell]]) -> Blocks+table' (headers, rows) =+  table emptyCaption (replicate numcols defaults) th [tb] tf+  where+    defaults = (AlignDefault, ColWidthDefault)+    numcols = maximum $ map length $ headers ++ rows+    toRow = Row nullAttr+    th = TableHead nullAttr $ map toRow headers+    tb = TableBody nullAttr 0 [] $ map toRow rows+    tf = TableFoot nullAttr []  ---read_table_row    :: ElementMatcher [[Blocks]]+read_table_header :: ElementMatcher [[Cell]]+read_table_header = matchingElement NsTable "table-header-rows"+                      $ matchChildContent' [ read_table_row+                                           ]++--+read_table_row    :: ElementMatcher [[Cell]] read_table_row     = matchingElement NsTable "table-row"                      $ liftA (:[])                      $ matchChildContent'  [ read_table_cell                                            ]  ---read_table_cell   :: ElementMatcher [Blocks]+read_table_cell   :: ElementMatcher [Cell] read_table_cell    = matchingElement NsTable "table-cell"-                     $ liftA (compactify.(:[]))-                     $ matchChildContent' [ read_paragraph-                                          , read_list-                                          ]+                     $ liftA3 cell'+                       (readAttrWithDefault NsTable "number-rows-spanned" 1 >>^ RowSpan)+                       (readAttrWithDefault NsTable "number-columns-spanned" 1 >>^ ColSpan)+                     $ matchSmushedChildBlocks' [ read_paragraph+                                                , read_list+                                                ]+  where+    cell' rowSpan colSpan blocks = map (cell AlignDefault rowSpan colSpan) $ compactify [blocks]  ---------------------- -- Frames@@ -861,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)@@ -897,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@@ -918,7 +950,7 @@ _ANCHOR_PREFIX_ = "anchor"  ---readAnchorAttr :: ODTReader _x Anchor+readAnchorAttr :: ODTReader a Anchor readAnchorAttr = findAttrText NsText "name"  -- | Beware: may fail@@ -959,7 +991,7 @@                      $ maybeAddAnchorFrom readAnchorAttr  -- | Beware: may fail-findAnchorRef :: ODTReader _x Anchor+findAnchorRef :: ODTReader a Anchor findAnchorRef = (      findAttrText NsText "ref-name"                   >>?^ (_ANCHOR_PREFIX_,)                 ) >>?! getPrettyAnchor@@ -994,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@@ -1012,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
src/Text/Pandoc/Readers/ODT/Generic/Fallible.hs view
@@ -17,7 +17,21 @@ -}  -- We export everything-module Text.Pandoc.Readers.ODT.Generic.Fallible where+module Text.Pandoc.Readers.ODT.Generic.Fallible+  ( Failure+  , Fallible+  , maybeToEither+  , eitherToMaybe+  , recover+  , failWith+  , failEmpty+  , succeedWith+  , collapseEither+  , chooseMax+  , chooseMaxWith+  , ChoiceVector(..)+  , SuccessList(..)+  ) where  -- | Default for now. Will probably become a class at some point. type Failure = ()
src/Text/Pandoc/Readers/ODT/Generic/Namespaces.hs view
@@ -11,7 +11,11 @@ typesafe Haskell namespace identifiers and unsafe "real world" namespaces. -} -module Text.Pandoc.Readers.ODT.Generic.Namespaces where+module Text.Pandoc.Readers.ODT.Generic.Namespaces+  ( NameSpaceIRI+  , NameSpaceIRIs+  , NameSpaceID(..)+  ) where  import qualified Data.Map as M import Data.Text (Text)
src/Text/Pandoc/Readers/ODT/Generic/SetMap.hs view
@@ -10,7 +10,13 @@ A map of values to sets of values. -} -module Text.Pandoc.Readers.ODT.Generic.SetMap where+module Text.Pandoc.Readers.ODT.Generic.SetMap+  ( SetMap+  , empty+  , fromList+  , insert+  , union3+  ) where  import qualified Data.Map as M import qualified Data.Set as S
src/Text/Pandoc/Readers/ODT/Generic/XMLConverter.hs view
@@ -64,7 +64,9 @@ import           Data.Text (Text) import           Data.Default import           Data.Maybe-import           Data.List (foldl')+import qualified Data.List as L+import qualified Data.List.NonEmpty as NonEmpty+import           Data.List.NonEmpty (NonEmpty(..))  import qualified Text.Pandoc.XML.Light as XML @@ -101,7 +103,7 @@          -- Arguably, a real Zipper would be better. But that is an          -- optimization that can be made at a later time, e.g. when          -- replacing Text.XML.Light.-         parentElements    :: [XML.Element]+         parentElements    :: NonEmpty XML.Element          -- | A map from internal namespace IDs to the namespace prefixes          -- used in XML elements        , namespacePrefixes :: NameSpacePrefixes nsID@@ -126,7 +128,7 @@                     -> XMLConverterState nsID extraState createStartState element extraState =   XMLConverterState-       { parentElements    = [element]+       { parentElements    = element :| []        , namespacePrefixes = M.empty        , namespaceIRIs     = getInitialIRImap        , moreState         = extraState@@ -147,13 +149,14 @@ -- currentElement      :: XMLConverterState nsID extraState                     -> XML.Element-currentElement state = head (parentElements state)+currentElement state = NonEmpty.head (parentElements state)  -- | Replace the current position by another, modifying the extra state -- in the process swapStack'          :: XMLConverterState nsID extraState-                    -> [XML.Element]-                    -> ( XMLConverterState nsID extraState , [XML.Element] )+                    -> NonEmpty XML.Element+                    -> ( XMLConverterState nsID extraState+                       , NonEmpty XML.Element ) swapStack' state stack                      = ( state { parentElements = stack }                        , parentElements state@@ -163,14 +166,16 @@ pushElement         :: XML.Element                     -> XMLConverterState nsID extraState                     -> XMLConverterState nsID extraState-pushElement e state  = state { parentElements = e:parentElements state }+pushElement e state  = state { parentElements =+                                 NonEmpty.cons e (parentElements state) }  -- | Pop the top element from the call stack, unless it is the last one. popElement          :: XMLConverterState nsID extraState                     -> Maybe (XMLConverterState nsID extraState) popElement state-  | _:es@(_:_) <- parentElements state = Just $ state { parentElements = es }-  | otherwise                          = Nothing+  | _ :| (e:es) <- parentElements state+                = Just $ state { parentElements = e :| es }+  | otherwise   = Nothing  -------------------------------------------------------------------------------- -- Main type@@ -293,7 +298,7 @@                          => XMLConverterState nsID extraState                          -> Maybe (XMLConverterState nsID extraState)     extractNSAttrs startState-                         = foldl' (\state d -> state >>= addNS d)+                         = L.foldl' (\state d -> state >>= addNS d)                                  (Just startState)                                  nsAttribs       where nsAttribs    = mapMaybe readNSattr (XML.elAttribs element)@@ -544,7 +549,8 @@                                    )  ---swapStack             :: XMLConverter nsID extraState [XML.Element] [XML.Element]+swapStack             :: XMLConverter nsID extraState (NonEmpty XML.Element)+                                                      (NonEmpty XML.Element) swapStack             = withState swapStack'  --@@ -559,7 +565,7 @@ -- accessible to the converter. switchingTheStack      :: XMLConverter nsID moreState a b                        -> XMLConverter nsID moreState (a, XML.Element) b-switchingTheStack a    =     second ( (:[]) ^>> swapStack )+switchingTheStack a    =     second ( (:| []) ^>> swapStack )                          >>> first  a                          >>> second swapStack                          >>^ fst
src/Text/Pandoc/Readers/ODT/StyleReader.hs view
@@ -45,7 +45,7 @@  import Data.Default import qualified Data.Foldable as F-import Data.List (unfoldr, foldl')+import qualified Data.List as L import qualified Data.Map as M import Data.Maybe import Data.Text (Text)@@ -114,14 +114,14 @@ -- 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"                               &&&                               lookupDefaultingAttr NsStyle "font-pitch"                             ))-                    >>?^ ( M.fromList . foldl' accumLegalPitches [] )+                    >>?^ ( M.fromList . L.foldl' accumLegalPitches [] )                   ) `ifFailedDo` returnV (Right M.empty)   where accumLegalPitches ls (Nothing,_) = ls         accumLegalPitches ls (Just n,p)  = (n,p):ls@@ -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@@ -603,7 +603,7 @@ -- be the first element of the list, followed by its parent and so on. -- The current style is not in the list. parents               :: Style       -> Styles ->      [Style]-parents style styles = unfoldr findNextParent style -- Ha!+parents style styles = L.unfoldr findNextParent style -- Ha!   where findNextParent Style{..}           = fmap duplicate $ (`lookupStyle` styles) =<< styleParentName 
+ src/Text/Pandoc/Readers/OOXML/Shared.hs view
@@ -0,0 +1,95 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+   Module      : Text.Pandoc.Readers.OOXML.Shared+   Copyright   : © 2025 Anton Antic+   License     : GNU GPL, version 2 or above++   Maintainer  : Anton Antic <anton@everworker.ai>+   Stability   : alpha+   Portability : portable++Shared utilities for Office Open XML (OOXML) readers (DOCX, PPTX).+Provides common functions for ZIP archive handling, XML parsing,+namespace management, and DrawingML parsing.+-}+module Text.Pandoc.Readers.OOXML.Shared+  ( -- * Constants+    emusPerInch+  , emuToInches+  , inchesToEmu+    -- * Types+  , NameSpaces+  , elemName+  , elemToNameSpaces+  , isElem+  , findChildByName+  , findChildrenByName+  , findElementByName+  , findAttrByName+  ) where++import qualified Data.Map as M+import qualified Data.Text as T+import Data.Text (Text)+import Text.Pandoc.XML.Light++-- | Type alias for namespace mappings+type NameSpaces = M.Map Text Text++-- | English Metric Units per inch+-- 1 inch = 914400 EMUs (used in OOXML for dimensions)+emusPerInch :: Integer+emusPerInch = 914400++-- | Convert EMUs to inches+emuToInches :: Integer -> Double+emuToInches n = fromIntegral n / fromIntegral emusPerInch++-- | Convert inches to EMUs+inchesToEmu :: Double -> Integer+inchesToEmu n = round (n * fromIntegral emusPerInch)++-- | Extract namespace declarations from element attributes+elemToNameSpaces :: Element -> NameSpaces+elemToNameSpaces = foldr (\(Attr qn val) ->+                            case qn of+                              QName s _ (Just "xmlns") -> M.insert s val+                              _ -> id) mempty . elAttribs++-- | Create a qualified name from namespace map, prefix, and local name+elemName :: NameSpaces -> Text -> Text -> QName+elemName ns prefix name =+  QName name+        (M.lookup prefix ns)+        (if T.null prefix then Nothing else Just prefix)++-- | Check if element matches namespace prefix and local name+isElem :: NameSpaces -> Text -> Text -> Element -> Bool+isElem ns prefix name element =+  let ns' = ns <> elemToNameSpaces element+  in  qName (elName element) == name &&+      qURI (elName element) == M.lookup prefix ns'++-- | Find first child element matching namespace and name+findChildByName :: NameSpaces -> Text -> Text -> Element -> Maybe Element+findChildByName ns pref name el =+  let ns' = ns <> elemToNameSpaces el+  in  findChild (elemName ns' pref name) el++-- | Find all children matching namespace and name+findChildrenByName :: NameSpaces -> Text -> Text -> Element -> [Element]+findChildrenByName ns pref name el =+  let ns' = ns <> elemToNameSpaces el+  in  findChildren (elemName ns' pref name) el++-- | Find element anywhere in descendants matching namespace and name+findElementByName :: NameSpaces -> Text -> Text -> Element -> Maybe Element+findElementByName ns pref name el =+  let ns' = ns <> elemToNameSpaces el+  in  findElement (elemName ns' pref name) el++-- | Find attribute value by namespace prefix and name+findAttrByName :: NameSpaces -> Text -> Text -> Element -> Maybe Text+findAttrByName ns pref name el =+  let ns' = ns <> elemToNameSpaces el+  in  findAttr (elemName ns' pref name) el
src/Text/Pandoc/Readers/OPML.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Readers.OPML-   Copyright   : Copyright (C) 2013-2023 John MacFarlane+   Copyright   : Copyright (C) 2013-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>
src/Text/Pandoc/Readers/Org.hs view
@@ -1,9 +1,9 @@ {- |    Module      : Text.Pandoc.Readers.Org-   Copyright   : Copyright (C) 2014-2023 Albert Krewinkel+   Copyright   : Copyright (C) 2014-2024 Albert Krewinkel    License     : GNU GPL, version 2 or above -   Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>  Conversion of org-mode formatted plain text to 'Pandoc' document. -}
src/Text/Pandoc/Readers/Org/BlockStarts.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Readers.Org.BlockStarts-   Copyright   : Copyright (C) 2014-2023 Albert Krewinkel+   Copyright   : Copyright (C) 2014-2024 Albert Krewinkel    License     : GNU GPL, version 2 or above -   Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>  Parsers for Org-mode inline elements. -}@@ -23,13 +23,14 @@   , endOfBlock   ) where -import Control.Monad (void)+import Control.Monad (void, guard) import Data.Text (Text) import Text.Pandoc.Readers.Org.Parsing import Text.Pandoc.Definition as Pandoc import Text.Pandoc.Shared (safeRead) import Text.Pandoc.Parsing (lowerAlpha, upperAlpha) import Text.Pandoc.Extensions+import Text.Pandoc.Readers.LaTeX.Math (inlineEnvironmentNames) import Data.Functor (($>))  -- | Horizontal Line (five -- dashes or more)@@ -55,10 +56,13 @@   latexEnvStart :: Monad m => OrgParser m Text-latexEnvStart = try $-  skipSpaces *> string "\\begin{"-             *> latexEnvName-             <* string "}"+latexEnvStart = try $ do+  skipSpaces+  string "\\begin{"+  name <- latexEnvName+  char '}'+  guard $ name `notElem` inlineEnvironmentNames+  pure name  where    latexEnvName :: Monad m => OrgParser m Text    latexEnvName = try $ mappend <$> many1Char alphaNum <*> option "" (textStr "*")
src/Text/Pandoc/Readers/Org/Blocks.hs view
@@ -1,13 +1,14 @@+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE FlexibleContexts  #-} {-# LANGUAGE LambdaCase        #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards   #-} {- |    Module      : Text.Pandoc.Readers.Org.Blocks-   Copyright   : Copyright (C) 2014-2023 Albert Krewinkel+   Copyright   : Copyright (C) 2014-2024 Albert Krewinkel    License     : GNU GPL, version 2 or above -   Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>  Parsers for Org-mode block elements. -}@@ -25,7 +26,7 @@ import Text.Pandoc.Readers.Org.Parsing import Text.Pandoc.Readers.Org.Shared (cleanLinkText, isImageFilename,                                        originalLang, translateLang, exportsCode)-+import Text.Pandoc.Readers.LaTeX.Math (inlineEnvironmentNames) import Text.Pandoc.Builder (Blocks, Inlines, Many(..)) import Text.Pandoc.Class.PandocMonad (PandocMonad) import Text.Pandoc.Definition@@ -33,10 +34,11 @@ import Text.Pandoc.Shared (compactify, compactifyDL, safeRead)  import Control.Monad (foldM, guard, mzero, void)+import Data.Bifunctor (bimap) import Data.Char (isSpace) import Data.Default (Default) import Data.Functor (($>))-import Data.List (find, foldl')+import qualified Data.List as L import Data.Maybe (fromMaybe, isJust, isNothing) import Data.Text (Text) import Data.List.NonEmpty (nonEmpty)@@ -71,6 +73,7 @@ block :: PandocMonad m => OrgParser m (F Blocks) block = choice [ mempty <$ blanklines                , table+               , dynamicBlock                , orgBlock                , figure                , example@@ -113,7 +116,7 @@  stringyMetaAttribute :: Monad m => OrgParser m (Text, Text) stringyMetaAttribute = try $ do-  metaLineStart+  metaLineStart *> notFollowedBy (stringAnyCase "begin" *> oneOf ":_")   attrName <- T.toLower <$> many1TillChar nonspaceChar (char ':')   skipSpaces   attrValue <- anyLine <|> ("" <$ newline)@@ -127,9 +130,9 @@ blockAttributes = try $ do   kv <- many stringyMetaAttribute   guard $ all (isBlockAttr . fst) kv-  let caption = foldl' (appendValues "caption") Nothing kv-  let kvAttrs = foldl' (appendValues "attr_html") Nothing kv-  let name    = snd <$> find ((`elem` ["name", "label"]) . fst) (reverse kv)+  let caption = L.foldl' (appendValues "caption") Nothing kv+  let kvAttrs = L.foldl' (appendValues "attr_html") Nothing kv+  let name    = snd <$> L.find ((`elem` ["name", "label"]) . fst) (reverse kv)   caption' <- traverse (parseFromString inlines . (<> "\n")) caption   kvAttrs' <- parseFromString keyValues . (<> "\n") $ fromMaybe mempty kvAttrs   return BlockAttributes@@ -182,11 +185,11 @@     case T.toLower blkType of       "export"    -> exportBlock       "comment"   -> rawBlockLines (const mempty)-      "html"      -> rawBlockLines (return . B.rawBlock (lowercase blkType))-      "latex"     -> rawBlockLines (return . B.rawBlock (lowercase blkType))-      "ascii"     -> rawBlockLines (return . B.rawBlock (lowercase blkType))+      "html"      -> rawBlockLines (return . B.rawBlock (T.toLower blkType))+      "latex"     -> rawBlockLines (return . B.rawBlock (T.toLower blkType))+      "ascii"     -> rawBlockLines (return . B.rawBlock (T.toLower blkType))       "example"   -> exampleBlock blockAttrs-      "quote"     -> parseBlockLines (fmap B.blockQuote)+      "quote"     -> \x -> ignHeaders *> parseBlockLines (fmap B.blockQuote) x       "verse"     -> verseBlock       "src"       -> codeBlock blockAttrs       "note"      -> admonitionBlock "note" blockAttrs@@ -198,20 +201,23 @@         -- case-sensitive checks         case blkType of           "abstract" -> metadataBlock-          _ -> parseBlockLines $-                   let (ident, classes, kv) = attrFromBlockAttributes blockAttrs-                   in fmap $ B.divWith (ident, classes ++ [blkType], kv)+          _ -> \bt -> do+            params <- blockParameters+            let (ident, classes, kv) = attrFromBlockAttributes blockAttrs+                toDiv = (B.divWith (ident, classes ++ [blkType], kv <> params))+            parseBlockLines (fmap toDiv) bt  where    blockHeaderStart :: Monad m => OrgParser m Text-   blockHeaderStart = try $ skipSpaces *> stringAnyCase "#+begin_" *> orgArgWord--   lowercase :: Text -> Text-   lowercase = T.toLower+   blockHeaderStart = try $ do+     skipSpaces+     metaLineStart+     stringAnyCase "begin_"+     many1Char (satisfy (not . isSpace))  admonitionBlock :: PandocMonad m                 => Text -> BlockAttributes -> Text -> OrgParser m (F Blocks) admonitionBlock blockType blockAttrs rawtext = do-  bls <- parseBlockLines id rawtext+  bls <- ignHeaders *> parseBlockLines id rawtext   let id' = fromMaybe mempty $ blockAttrName blockAttrs   pure $ fmap     (B.divWith (id', [blockType], []) .@@ -225,14 +231,14 @@   newline   content <- rawBlockContent "example"   let id' = fromMaybe mempty $ blockAttrName blockAttrs-  let codeBlck = B.codeBlockWith (id', "example":classes, kv) content+  let codeBlck = B.codeBlockWith (id', classes, kv) content   return . return $ codeBlck  rawBlockLines :: Monad m => (Text   -> F Blocks) -> Text -> OrgParser m (F Blocks) rawBlockLines f blockType = ignHeaders *> (f <$> rawBlockContent blockType)  parseBlockLines :: PandocMonad m => (F Blocks -> F Blocks) -> Text -> OrgParser m (F Blocks)-parseBlockLines f blockType = ignHeaders *> (f <$> parsedBlockContent)+parseBlockLines f blockType = (f <$> parsedBlockContent)  where    parsedBlockContent :: PandocMonad m => OrgParser m (F Blocks)    parsedBlockContent = try $ do@@ -241,41 +247,37 @@  -- | Read the raw string content of a block rawBlockContent :: Monad m => Text -> OrgParser m Text-rawBlockContent blockType = try $ do-  blkLines <- manyTill rawLine blockEnder-  tabLen <- getOption readerTabStop+rawBlockContent blockType = rawBlockContent' $+   stringAnyCase ("#+end_" <> blockType)++-- | Read the raw string content of a block+rawBlockContent' :: Monad m => OrgParser m Text -> OrgParser m Text+rawBlockContent' blockEnder = try $ do+  blkLines <- manyTill rawLine (try $ skipSpaces <* blockEnder)+  tabStop <- getOption readerTabStop   trimP <- orgStateTrimLeadBlkIndent <$> getState-  let stripIndent strs = if trimP then map (T.drop (shortestIndent strs)) strs else strs-  (T.unlines-   . stripIndent-   . map (tabsToSpaces tabLen . commaEscaped)-   $ blkLines)+  -- split lines into indentation/contents tuples+  let splitLines = map (T.span (\c -> c == ' ' || c == '\t')) blkLines+  let countSpaces = T.foldr (\case {'\t' -> (tabStop +); _ -> (1 +)}) 0+  let shortestIndent = foldr (min . countSpaces . fst) maxBound+                     . filter (not . T.null . snd) -- ignore empty lines+                     $ splitLines+  let tabsToSpaces = T.replace "\t" (T.replicate tabStop " ")+  let reIndent = if trimP+                 then (T.drop shortestIndent . tabsToSpaces)+                 else id++  T.unlines (map (uncurry T.append . bimap reIndent commaEscaped) splitLines)    <$ updateState (\s -> s { orgStateTrimLeadBlkIndent = True })  where    rawLine :: Monad m => OrgParser m Text    rawLine = try $ ("" <$ blankline) <|> anyLine -   blockEnder :: Monad m => OrgParser m ()-   blockEnder = try $ skipSpaces <* stringAnyCase ("#+end_" <> blockType)--   shortestIndent :: [Text] -> Int-   shortestIndent = foldr (min . T.length . T.takeWhile isSpace) maxBound-                    . filter (not . T.null)--   tabsToSpaces :: Int -> Text -> Text-   tabsToSpaces tabStop t =-     let (ind, suff) = T.span (\c -> c == ' ' || c == '\t') t-         tabNum      = T.length $ T.filter (== '\n') ind-         spaceNum    = T.length ind - tabNum-     in  T.replicate (spaceNum + tabStop * tabNum) " " <> suff--   commaEscaped t =-     let (ind, suff) = T.span (\c -> c == ' ' || c == '\t') t-     in  case T.uncons suff of-           Just (',', cs)-             | "*"  <- T.take 1 cs -> ind <> cs-             | "#+" <- T.take 2 cs -> ind <> cs-           _                       -> t+   commaEscaped suff = case T.uncons suff of+     Just (',', cs)+       | "*"  <- T.take 1 cs -> cs+       | "#+" <- T.take 2 cs -> cs+     _                       -> suff  -- | Read but ignore all remaining block headers. ignHeaders :: Monad m => OrgParser m ()@@ -311,6 +313,7 @@ -- metadata under a key of the same name. metadataBlock :: PandocMonad m => Text -> OrgParser m (F Blocks) metadataBlock blockType = try $ do+  ignHeaders   content <- parseBlockLines id blockType   meta'   <- orgStateMeta <$> getState   updateState $ \st ->@@ -431,10 +434,11 @@   return (argKey, paramValue)  orgParamValue :: Monad m => OrgParser m Text-orgParamValue = try $ fmap T.pack $+orgParamValue = try $   skipSpaces     *> notFollowedBy orgArgKey-    *> noneOf "\n\r" `many1Till` endOfValue+    *> ((char '"' *> manyChar (noneOf "\n\r\"") <* char '"') <|>+        noneOf "\n\r" `many1TillChar` endOfValue)     <* skipSpaces  where   endOfValue = lookAhead $  try (skipSpaces <* oneOf "\n\r")@@ -442,6 +446,34 @@   --+-- Dynamic block (#+begin: ...  #+end:)+--++-- | Parses a Dynamic Block, i.e., a block delimited by #+BEGIN: and+-- #+END:.+dynamicBlock :: PandocMonad m => OrgParser m (F Blocks)+dynamicBlock = try $ do+  metaLineStart *> stringAnyCase "begin:" *> spaces+  blockname <- optionMaybe orgArgWord+  blockArgs <- blockParameters+  contents <- do+    raw <- rawBlockContent' $ metaLineStart *> stringAnyCase "end:"+    parseFromString blocks (raw <> "\n")+  let attr = ("", maybe [] (:[]) blockname, blockArgs)+  return $ B.divWith attr <$> contents++-- | Parse block arguments; in order, this tries to parse a Lisp-style+-- argument list, a set of key-value pairs using /equals/, and as a+-- fallback the whole line as a single /parameters/ argument.+blockParameters :: PandocMonad m => OrgParser m [(Text, Text)]+blockParameters = choice+  [ try $ manyTill ((,) <$> orgArgKey <*> orgParamValue) newline+  , try $ manyTill ((,) <$> (spaces *> orgArgWord <* char '=') <*> orgArgWord)+                   newline+  , (\x -> [ ("parameters", x) | not (T.null x)]) <$> (skipSpaces *> anyLine)+  ]++-- -- Drawers -- @@ -526,7 +558,7 @@    exampleLine = try $ exampleLineStart *> anyLine  exampleCode :: Text -> Blocks-exampleCode = B.codeBlockWith ("", ["example"], [])+exampleCode = B.codeBlockWith ("", [], [])   --@@ -801,6 +833,7 @@ latexFragment :: PandocMonad m => OrgParser m (F Blocks) latexFragment = try $ do   envName <- latexEnvStart+  guard $ envName `notElem` inlineEnvironmentNames   texOpt  <- getExportSetting exportWithLatex   let envStart = "\\begin{" <> envName <> "}"   let envEnd = "\\end{" <> envName <> "}"
src/Text/Pandoc/Readers/Org/DocumentTree.hs view
@@ -3,10 +3,10 @@ {-# LANGUAGE TupleSections     #-} {- |    Module      : Text.Pandoc.Readers.Org.DocumentTree-   Copyright   : Copyright (C) 2014-2023 Albert Krewinkel+   Copyright   : Copyright (C) 2014-2024 Albert Krewinkel    License     : GNU GPL, version 2 or above -   Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>  Parsers for org-mode headlines and document subtrees -}
src/Text/Pandoc/Readers/Org/ExportSettings.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Readers.Org.ExportSettings-   Copyright   : © 2016-2023 Albert Krewinkel+   Copyright   : © 2016-2024 Albert Krewinkel    License     : GNU GPL, version 2 or above -   Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>  Parsers for Org-mode export options. -}
src/Text/Pandoc/Readers/Org/Inlines.hs view
@@ -2,10 +2,10 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Readers.Org.Inlines-   Copyright   : Copyright (C) 2014-2023 Albert Krewinkel-   License     : GNU GPL, version 2 or above+   Copyright   : Copyright (C) 2014-2025 Albert Krewinkel+   License     : GPL-2.0-or-later -   Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>  Parsers for Org-mode inline elements. -}@@ -88,17 +88,18 @@          , inlineCodeBlock          , str          , endline+         , subscript   -- takes precedence over underlined text+         , superscript          , emphasizedText          , code          , math          , displayMath          , verbatim-         , subscript-         , superscript          , inlineLaTeX          , exportSnippet          , macro-         , smart+         , smartQuotes+         , specialStrings          , symbol          ] <* (guard =<< newlinesCountWithinLimits)   <?> "inline"@@ -199,10 +200,10 @@                                 citationSuffix d <> B.toList aff' }])  citeItems :: PandocMonad m => OrgParser m (F [Citation])-citeItems = sequence <$> citeItem `sepBy1` (char ';')+citeItems = sequence <$> sepBy1' citeItem (char ';' <* void (many spaceChar))  citeItem :: PandocMonad m => OrgParser m (F Citation)-citeItem = do+citeItem = try $ do   pref <- citePrefix   itemKey <- orgCiteKey   suff <- citeSuffix@@ -246,37 +247,36 @@  citeSuffix :: PandocMonad m => OrgParser m (F Inlines) citeSuffix =-  rawAffix False >>= parseFromString parseSuffix- where-   parseSuffix = do-     hasSpace <- option False-              (True <$ try (spaceChar >> skipSpaces >> lookAhead nonspaceChar))-     ils <- trimInlinesF . mconcat <$> many inline-     return $ if hasSpace-                 then (B.space <>) <$> ils-                 else ils+  rawAffix False >>= parseFromString (mconcat <$> many inline)  citeStyle :: PandocMonad m => OrgParser m (CiteStyle, [CiteVariant])-citeStyle = option (DefStyle, []) $ do-  sty <- option DefStyle $ try $ char '/' *> orgCiteStyle+citeStyle = do+  sty <- option NilStyle $ try $ char '/' *> orgCiteStyle   variants <- option [] $ try $ char '/' *> orgCiteVariants   return (sty, variants)  orgCiteStyle :: PandocMonad m => OrgParser m CiteStyle-orgCiteStyle = choice $ map try-  [ NoAuthorStyle <$ string "noauthor"-  , NoAuthorStyle <$ string "na"-  , LocatorsStyle <$ string "locators"-  , LocatorsStyle <$ char 'l'-  , NociteStyle <$ string "nocite"-  , NociteStyle <$ char 'n'-  , TextStyle <$ string "text"-  , TextStyle <$ char 't'-  ]+orgCiteStyle = try $ do+  s <- many1 letter+  case s of+    "author" -> pure AuthorStyle+    "a" -> pure AuthorStyle+    "noauthor" -> pure NoAuthorStyle+    "na" -> pure NoAuthorStyle+    "nocite" -> pure NociteStyle+    "n" -> pure NociteStyle+    "text" -> pure TextStyle+    "t" -> pure TextStyle+    "note" -> pure NoteStyle+    "ft" -> pure NoteStyle+    "numeric" -> pure NumericStyle+    "nb" -> pure NumericStyle+    "nil" -> pure NilStyle+    _ -> fail $ "Unknown org cite style " <> show s  orgCiteVariants :: PandocMonad m => OrgParser m [CiteVariant] orgCiteVariants =-  (fullnameVariant `sepBy1` (char '-')) <|> (many1 onecharVariant)+  (sepBy1' fullnameVariant (char '-')) <|> (many1 onecharVariant)  where   fullnameVariant = choice $ map try      [ Bare <$ string "bare"@@ -290,11 +290,14 @@      ]  data CiteStyle =-    NoAuthorStyle+    AuthorStyle+  | NoAuthorStyle   | LocatorsStyle   | NociteStyle   | TextStyle-  | DefStyle+  | NoteStyle+  | NumericStyle+  | NilStyle   deriving Show  data CiteVariant =@@ -591,11 +594,25 @@ code      :: PandocMonad m => OrgParser m (F Inlines) code      = return . B.code     <$> verbatimBetween '~' +-- | Returns 'True' if the parser position right after a string, and 'False'+-- otherwise.+isAfterString :: PandocMonad m => OrgParser m Bool+isAfterString = do+  pos <- getPosition+  st  <- getState+  pure $ getLastStrPos st == Just pos++-- | Parses subscript markup. Subscripts must be preceded by a string. subscript   :: PandocMonad m => OrgParser m (F Inlines)-subscript   = fmap B.subscript   <$> try (char '_' *> subOrSuperExpr)+subscript   = do+  guard =<< isAfterString+  fmap B.subscript   <$> try (char '_' *> subOrSuperExpr) +-- | Parses superscript markup. Superscript must be preceded by a string. superscript :: PandocMonad m => OrgParser m (F Inlines)-superscript = fmap B.superscript <$> try (char '^' *> subOrSuperExpr)+superscript = do+  guard =<< isAfterString+  fmap B.superscript <$> try (char '^' *> subOrSuperExpr)  math      :: PandocMonad m => OrgParser m (F Inlines) math      = return . B.math      <$> choice [ math1CharBetween '$'@@ -635,11 +652,11 @@ verbatimBetween :: PandocMonad m                 => Char                 -> OrgParser m Text-verbatimBetween c = try $-  emphasisStart c *>-  many1TillNOrLessNewlines 1 verbatimChar (emphasisEnd c)+verbatimBetween c = newlinesToSpaces <$>+  try (emphasisStart c *> many1TillNOrLessNewlines 1 verbatimChar (emphasisEnd c))  where    verbatimChar = noneOf "\n\r" >>= updatePositions+   newlinesToSpaces = T.map (\d -> if d == '\n' then ' ' else d)  -- | Parses a raw string delimited by @c@ using Org's math rules mathTextBetween :: PandocMonad m@@ -808,16 +825,20 @@   allowEntities <- getExportSetting exportWithEntities   ils <- parseAsInlineLaTeX cmd texOpt   maybe mzero returnF $-     parseAsMathMLSym allowEntities cmd `mplus`-     parseAsMath cmd texOpt `mplus`-     ils+    if "\\begin{" `T.isPrefixOf` cmd+       then ils+       else parseAsMathMLSym allowEntities cmd `mplus`+            parseAsMath cmd texOpt `mplus`+            ils  where    parseAsInlineLaTeX :: PandocMonad m                       => Text -> TeXExport -> OrgParser m (Maybe Inlines)    parseAsInlineLaTeX cs = \case-     TeXExport -> maybeRight <$> runParserT inlineCommand state "" (toSources cs)+     TeXExport -> maybeRight <$> runParserT+                  (B.rawInline "latex" . snd <$> withRaw inlineCommand)+                  state "" (toSources cs)      TeXIgnore -> return (Just mempty)-     TeXVerbatim -> return (Just $ B.str cs)+     TeXVerbatim -> return (Just $ B.text cs)     parseAsMathMLSym :: Bool -> Text -> Maybe Inlines    parseAsMathMLSym allowEntities cs = do@@ -886,29 +907,27 @@   escapedComma = try $ char '\\' *> oneOf ",\\"   eoa = string ")}}}" -smart :: PandocMonad m => OrgParser m (F Inlines)-smart = choice [doubleQuoted, singleQuoted, orgApostrophe, orgDash, orgEllipses]+smartQuotes :: PandocMonad m => OrgParser m (F Inlines)+smartQuotes = do+  guard =<< getExportSetting exportSmartQuotes+  choice [doubleQuoted, singleQuoted, orgApostrophe]   where-    orgDash = do-      guardOrSmartEnabled =<< getExportSetting exportSpecialStrings-      pure <$> dash <* updatePositions '-'-    orgEllipses = do-      guardOrSmartEnabled =<< getExportSetting exportSpecialStrings-      pure <$> ellipses <* updatePositions '.'     orgApostrophe = do-      guardEnabled Ext_smart       (char '\'' <|> char '\8217') <* updateLastPreCharPos                                    <* updateLastForbiddenCharPos       returnF (B.str "\x2019") -guardOrSmartEnabled :: PandocMonad m => Bool -> OrgParser m ()-guardOrSmartEnabled b = do-  smartExtension <- extensionEnabled Ext_smart <$> getOption readerExtensions-  guard (b || smartExtension)+specialStrings :: PandocMonad m => OrgParser m (F Inlines)+specialStrings = do+  guard =<< getExportSetting exportSpecialStrings+  choice [orgDash, orgEllipses, shyHyphen]+  where+    shyHyphen   = pure <$> (B.str "\173" <$ string "\\-") <* updatePositions '-'+    orgDash     = pure <$> dash <* updatePositions '-'+    orgEllipses = pure <$> ellipses <* updatePositions '.'  singleQuoted :: PandocMonad m => OrgParser m (F Inlines) singleQuoted = try $ do-  guardOrSmartEnabled =<< getExportSetting exportSmartQuotes   singleQuoteStart   updatePositions '\''   withQuoteContext InSingleQuote $@@ -920,7 +939,6 @@ -- in the same paragraph. doubleQuoted :: PandocMonad m => OrgParser m (F Inlines) doubleQuoted = try $ do-  guardOrSmartEnabled =<< getExportSetting exportSmartQuotes   doubleQuoteStart   updatePositions '"'   contents <- mconcat <$> many (try $ notFollowedBy doubleQuoteEnd >> inline)
src/Text/Pandoc/Readers/Org/Meta.hs view
@@ -3,10 +3,10 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Readers.Org.Meta-   Copyright   : Copyright (C) 2014-2023 Albert Krewinkel+   Copyright   : Copyright (C) 2014-2024 Albert Krewinkel    License     : GNU GPL, version 2 or above -   Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>  Parsers for Org-mode meta declarations. -}@@ -252,7 +252,11 @@   where    todoKeyword :: Monad m => OrgParser m Text-   todoKeyword = many1Char nonspaceChar <* skipSpaces+   todoKeyword = do+     keyword <- many1Char nonspaceChar+     let cleanKeyword = T.takeWhile (/= '(') keyword+     skipSpaces+     return cleanKeyword     todoKeywords :: Monad m => OrgParser m [Text]    todoKeywords = try $
src/Text/Pandoc/Readers/Org/ParserState.hs view
@@ -3,10 +3,10 @@ {-# LANGUAGE OverloadedStrings     #-} {- |    Module      : Text.Pandoc.Readers.Org.ParserState-   Copyright   : Copyright (C) 2014-2023 Albert Krewinkel+   Copyright   : Copyright (C) 2014-2025 Albert Krewinkel    License     : GNU GPL, version 2 or above -   Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>  Define the Org-mode parser state. -}@@ -49,7 +49,7 @@ import Text.Pandoc.Builder (Blocks) import Text.Pandoc.Definition (Meta (..), nullMeta) import Text.Pandoc.Logging-import Text.Pandoc.Options (ReaderOptions (..))+import Text.Pandoc.Options (ReaderOptions (..), Extension(..), isEnabled) import Text.Pandoc.Parsing (Future, HasIdentifierList (..),                             HasIncludeFiles (..), HasLastStrPosition (..),                             HasLogMessages (..), HasMacros (..),@@ -193,7 +193,15 @@  optionsToParserState :: ReaderOptions -> OrgParserState optionsToParserState opts =-  def { orgStateOptions = opts }+  let exportSettings = defaultExportSettings+        { exportSmartQuotes = isEnabled Ext_smart opts ||+                              isEnabled Ext_smart_quotes opts+        , exportSpecialStrings = isEnabled Ext_smart opts ||+                                 isEnabled Ext_special_strings opts+        }+  in def { orgStateOptions = opts+         , orgStateExportSettings = exportSettings+         }  registerTodoSequence :: TodoSequence -> OrgParserState -> OrgParserState registerTodoSequence todoSeq st =
src/Text/Pandoc/Readers/Org/Parsing.hs view
@@ -1,9 +1,9 @@ {- |    Module      : Text.Pandoc.Readers.Org.Parsing-   Copyright   : Copyright (C) 2014-2023 Albert Krewinkel+   Copyright   : Copyright (C) 2014-2025 Albert Krewinkel    License     : GNU GPL, version 2 or above -   Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>  Org-mode parsing utilities. @@ -40,6 +40,7 @@   , many1Till   , many1TillChar   , notFollowedBy'+  , sepBy1'   , spaceChar   , nonspaceChar   , skipSpaces@@ -53,6 +54,7 @@   , guardEnabled   , updateLastStrPos   , notAfterString+  , getLastStrPos   , ParserState (..)   , registerHeader   , QuoteContext (..)
src/Text/Pandoc/Readers/Org/Shared.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Readers.Org.Shared-   Copyright   : Copyright (C) 2014-2023 Albert Krewinkel+   Copyright   : Copyright (C) 2014-2024 Albert Krewinkel    License     : GNU GPL, version 2 or above -   Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>  Utility functions used in other Pandoc Org modules. -}@@ -32,7 +32,7 @@                        `elem` imageExtensions    isKnownProtocolUri = any (\x -> (x <> "://") `T.isPrefixOf` fp) protocols -   imageExtensions = [ ".jpeg", ".jpg", ".png", ".gif", ".svg", ".webp", ".jxl" ]+   imageExtensions = [ ".jpeg", ".jpg", ".png", ".gif", ".svg", ".webp", ".jxl", ".avif" ]    protocols = [ "file", "http", "https" ]  -- | Cleanup and canonicalize a string describing a link.  Return @Nothing@ if
+ src/Text/Pandoc/Readers/Pod.hs view
@@ -0,0 +1,446 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE TypeApplications #-}+{- |+   Module      : Text.Pandoc.Readers.Pod+   Copyright   : © 2024 Evan Silberman+   License     : GNU GPL, version 2 or above++   Maintainer  : Evan Silberman <evan@jklol.net>+   Stability   : WIP+   Portability : portable++Conversion of Pod to 'Pandoc' documents+-}+module Text.Pandoc.Readers.Pod (readPod) where++import Control.Monad (void)+import Control.Monad.Except (throwError)+import Data.Char (isAsciiUpper, digitToInt)+import Data.Default (Default)+import Text.Pandoc.Logging+import Text.Pandoc.Options+import Text.Pandoc.Parsing+import Text.Pandoc.Parsing.General (isSpaceChar)+import Text.Pandoc.XML (lookupEntity)+import Text.Pandoc.Class.PandocMonad (PandocMonad(..))+import Text.Pandoc.Definition (Pandoc)+import Text.Pandoc.Error+import Text.Pandoc.Builder (Blocks, Inlines)+import qualified Text.Pandoc.Builder as B+import qualified Data.Text as T+import qualified Data.Text.Read as TR+import Text.Pandoc.Shared (stringify, textToIdentifier, tshow)+import Data.Set (Set)+import Data.Functor (($>))+import Data.Maybe (listToMaybe, fromMaybe)+import Numeric (readOct)++data PodState = PodState+  { logMessages :: [LogMessage]+  , headerIds :: Set T.Text+  , options :: ReaderOptions+} deriving (Show)++instance HasLogMessages PodState where+  addLogMessage msg st = st{ logMessages = msg : logMessages st }+  getLogMessages st = reverse $ logMessages st++instance HasIdentifierList PodState where+  extractIdentifierList = headerIds+  updateIdentifierList f st = st{headerIds = f (headerIds st)}++instance HasReaderOptions PodState where+  extractReaderOptions = options++instance Default PodState where+  def = PodState+    { logMessages = []+    , headerIds = mempty+    , options = def+    }++data PodLinkDestination = LinkUrl Inlines T.Text+                        | LinkMan Inlines (Maybe Inlines)+                        | LinkInternal Inlines+                        deriving (Show)++defaultLinkName :: PodLinkDestination -> Inlines+defaultLinkName (LinkUrl inl _) = inl+defaultLinkName (LinkMan nm (Just sec)) = B.doubleQuoted sec <> " in " <> nm+defaultLinkName (LinkMan nm Nothing) = nm+defaultLinkName (LinkInternal sec) = B.doubleQuoted sec++type PodParser m = ParsecT Sources PodState m++readPod :: (PandocMonad m, ToSources a)+        => ReaderOptions+        -> a+        -> m Pandoc+readPod _ s = do+  let sources = toSources s+  p <- readWithM parsePod def sources+  case p of+    Right result -> return result+    Left e       -> throwError e++parsePod :: PandocMonad m => PodParser m Pandoc+parsePod = do+  -- We don't actually start processing Pod until we encounter a Pod command.+  -- If we never encounter a Pod command, the document is still valid Pod, it+  -- just contains no content.+  notPod+  bs <- manyTill block eof+  reportLogMessages+  return $ B.doc $ mconcat bs++block :: PandocMonad m => PodParser m Blocks+block = verbatim  <|> paragraph <|> command <?> "Pod paragraph"++command :: PandocMonad m => PodParser m Blocks+command = do+    try (char '=' >> notFollowedBy (string "item" <|> string "back" <|> string "end"))+    header <|> pod <|> cut <|> over <|> for <|> begin <|> encoding <?> "Pod command"++cmd :: PandocMonad m => T.Text -> PodParser m ()+cmd nm = do+  textStr nm+  notFollowedBy nonspaceChar+  void $ many spaceChar++encoding :: PandocMonad m => PodParser m Blocks+encoding = do+  cmd "encoding"+  anyLine+  optional blanklines+  logMessage $ IgnoredElement "=encoding; Pandoc requires UTF-8 input"+  return mempty++header :: PandocMonad m => PodParser m Blocks+header = do+  string "head"+  dig <- oneOf "123456"+  void blankline <|> skipMany1 spaceChar+  ins <- inlines+  attrs <- registerHeader B.nullAttr ins+  optional blanklines+  return $ B.headerWith attrs (digitToInt dig) ins++pod :: PandocMonad m => PodParser m Blocks+pod = do+  cmd "pod"+  optional (try inlines)+  optional blanklines+  return mempty++cut :: PandocMonad m => PodParser m Blocks+cut = cmd "cut" *> notPod++notPod :: PandocMonad m => PodParser m Blocks+notPod = do+  manyTill anyLine (eof <|> void (try (lookAhead (char '=' *> letter))))+  return mempty++over :: PandocMonad m => PodParser m Blocks+over = do+  cmd "over"+  anyLine+  blanklines+  optional $ try (char '=' *> cut)+  bs <- list <|> blockquote+  string "=back" <* blanklines+  return bs++list :: PandocMonad m => PodParser m Blocks+list = try bulletList <|> try orderedList <|> definitionList++bulletList :: PandocMonad m => PodParser m Blocks+bulletList = B.bulletList <$> many1 (item (many spaceChar *> optional (char '*')))++orderedList :: PandocMonad m => PodParser m Blocks+orderedList = do+  start <- item1+  more <- many orderedItem+  return $ B.orderedList (start : more)+  where+    item1 = item $ spaces *> char '1' *> optional (char '.')+    orderedItem = item $ spaces *> many digit *> optional (char '.')++item :: PandocMonad m => PodParser m () -> PodParser m Blocks+item p = do+  try (cmd "=item")+  p+  blanklines+  mconcat <$> many block <?> "runaway item"++definitionList :: PandocMonad m => PodParser m Blocks+definitionList = B.definitionList <$> many1 dlItem+  where+    dlItem = do+      try (cmd "=item")+      spaces+      term <- inlines+      blanklines+      -- perlpodspec sez the /section part of a link can refer to either+      -- a header or a dl item, hence treating it as a "header" here+      attrs <- registerHeader B.nullAttr term+      defn <- mconcat <$> many block <?> "runaway dlitem"+      return (B.spanWith attrs term, [defn])++blockquote :: PandocMonad m => PodParser m Blocks+blockquote = B.blockQuote . mconcat <$> many block <?> "runaway blockquote"++paragraph :: PandocMonad m => PodParser m Blocks+paragraph = do+  try (notFollowedBy (char '=' *> letter))+  inl <- inlines+  optional blanklines+  return $ B.para $ B.trimInlines inl++inlines :: PandocMonad m => PodParser m Inlines+inlines = mconcat <$> many1 (format <|> whitespace <|> str)++-- perlpodspec sez:+--   If a Pod processor sees any formatting code other than the ones listed,+--   that processor must by default treat this as an error.+format :: PandocMonad m => PodParser m Inlines+format = try $ do+  ctrl <- satisfy isAsciiUpper+  p <- getPosition+  lookAhead (char '<')+  case ctrl of+    'B' -> B.strong <$> argument+    'C' -> B.code . stringify <$> argument+    'F' -> B.spanWith (mempty, ["filename"], mempty) <$> argument+    'I' -> B.emph <$> argument+    'S' -> argument  -- TODO map nbsps+    'X' -> argument $> mempty+    'Z' -> argument $> mempty++    'E' -> do+      a <- stringify <$> argument+      case entity a of+             -- per spec:+             --   Pod parsers, when faced with some unknown "E<identifier>" code,+             --   shouldn't simply replace it with nullstring (by default, at+             --   least), but may pass it through as a string consisting of the+             --   literal characters E, less-than, identifier, greater-than.+             Nothing -> do+               logMessage $ SkippedContent ("unknown entity " <> a) p+               return $ B.str $ "E<" <> a <> ">"+             Just e -> return $ B.str e++    'L' -> link++    x -> throwError $ PandocParseError $ T.snoc "unknown Pod formatting code " x+  where+    argument = try expandedArg <|> compactArg <?> "argument"+    innerStr =  B.str <$> many1Char (podCharLess ">")+    compactArg = do+      char '<'+      mconcat <$> manyTill (format <|> whitespace <|> innerStr) (char '>')+    expandedArg = do+      openLen <- length <$> many1 (char '<')+      let close = T.pack $ replicate openLen '>'+      skipMany1 spaceChar <|> void blankline+      arg <- mconcat <$> many (format <|> try (whitespace <* notFollowedBy (textStr close)) <|> str)+      many1 spaceChar+      textStr close+      return arg+    -- Some legacy entity names are required to be parsed by Pod formatters+    oct = listToMaybe . readOct @Integer+    entity "apos" = Just "'"+    entity "sol" = Just "/"+    entity "verbar" = Just "|"+    entity "lchevron" = Just "«"+    entity "rchevron" = Just "»"+    entity (T.stripPrefix "0x" -> Just suf) = lookupEntity $ "#x" <> suf+    entity (T.stripPrefix "0" -> Just suf)+        | Just (n, "") <- oct (T.unpack suf) = lookupEntity $ "#" <> tshow n+    entity (TR.decimal @Integer -> Right (x, "")) = lookupEntity $ "#" <> tshow x+    -- named entities in Commonmark.Entity de facto have to be looked up with+    -- the semicolon at the end. perlpodspec says arguments to E<> must be+    -- alphanumeric, so an argument that already has a trailing semicolon+    -- is bogus anyway, so just paste the semicolon on unconditionally.+    entity x = lookupEntity (x <> ";")++-- god knows there must be a higher order way of writing this thing, where we+-- have multiple different possible parser states within the link argument+-- varying depending on whether the link is expanded or not, but at least I+-- understand what I've done. This would be less wacky with a lexing step.+link :: PandocMonad m => PodParser m Inlines+link = do+  identifier <- textToIdentifier <$> getOption readerExtensions+  (name, dest) <- try expandedLinkArg <|> compactLinkArg+  return $ mkLink identifier name dest+  where+    compactLinkArg = do+      char '<'+      name <- linkName whitespace ">"+      dest <- linkDest whitespace (char '>') ">"+      char '>'+      return (mconcat <$> name, dest)+    expandedLinkArg = do+      openLen <- length <$> many1 (char '<')+      let closeStr = textStr (T.pack $ replicate openLen '>')+      let close = skipMany1 spaceChar *> closeStr+      let sp = try $ many1 spaceChar *> notFollowedBy closeStr $> B.space+      many1 spaceChar+      name <- linkName sp ""+      dest <- linkDest sp close ""+      close+      return (mconcat <$> name, dest)+    mkLink identifier name dest =+      let name' = fromMaybe (defaultLinkName dest) name in+          case dest of+            LinkUrl _ href -> B.link href "" name'+            LinkMan nm Nothing ->  B.linkWith (mempty, mempty, [("manual", stringify nm)]) "" "" name'+            LinkMan nm (Just sc) -> B.linkWith (mempty, mempty, [("manual", stringify nm), ("section", stringify sc)]) "" "" name'+            LinkInternal sc -> B.link ("#" <> identifier (stringify sc)) "" name'++    linkName sp ex = optionMaybe $ try $ many+        (try format+         <|> sp+         <|> B.str <$> many1Char (podCharLess ('|':ex))) <* char '|'+    linkDest sp close ex = try (url ex) <|> internal sp close ex <|> man sp close ex+    -- perlpodspec sez:+    --    Note that you can distinguish URL-links from anything else by the+    --    fact that they match m/\A\w+:[^:\s]\S*\z/.+    -- This is obviously not an RFC-compliant matcher for a URI scheme, but+    -- this is what the specification and the canonical implementation (Pod::Simple)+    -- do for deciding that a link target "looks like" a URL, as opposed to a+    -- manual page reference, so what we are doing here is roughly equivalent+    -- even though it is nonsense+    url ex = do+      scheme <- many1Char (letter <|> digit <|> char '_')+      colon <- T.singleton <$> char ':' <* notFollowedBy (char ':')+      rst <- many (format <|> B.str <$> many1Char (podCharLess ex))+      return $ LinkUrl+                 (B.str scheme <> B.str colon <> mconcat rst)+                 (scheme <> colon <> stringify rst)+    quotedSection sp close ex = do+      let mystr = B.str <$> many1Char (podCharLess ('\"':ex) <|> try (char '"' <* notFollowedBy close))+      char '"'+      ins <- mconcat <$> many1 (format <|> sp <|> mystr)+      char '"'+      return ins+    section sp close ex = try (quotedSection sp close ex) <|> mconcat <$> many1 (format <|> sp <|> B.str <$> many1Char (podCharLess ex))+    internal sp close ex = do+      char '/'+      LinkInternal <$> section sp close ex+    notSlash sp ex = format <|> sp <|> B.str <$> many1Char (podCharLess ('/':ex))+    man sp close ex = do+      page <- mconcat <$> many (notSlash sp ex)+      sec <- optionMaybe $ char '/' *> section sp close ex+      return $ LinkMan page sec++whitespace :: PandocMonad m => PodParser m Inlines+whitespace = try $ do+  many1 spaceChar *> optional newline <|> many spaceChar *> void newline+  notFollowedBy blankline+  return B.space++podCharLess :: PandocMonad m => String -> PodParser m Char+podCharLess exclude = try (satisfy isAsciiUpper <* notFollowedBy (char '<'))+                <|> satisfy (\c -> not (isSpaceChar c || isAsciiUpper c || elem c exclude))++podChar :: PandocMonad m => PodParser m Char+podChar = try (satisfy isAsciiUpper <* notFollowedBy (char '<'))+                <|> satisfy (\c -> not (isSpaceChar c || isAsciiUpper c))++str :: PandocMonad m => PodParser m Inlines+str = B.str <$> many1Char podChar++nonEmptyLine :: PandocMonad m => PodParser m T.Text+nonEmptyLine = try $ do+  pre <- manyChar spaceChar+  something <- T.singleton <$> nonspaceChar+  post <- anyLineNewline+  return $ pre <> something <> post++verbatim :: PandocMonad m => PodParser m Blocks+verbatim = do+  start <- startVerbatimLine+  lns <- many (nonEmptyLine <|>+                     try (do b <- blanklines+                             l <- startVerbatimLine+                             return $ b <> l))+  optional blanklines+  return $ B.codeBlock $ mconcat $ start:lns+  where+    startVerbatimLine = many1Char spaceChar <> nonEmptyLine++-- =begin/=end/=for and data paragraphs+-- The =begin/=end (and single-paragraph =for variant) markers in Pod are+-- designed as an extension point for specific formatters+--+-- this doesn't strictly match the intent of "=begin :ident" pod blocks, which+-- are still meant to be processed specially by the formatter, and only land in+-- the output upon request, i.e. pod2html will process "=begin :html" blocks as+-- Pod and include them in the regular output. Since the regions contain Pod+-- markup it seems to me that the best thing to do is parse the markup and put+-- a classname on it, allowing users to respond as desired with filters.+-- Pandoc doesn't have a built-in concept of parsed Divs that are only rendered+-- to certain formats, just raw blocks.+--+-- perlpodspec allows nesting of =begin/=end regions but we currently don't+-- because it would be annoying and we have something somewhat useful we+-- can do with these blocks which is treat them as RawBlocks, which matches+-- the intent reasonably well, and that gets weirder if we parse a nested+-- structure. It seems unlikely this would be encountered in the wild.++regionIdentifier :: PandocMonad m => PodParser m T.Text+regionIdentifier = many1Char (alphaNum <|> oneOf "-_")++for :: PandocMonad m => PodParser m Blocks+for = do+  string "for"+  many1 spaceChar+  forDiv <|> forData++forDiv :: PandocMonad m => PodParser m Blocks+forDiv = do+  char ':'+  cls <- regionIdentifier+  many1 spaceChar+  B.divWith (mempty, [cls], mempty) <$> paragraph++forData :: PandocMonad m => PodParser m Blocks+forData = do+  fmt <- regionIdentifier+  ln1 <- anyLineNewline+  lns <- many nonEmptyLine+  optional blanklines+  return $ B.rawBlock fmt (T.concat (ln1 : lns))++begin :: PandocMonad m => PodParser m Blocks+begin = do+  cmd "begin"+  beginDiv <|> beginData++beginDiv :: PandocMonad m => PodParser m Blocks+beginDiv = do+  char ':'+  cls <- regionIdentifier+  anyLine  -- "parameters" may appear in this position+  blanklines+  bs <- mconcat <$> many block+  textStr ("=end :" <> cls) <* blanklines+  return $ B.divWith (mempty, [cls], mempty) bs++beginData :: PandocMonad m => PodParser m Blocks+beginData = do+  fmt <- regionIdentifier+  anyLine+  blanklines+  lns <- mconcat <$> many (try rawCut <|> rawLine)+  textStr ("=end " <> fmt) <* blanklines+  return $ B.rawBlock fmt lns+  where+    rawCut = do+      char '=' *> cut+      pod <?> "=pod to close =cut within =begin/=end"+      return mempty+    rawLine = do+      try (notFollowedBy (char '=' *> letter))+      anyLineNewline
+ src/Text/Pandoc/Readers/Pptx.hs view
@@ -0,0 +1,43 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+   Module      : Text.Pandoc.Readers.Pptx+   Copyright   : © 2025 Anton Antic+   License     : GNU GPL, version 2 or above++   Maintainer  : Anton Antic <anton@everworker.ai>+   Stability   : alpha+   Portability : portable++Conversion of PPTX (PowerPoint) documents to 'Pandoc' document.+-}+module Text.Pandoc.Readers.Pptx (readPptx) where++import qualified Data.ByteString.Lazy as B+import qualified Data.Text as T+import Codec.Archive.Zip (toArchiveOrFail)+import Control.Monad.Except (throwError)+import Text.Pandoc.Class.PandocMonad (PandocMonad)+import Text.Pandoc.Definition (Pandoc(..))+import Text.Pandoc.Error (PandocError(..))+import Text.Pandoc.Options (ReaderOptions)+import Text.Pandoc.Readers.Pptx.Parse (archiveToPptx)+import Text.Pandoc.Readers.Pptx.Slides (pptxToOutput)++-- | Read PPTX file into Pandoc AST+readPptx :: PandocMonad m => ReaderOptions -> B.ByteString -> m Pandoc+readPptx opts bytes =+  case toArchiveOrFail bytes of+    Right archive ->+      case archiveToPptx archive of+        Right pptx -> do+          -- Convert Pptx intermediate to Pandoc AST+          (meta, blocks) <- pptxToOutput opts pptx+          return $ Pandoc meta blocks++        Left err ->+          throwError $ PandocParseError $+            "Failed to parse PPTX: " <> err++    Left err ->+      throwError $ PandocParseError $+        "Failed to unpack PPTX archive: " <> T.pack err
+ src/Text/Pandoc/Readers/Pptx/Parse.hs view
@@ -0,0 +1,216 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+   Module      : Text.Pandoc.Readers.Pptx.Parse+   Copyright   : © 2025 Anton Antic+   License     : GNU GPL, version 2 or above++   Maintainer  : Anton Antic <anton@everworker.ai>+   Stability   : alpha+   Portability : portable++Parsing of PPTX archive to intermediate representation.+-}+module Text.Pandoc.Readers.Pptx.Parse+  ( Pptx(..)+  , PresentationDoc(..)+  , PptxSlide(..)+  , SlideId(..)+  , archiveToPptx+  ) where++import Codec.Archive.Zip (Archive, Entry, findEntryByPath, fromEntry)+import qualified Data.ByteString.Lazy as B+import Data.List (find)+import Data.Maybe (mapMaybe)+import qualified Data.Text as T+import qualified Data.Text.Lazy.Encoding as TL+import Data.Text (Text)+import System.FilePath (splitFileName)+import Text.Pandoc.Readers.OOXML.Shared+import Text.Pandoc.XML.Light+import Text.Read (readMaybe)++-- | Slide identifier+newtype SlideId = SlideId Int deriving (Show, Eq, Ord)++-- | Complete PPTX document (intermediate representation)+data Pptx = Pptx+  { pptxPresentation :: PresentationDoc+  , pptxSlides       :: [PptxSlide]+  , pptxArchive      :: Archive+  } deriving (Show)++-- | Individual slide data+data PptxSlide = PptxSlide+  { slideId      :: SlideId+  , slidePath    :: FilePath+  , slideElement :: Element     -- The parsed p:sld element+  , slideRels    :: [(Text, Text)]  -- Slide relationships+  } deriving (Show)++-- | Presentation-level information from presentation.xml+data PresentationDoc = PresentationDoc+  { presNameSpaces   :: NameSpaces+  , presSlideSize    :: (Integer, Integer)  -- (width, height) in pixels+  , presSlideIds     :: [(SlideId, Text)]   -- (slideId, relationshipId)+  } deriving (Show)++-- | Parse PPTX archive to intermediate representation+archiveToPptx :: Archive -> Either Text Pptx+archiveToPptx archive = do+  -- Find and parse presentation.xml+  presPath <- getPresentationXmlPath archive+  presElem <- loadXMLFromArchive archive presPath+  presDoc <- elemToPresentation presElem++  -- Load presentation relationships to resolve slide paths+  presRelsPath <- getPresentationRelsPath archive presPath+  presRels <- loadRelationships archive presRelsPath++  -- Parse each slide+  slides <- mapM (parseSlide archive presRels) (presSlideIds presDoc)++  return $ Pptx presDoc slides archive++-- | Find presentation.xml via root relationships+getPresentationXmlPath :: Archive -> Either Text FilePath+getPresentationXmlPath archive = do+  -- Load _rels/.rels+  relsEntry <- maybeToEither "Missing _rels/.rels" $+               findEntryByPath "_rels/.rels" archive++  relsElem <- parseXMLFromEntry relsEntry++  -- The Relationships element has a default namespace, but Relationship children don't use prefix+  -- We need to look at all children regardless of namespace+  let relElems = onlyElems $ elContent relsElem++  -- Look for relationship containing "officeDocument" in Type attribute+  case find isOfficeDocRel relElems of+    Nothing -> Left $ "No presentation.xml relationship found. Found " <>+                     T.pack (show (length relElems)) <> " relationships."+    Just rel -> do+      target <- maybeToEither "Missing Target attribute" $+                findAttr (unqual "Target") rel+      return $ T.unpack target  -- Convert Text to FilePath++  where+    isOfficeDocRel el =+      case findAttr (unqual "Type") el of+        -- Must end with "/officeDocument" to avoid matching "/extended-properties"+        Just relType -> "/officeDocument" `T.isSuffixOf` relType+        Nothing -> False++-- | Load and parse XML from archive entry+loadXMLFromArchive :: Archive -> FilePath -> Either Text Element+loadXMLFromArchive archive path = do+  entry <- maybeToEither ("Entry not found: " <> T.pack path) $+           findEntryByPath path archive++  let xmlBytes = fromEntry entry+  parseXMLFromBS xmlBytes++-- | Parse XML from ByteString+parseXMLFromBS :: B.ByteString -> Either Text Element+parseXMLFromBS = parseXMLElement . TL.decodeUtf8++-- | Parse XML from Entry+parseXMLFromEntry :: Entry -> Either Text Element+parseXMLFromEntry = parseXMLFromBS . fromEntry++-- | Parse presentation.xml element to PresentationDoc+elemToPresentation :: Element -> Either Text PresentationDoc+elemToPresentation presElem = do+  let ns = elemToNameSpaces presElem++  -- Extract slide size (with defaults)+  let sizeElem = findChildByName ns "p" "sldSz" presElem+      (widthEMU, heightEMU) = case sizeElem of+        Just el ->+          let cx = readAttrInt "cx" el+              cy = readAttrInt "cy" el+           in (cx, cy)+        Nothing -> (9144000, 6858000)  -- Default 10" x 7.5"++  -- Convert EMUs to pixels (approximate for metadata)+  let width = widthEMU `div` emusPerInch+      height = heightEMU `div` emusPerInch++  -- Extract slide ID list (optional - some presentations may have no slides)+  let sldIdLstElem = findChildByName ns "p" "sldIdLst" presElem++  slideRefs <- case sldIdLstElem of+    Nothing -> return []  -- No slides is valid for templates/masters-only presentations+    Just el -> do+      let sldIdElems = findChildren (elemName ns "p" "sldId") el+      mapM (extractSlideRef ns) (zip [1..] sldIdElems)++  return $ PresentationDoc+    { presNameSpaces = ns+    , presSlideSize = (width, height)+    , presSlideIds = slideRefs+    }++-- | Extract slide ID and relationship ID from p:sldId element+extractSlideRef :: NameSpaces -> (Int, Element) -> Either Text (SlideId, Text)+extractSlideRef ns (idx, sldIdElem) = do+  relId <- maybeToEither ("Missing r:id in slide " <> T.pack (show idx)) $+           findAttrByName ns "r" "id" sldIdElem++  return (SlideId idx, relId)++-- | Safe read attribute as Integer (with default of 0)+readAttrInt :: Text -> Element -> Integer+readAttrInt attrName el =+  case findAttr (unqual attrName) el of+    Just str -> case readMaybe (T.unpack str) of+      Just n -> n+      Nothing -> 0+    Nothing -> 0++-- | Get presentation relationships path+getPresentationRelsPath :: Archive -> FilePath -> Either Text FilePath+getPresentationRelsPath _archive presPath =+  -- ppt/presentation.xml → ppt/_rels/presentation.xml.rels+  let (dir, file) = splitFileName presPath+      relsPath = dir ++ "/_rels/" ++ file ++ ".rels"+   in Right relsPath++-- | Load relationships from .rels file+loadRelationships :: Archive -> FilePath -> Either Text [(Text, Text)]+loadRelationships archive relsPath =+  case findEntryByPath relsPath archive of+    Nothing -> Right []  -- No relationships is OK+    Just entry -> do+      relsElem <- parseXMLFromEntry entry+      let relElems = onlyElems $ elContent relsElem+      return $ mapMaybe extractRelationship relElems+  where+    extractRelationship el = do+      relId <- findAttr (unqual "Id") el+      target <- findAttr (unqual "Target") el+      return (relId, target)++-- | Parse a single slide+parseSlide :: Archive -> [(Text, Text)] -> (SlideId, Text) -> Either Text PptxSlide+parseSlide archive rels (sid, relId) = do+  -- Resolve relationship to get slide path+  target <- maybeToEither ("Relationship not found: " <> relId) $+            lookup relId rels++  -- Resolve relative path: ppt/slides/slide1.xml+  let slidePath' = "ppt/" <> T.unpack target++  -- Load and parse slide XML+  slideElem <- loadXMLFromArchive archive slidePath'++  -- Load slide-specific relationships+  slideRelsPath <- getPresentationRelsPath archive slidePath'+  slideRels' <- loadRelationships archive slideRelsPath++  return $ PptxSlide sid slidePath' slideElem slideRels'++-- | Helper: Maybe a -> Either Text a+maybeToEither :: Text -> Maybe a -> Either Text a+maybeToEither err Nothing = Left err+maybeToEither _ (Just x) = Right x
+ src/Text/Pandoc/Readers/Pptx/Shapes.hs view
@@ -0,0 +1,330 @@+{-# LANGUAGE OverloadedStrings #-}+{-# OPTIONS_GHC -Wno-partial-fields #-}+{- |+   Module      : Text.Pandoc.Readers.Pptx.Shapes+   Copyright   : © 2025 Anton Antic+   License     : GNU GPL, version 2 or above++   Maintainer  : Anton Antic <anton@everworker.ai>+   Stability   : alpha+   Portability : portable++Parsing of PPTX shapes (text boxes, images, tables, diagrams).+-}+module Text.Pandoc.Readers.Pptx.Shapes+  ( PptxShape(..)+  , PptxParagraph(..)+  , BulletType(..)+  , parseShapes+  , parseShape+  , shapeToBlocks+  , isTitlePlaceholder+  , extractDrawingMLText+  ) where++import Codec.Archive.Zip (Archive, findEntryByPath, fromEntry)+import qualified Data.ByteString.Lazy as B+import Data.List (find, groupBy)+import Data.Maybe (mapMaybe)+import qualified Data.Text as T+import Data.Text (Text)+import Text.Read (readMaybe)+import Text.Pandoc.Class.PandocMonad (PandocMonad)+import qualified Text.Pandoc.Class.PandocMonad as P+import Text.Pandoc.Definition+import Text.Pandoc.Readers.OOXML.Shared+import Text.Pandoc.Readers.Pptx.SmartArt+import Text.Pandoc.XML.Light++-- | Paragraph with bullet/numbering information+data PptxParagraph = PptxParagraph+  { paraLevel   :: Int            -- Bullet level (0, 1, 2...)+  , paraBullet  :: BulletType+  , paraText    :: Text+  } deriving (Show)++-- | Bullet type+data BulletType+  = NoBullet+  | Bullet                        -- Has bullet (character detected or implicit)+  | WingdingsBullet              -- Detected via Wingdings symbol+  deriving (Show, Eq)++-- | Shape types in PPTX slides+data PptxShape+  = PptxTextBox [PptxParagraph]         -- Parsed paragraphs with bullet info+  | PptxPicture+      { picRelId  :: Text               -- Relationship ID (lazy loading)+      , picTitle  :: Text+      , picAlt    :: Text+      }+  | PptxTable [[Text]]                  -- Simple text cells for now+  | PptxDiagramRef+      { dgmDataRelId   :: Text          -- Relationship to data.xml+      , dgmLayoutRelId :: Text          -- Relationship to layout.xml+      }+  | PptxGraphic Text                    -- Placeholder for other graphics+  deriving (Show)++-- | Parse all shapes from shape tree+parseShapes :: NameSpaces -> Element -> [PptxShape]+parseShapes ns spTreeElem =+  let shapeElems = onlyElems $ elContent spTreeElem+      -- Merge parent namespaces with element namespaces+      ns' = ns <> elemToNameSpaces spTreeElem+   in mapMaybe (parseShape ns') shapeElems++-- | Parse individual shape element+parseShape :: NameSpaces -> Element -> Maybe PptxShape+parseShape ns el+  -- Text box: <p:sp> with <p:txBody>+  | isElem ns "p" "sp" el =+      case findChildByName ns "p" "txBody" el of+        Just txBody ->+          let paras = parseParagraphs ns txBody+           in if null paras+              then Nothing+              else Just $ PptxTextBox paras+        Nothing -> Nothing++  -- Picture: <p:pic>+  | isElem ns "p" "pic" el = do+      nvPicPr <- findChildByName ns "p" "nvPicPr" el+      cNvPr <- findChildByName ns "p" "cNvPr" nvPicPr++      let title = maybe "" id $ findAttr (unqual "name") cNvPr+          alt = maybe "" id $ findAttr (unqual "descr") cNvPr++      -- Get blip relationship ID+      blipFill <- findChildByName ns "p" "blipFill" el+      blip <- findChildByName ns "a" "blip" blipFill+      relId <- findAttrByName ns "r" "embed" blip++      return $ PptxPicture relId title alt++  -- GraphicFrame: table or diagram+  | isElem ns "p" "graphicFrame" el =+      case findChildByName ns "a" "graphic" el >>=+           findChildByName ns "a" "graphicData" of+        Nothing -> Nothing+        Just graphicData ->+          case findAttr (unqual "uri") graphicData of+            Nothing -> Just $ PptxGraphic "no-uri"+            Just uri ->+              if "table" `T.isInfixOf` uri+                then+                  -- Table+                  case findChildByName ns "a" "tbl" graphicData of+                    Just tbl ->+                      let rows = parseTableRows ns tbl+                       in Just $ PptxTable rows+                    Nothing -> Nothing+                else if "diagram" `T.isInfixOf` uri+                  then+                    -- SmartArt diagram - dgm namespace is declared inline on relIds element+                    let dgmRelIds = find (\e -> qName (elName e) == "relIds") (elChildren graphicData)+                     in case dgmRelIds of+                          Nothing -> Just $ PptxGraphic "diagram-no-relIds"+                          Just relIdsElem ->+                            -- Get r:dm and r:lo attributes (r namespace is in parent)+                            let ns' = ns <> elemToNameSpaces relIdsElem+                             in case (findAttrByName ns' "r" "dm" relIdsElem,+                                      findAttrByName ns' "r" "lo" relIdsElem) of+                                  (Just dataRelId, Just layoutRelId) ->+                                    Just $ PptxDiagramRef dataRelId layoutRelId+                                  _ -> Just $ PptxGraphic "diagram-missing-rels"+                  else+                    -- Other graphic (chart, etc.)+                    Just $ PptxGraphic ("other: " <> uri)++  -- Skip other shapes for now+  | otherwise = Nothing++-- | Parse table rows (simple text extraction)+parseTableRows :: NameSpaces -> Element -> [[Text]]+parseTableRows ns tblElem =+  let trElems = findChildrenByName ns "a" "tr" tblElem+   in map (parseTableRow ns) trElems++parseTableRow :: NameSpaces -> Element -> [Text]+parseTableRow ns trElem =+  let tcElems = findChildrenByName ns "a" "tc" trElem+   in map extractCellText tcElems+  where+    extractCellText tcElem =+      -- Get text from txBody/a:p/a:r/a:t+      case findChildByName ns "a" "txBody" tcElem of+        Just txBody -> extractDrawingMLText txBody+        Nothing -> ""++-- | Convert shape to Pandoc blocks+shapeToBlocks :: PandocMonad m => Archive -> [(Text, Text)] -> PptxShape -> m [Block]+shapeToBlocks _archive _rels (PptxTextBox paras) =+  return $ paragraphsToBlocks paras+shapeToBlocks archive rels (PptxPicture relId title alt) = do+  -- Resolve relationship to get media path+  case lookup relId rels of+    Nothing -> return []  -- Image not found+    Just target -> do+      let mediaPath = resolveMediaPath target++      -- Load image bytes and add to MediaBag+      case loadMediaFromArchive archive mediaPath of+        Nothing -> return []+        Just mediaBytes -> do+          P.insertMedia (T.unpack mediaPath) Nothing mediaBytes++          let altText = if T.null alt then [] else [Str alt]+          return [Para [Image nullAttr altText (mediaPath, title)]]++shapeToBlocks _archive _rels (PptxTable rows) =+  -- Simple table representation for now+  case rows of+    [] -> return []+    (headerRow:bodyRows) -> do+      let makeCell text = Cell nullAttr AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str text]]+          headerCells = map makeCell headerRow+          bodyCells = map (map makeCell) bodyRows+          caption = Caption Nothing []+          colSpec = replicate (length headerRow) (AlignDefault, ColWidthDefault)+          headerRow' = Row nullAttr headerCells+          bodyRows' = map (Row nullAttr) bodyCells+          thead = TableHead nullAttr [headerRow']+          tbody = [TableBody nullAttr 0 [] bodyRows']+          tfoot = TableFoot nullAttr []+      return [Table nullAttr caption colSpec thead tbody tfoot]++shapeToBlocks archive rels (PptxDiagramRef dataRelId layoutRelId) = do+  -- Parse SmartArt diagram+  case parseDiagram archive rels dataRelId layoutRelId of+    Left err -> do+      -- Failed to parse diagram, return placeholder+      return [Para [Str $ "[Diagram parse error: " <> err <> "]"]]+    Right diagram ->+      return $ diagramToBlocks diagram+shapeToBlocks _archive _rels (PptxGraphic text) =+  -- Placeholder for other graphics (charts, etc.)+  return [Para [Str $ "[Graphic: " <> text <> "]"]]++-- | Resolve media path (handle relative paths)+resolveMediaPath :: Text -> Text+resolveMediaPath target =+  if "../media/" `T.isPrefixOf` target+    then "ppt/media/" <> T.drop 9 target  -- "../media/" = 9 chars+    else if "media/" `T.isPrefixOf` target+      then "ppt/" <> target+      else target++-- | Load media file from archive+loadMediaFromArchive :: Archive -> Text -> Maybe B.ByteString+loadMediaFromArchive archive path =+  case findEntryByPath (T.unpack path) archive of+    Just entry -> Just $ fromEntry entry+    Nothing -> Nothing++-- | Parse paragraphs from text box+parseParagraphs :: NameSpaces -> Element -> [PptxParagraph]+parseParagraphs ns txBody =+  let pElems = findChildrenByName ns "a" "p" txBody+   in map (parseParagraph ns) pElems++-- | Parse individual paragraph+parseParagraph :: NameSpaces -> Element -> PptxParagraph+parseParagraph ns pElem =+  let level = parseBulletLevel ns pElem+      bullet = detectBulletType ns pElem+      text = extractParagraphText ns pElem+   in PptxParagraph level bullet text++-- | Parse bullet level from paragraph properties+parseBulletLevel :: NameSpaces -> Element -> Int+parseBulletLevel ns pElem =+  case findChildByName ns "a" "pPr" pElem >>=+       findAttr (unqual "lvl") >>=+       (\s -> readMaybe (T.unpack s) :: Maybe Int) of+    Just lvl -> lvl+    Nothing -> 0  -- Default to level 0++-- | Detect bullet type+detectBulletType :: NameSpaces -> Element -> BulletType+detectBulletType ns pElem =+  -- Check for explicit <a:pPr><a:buChar>+  case findChildByName ns "a" "pPr" pElem >>=+       findChildByName ns "a" "buChar" of+    Just _buCharElem -> Bullet+    Nothing ->+      -- Check for Wingdings symbol (common in PowerPoint)+      if hasWingdingsSymbol ns pElem+        then WingdingsBullet+        else NoBullet++-- | Check if paragraph starts with Wingdings symbol+hasWingdingsSymbol :: NameSpaces -> Element -> Bool+hasWingdingsSymbol ns pElem =+  let runs = findChildrenByName ns "a" "r" pElem+      checkRun r = case findChildByName ns "a" "rPr" r >>=+                        findChildByName ns "a" "sym" of+                     Just symElem ->+                       case findAttr (unqual "typeface") symElem of+                         Just typeface -> "Wingdings" `T.isInfixOf` typeface+                         Nothing -> False+                     Nothing -> False+   in any checkRun runs++-- | Extract text from paragraph+extractParagraphText :: NameSpaces -> Element -> Text+extractParagraphText _ns pElem =+  -- Find all <a:t> elements and concatenate+  let textElems = filterElementsName (\qn -> qName qn == "t") pElem+      texts = map strContent textElems+   in T.unwords $ filter (not . T.null) texts++-- | Extract text from DrawingML element (finds all <a:t> descendants)+extractDrawingMLText :: Element -> Text+extractDrawingMLText el =+  let textElems = filterElementsName (\qn -> qName qn == "t") el+      texts = map strContent textElems+   in T.unwords $ filter (not . T.null) texts++-- | Convert paragraphs to blocks, grouping bullets into lists+paragraphsToBlocks :: [PptxParagraph] -> [Block]+paragraphsToBlocks paras =+  -- If we have multiple paragraphs with bullets, group them+  let hasBullets = any (\p -> paraBullet p /= NoBullet) paras+   in if hasBullets+      then groupBulletParagraphs paras+      else map (\p -> Para [Str $ paraText p]) paras++-- | Group bullet paragraphs into lists+groupBulletParagraphs :: [PptxParagraph] -> [Block]+groupBulletParagraphs paras =+  let grouped = groupBy sameBulletLevel paras+   in concatMap groupToBlock grouped+  where+    sameBulletLevel p1 p2 =+      (paraBullet p1 /= NoBullet) &&+      (paraBullet p2 /= NoBullet) &&+      (paraLevel p1 == paraLevel p2)++    groupToBlock :: [PptxParagraph] -> [Block]+    groupToBlock [] = []+    groupToBlock ps@(p:_)+      | paraBullet p /= NoBullet =+          -- Bullet list+          let items = map (\para -> [Plain [Str $ paraText para]]) ps+           in [BulletList items]+      | otherwise =+          -- Plain paragraph+          map (\para -> Para [Str $ paraText para]) ps++-- | Check if shape is title placeholder (also used in Slides module)+isTitlePlaceholder :: NameSpaces -> Element -> Bool+isTitlePlaceholder ns el =+  case findChildByName ns "p" "nvSpPr" el >>=+       findChildByName ns "p" "nvPr" >>=+       findChildByName ns "p" "ph" of+    Just phElem ->+      case findAttr (unqual "type") phElem of+        Just phType -> phType == "title" || phType == "ctrTitle"+        Nothing -> False+    Nothing -> False
+ src/Text/Pandoc/Readers/Pptx/Slides.hs view
@@ -0,0 +1,83 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+   Module      : Text.Pandoc.Readers.Pptx.Slides+   Copyright   : © 2025 Anton Antic+   License     : GNU GPL, version 2 or above++   Maintainer  : Anton Antic <anton@everworker.ai>+   Stability   : alpha+   Portability : portable++Conversion of PPTX slides to Pandoc AST blocks.+-}+module Text.Pandoc.Readers.Pptx.Slides+  ( pptxToOutput+  ) where++import Codec.Archive.Zip (Archive)+import Data.List (find)+import Data.Maybe (mapMaybe)+import qualified Data.Text as T+import Data.Text (Text)+import Text.Pandoc.Class.PandocMonad (PandocMonad)+import Text.Pandoc.Definition+import Text.Pandoc.Options (ReaderOptions)+import Text.Pandoc.Readers.OOXML.Shared+import Text.Pandoc.Readers.Pptx.Parse+import Text.Pandoc.Readers.Pptx.Shapes+import Text.Pandoc.XML.Light++-- | Convert Pptx intermediate representation to Pandoc AST+pptxToOutput :: PandocMonad m => ReaderOptions -> Pptx -> m (Meta, [Block])+pptxToOutput _opts pptx = do+  let slides = pptxSlides pptx+      archive = pptxArchive pptx++  -- Convert each slide to blocks+  slideBlocks <- concat <$> mapM (slideToBlocks archive) slides++  return (mempty, slideBlocks)++-- | Convert slide to blocks+slideToBlocks :: PandocMonad m => Archive -> PptxSlide -> m [Block]+slideToBlocks archive slide = do+  let SlideId n = slideId slide+      slideElem = slideElement slide+      rels = slideRels slide+      ns = elemToNameSpaces slideElem++      -- Extract title from title placeholder+      title = extractSlideTitle ns slideElem++      -- Create header+      slideIdent = "slide-" <> T.pack (show n)+      headerText = if T.null title+                   then "Slide " <> T.pack (show n)+                   else title+      header = Header 2 (slideIdent, [], []) [Str headerText]++  -- Parse shapes and convert to blocks+  case findChildByName ns "p" "cSld" slideElem >>=+       findChildByName ns "p" "spTree" of+    Nothing -> return [header]+    Just spTree -> do+      -- Filter out title placeholder shapes before parsing+      let allShapeElems = onlyElems $ elContent spTree+          nonTitleShapeElems = filter (not . isTitlePlaceholder ns) allShapeElems+          shapes = mapMaybe (parseShape ns) nonTitleShapeElems+      shapeBlocks <- concat <$> mapM (shapeToBlocks archive rels) shapes+      return $ header : shapeBlocks++-- | Extract title from title placeholder+extractSlideTitle :: NameSpaces -> Element -> Text+extractSlideTitle ns slideElem =+  case findChildByName ns "p" "cSld" slideElem >>=+       findChildByName ns "p" "spTree" of+    Nothing -> ""+    Just spTree ->+      -- Find shape with ph type="title"+      let shapes = onlyElems $ elContent spTree+          titleShape = find (isTitlePlaceholder ns) shapes+       in maybe "" extractDrawingMLText titleShape++-- isTitlePlaceholder is imported from Shapes module
+ src/Text/Pandoc/Readers/Pptx/SmartArt.hs view
@@ -0,0 +1,220 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+   Module      : Text.Pandoc.Readers.Pptx.SmartArt+   Copyright   : © 2025 Anton Antic+   License     : GNU GPL, version 2 or above++   Maintainer  : Anton Antic <anton@everworker.ai>+   Stability   : alpha+   Portability : portable++SmartArt diagram parsing and text extraction for PPTX.+-}+module Text.Pandoc.Readers.Pptx.SmartArt+  ( PptxDiagram(..)+  , parseDiagram+  , diagramToBlocks+  ) where++import Codec.Archive.Zip (Archive, findEntryByPath, fromEntry)+import qualified Data.Map.Strict as M+import Data.Maybe (mapMaybe)+import qualified Data.Text as T+import qualified Data.Text.Lazy.Encoding as TL+import Data.Text (Text)+import Text.Pandoc.Definition+import Text.Pandoc.Readers.OOXML.Shared+import Text.Pandoc.XML.Light++-- | SmartArt diagram data+data PptxDiagram = PptxDiagram+  { diagramType :: Text               -- Layout type (chevron, cycle, etc.)+  , diagramNodes :: [(Text, [Text])]  -- (nodeText, childTexts)+  } deriving (Show)++-- | Parse SmartArt diagram from relationship IDs+parseDiagram :: Archive+             -> [(Text, Text)]  -- Slide relationships+             -> Text            -- data relationship ID+             -> Text            -- layout relationship ID+             -> Either Text PptxDiagram+parseDiagram archive rels dataRelId layoutRelId = do+  -- Resolve relationships to file paths+  dataTarget <- maybeToEither ("Relationship not found: " <> dataRelId) $+                lookup dataRelId rels+  layoutTarget <- maybeToEither ("Relationship not found: " <> layoutRelId) $+                  lookup layoutRelId rels++  -- Resolve relative paths (diagrams are in ../diagrams/ from slides/)+  let dataPath = resolveDiagramPath dataTarget+      layoutPath = resolveDiagramPath layoutTarget++  -- Load XML files+  dataElem <- loadXMLFromArchive archive dataPath+  layoutElem <- loadXMLFromArchive archive layoutPath++  -- Extract layout type+  layoutType <- extractLayoutType layoutElem++  -- Extract text nodes with hierarchy+  nodes <- extractDiagramNodes dataElem++  return $ PptxDiagram layoutType nodes++-- | Resolve diagram path (handle ../diagrams/ relative paths)+resolveDiagramPath :: Text -> FilePath+resolveDiagramPath target =+  if "../diagrams/" `T.isPrefixOf` target+    then "ppt/diagrams/" ++ T.unpack (T.drop 12 target)  -- "../diagrams/" = 12 chars+    else T.unpack target++-- | Load XML from archive+loadXMLFromArchive :: Archive -> FilePath -> Either Text Element+loadXMLFromArchive archive path =+  case findEntryByPath path archive of+    Nothing -> Left $ "File not found in archive: " <> T.pack path+    Just entry ->+      let xmlBytes = fromEntry entry+          lazyText = TL.decodeUtf8 xmlBytes+       in parseXMLElement lazyText++-- | Extract layout type from layout XML+extractLayoutType :: Element -> Either Text Text+extractLayoutType layoutElem = do+  -- Look for uniqueId attribute: "urn:.../layout/chevron2"+  case findAttr (unqual "uniqueId") layoutElem of+    Just uid ->+      -- Extract last part after last /+      let layoutName = T.takeWhileEnd (/= '/') uid+       in Right layoutName+    Nothing ->+      -- Fallback: look for title+      case findChildByName ns "dgm" "title" layoutElem >>=+           findAttr (unqual "val") of+        Just title -> Right title+        Nothing -> Right "unknown"+  where+    ns = elemToNameSpaces layoutElem++-- | Extract text nodes from diagram data+extractDiagramNodes :: Element -> Either Text [(Text, [Text])]+extractDiagramNodes dataElem = do+  let ns = elemToNameSpaces dataElem++  -- Find point list+  ptLst <- maybeToEither "Missing dgm:ptLst" $+           findChildByName ns "dgm" "ptLst" dataElem++  let ptElems = findChildrenByName ns "dgm" "pt" ptLst++  -- Build node map: modelId → text+  let nodeMap = M.fromList $ mapMaybe (extractNodeText ns) ptElems++  -- Parse connections+  let cxnLst = findChildByName ns "dgm" "cxnLst" dataElem+      connections = maybe [] (parseConnections ns) cxnLst++  -- Build parent-child map+  let parentMap = buildParentMap connections++  -- Find parent nodes (nodes that have children)+  let parentIds = M.keys parentMap++  -- Build hierarchy - only show nodes that are parents+  -- (children are shown under their parents)+  let hierarchy = map (buildNodeWithChildren nodeMap parentMap) parentIds+      -- Filter out nodes with empty text (presentation nodes)+      validHierarchy = filter (\(nodeText, _) -> not $ T.null nodeText) hierarchy++  return validHierarchy++-- | Extract text from a point element (returns Nothing if no text)+extractNodeText :: NameSpaces -> Element -> Maybe (Text, Text)+extractNodeText ns ptElem = do+  modelId <- findAttr (unqual "modelId") ptElem++  -- Extract text from dgm:t element (which contains a:p/a:r/a:t)+  let text = case findChildByName ns "dgm" "t" ptElem of+        Just tElem ->+          -- Recursively get ALL text content from all descendants+          getAllText tElem+        Nothing -> ""++  -- Only return nodes with actual text+  if T.null (T.strip text)+    then Nothing+    else return (modelId, text)++-- | Connection between nodes+data Connection = Connection+  { connType :: Text+  , connSrc  :: Text+  , connDest :: Text+  } deriving (Show)++-- | Parse connections+parseConnections :: NameSpaces -> Element -> [Connection]+parseConnections ns cxnLst =+  let cxnElems = findChildrenByName ns "dgm" "cxn" cxnLst+   in mapMaybe (parseConnection ns) cxnElems++parseConnection :: NameSpaces -> Element -> Maybe Connection+parseConnection _ns cxnElem = do+  let cxnType = maybe "" id $ findAttr (unqual "type") cxnElem  -- Empty if no type+  srcId <- findAttr (unqual "srcId") cxnElem+  destId <- findAttr (unqual "destId") cxnElem+  return $ Connection cxnType srcId destId++-- | Build parent-child map from connections+-- Use connections WITHOUT a type attribute (these are the data hierarchy)+buildParentMap :: [Connection] -> M.Map Text [Text]+buildParentMap connections =+  let dataConnections = filter (\c -> T.null (connType c)) connections+   in foldr addConn M.empty dataConnections+  where+    addConn conn m = M.insertWith (++) (connSrc conn) [connDest conn] m++-- | Build node with its children+buildNodeWithChildren :: M.Map Text Text -> M.Map Text [Text] -> Text -> (Text, [Text])+buildNodeWithChildren nodeMap parentMap nodeId =+  let nodeText = M.findWithDefault "" nodeId nodeMap+      childIds = M.findWithDefault [] nodeId parentMap+      -- Only include children that have text+      childTexts = filter (not . T.null) $+                   map (\cid -> M.findWithDefault "" cid nodeMap) childIds+   in (nodeText, childTexts)++-- | Convert diagram to Pandoc blocks+diagramToBlocks :: PptxDiagram -> [Block]+diagramToBlocks diagram =+  let nodes = diagramNodes diagram+      layoutType = diagramType diagram++      -- Build content blocks+      contentBlocks = concatMap nodeToBlocks nodes++   in [Div ("", ["smartart", layoutType], [("layout", layoutType)])+           contentBlocks]++-- | Convert node to blocks+nodeToBlocks :: (Text, [Text]) -> [Block]+nodeToBlocks (nodeText, childTexts) =+  if null childTexts+    then [Para [Strong [Str nodeText]]]+    else [ Para [Strong [Str nodeText]]+         , BulletList [[Plain [Str child]] | child <- childTexts]+         ]++-- | Recursively extract all text from an element and its descendants+getAllText :: Element -> Text+getAllText el =+  let textFromContent (Text cdata) = cdData cdata+      textFromContent (Elem e) = getAllText e+      textFromContent _ = ""+      texts = map textFromContent (elContent el)+   in T.unwords $ filter (not . T.null) texts++-- Helper functions+maybeToEither :: Text -> Maybe a -> Either Text a+maybeToEither err Nothing = Left err+maybeToEither _ (Just x) = Right x
src/Text/Pandoc/Readers/RIS.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Readers.RIS-   Copyright   : Copyright (C) 2022-2023 John MacFarlane+   Copyright   : Copyright (C) 2022-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -23,7 +23,7 @@ import Text.Pandoc.Definition import Text.Pandoc.Parsing import Data.Char (isAsciiUpper, isDigit, isSpace, ord, chr)-import Data.List (foldl')+import qualified Data.List as L import Citeproc (Reference(..), ItemId(..), Val(..), Date(..), DateParts(..),                  toVariable) import Text.Pandoc.Builder as B@@ -185,7 +185,7 @@   return $ fixDuplicateIds $ map risRecordToReference recs  fixDuplicateIds :: [Reference Text] -> [Reference Text]-fixDuplicateIds = reverse . snd . foldl' go (mempty, [])+fixDuplicateIds = reverse . snd . L.foldl' go (mempty, [])  where    go (ids_seen, refs) ref =      case M.lookup (referenceId ref) ids_seen of
src/Text/Pandoc/Readers/RST.hs view
@@ -4,7 +4,7 @@ {-# LANGUAGE ViewPatterns        #-} {- |    Module      : Text.Pandoc.Readers.RST-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -15,20 +15,22 @@ -} module Text.Pandoc.Readers.RST ( readRST ) where import Control.Arrow (second)-import Control.Monad (forM_, guard, liftM, mplus, mzero, when)+import Control.Monad (forM_, guard, liftM, mplus, mzero, when, unless, void) import Control.Monad.Except (throwError) import Control.Monad.Identity (Identity (..))-import Data.Char (isHexDigit, isSpace, toUpper, isAlphaNum)+import Data.Char (isHexDigit, isSpace, toUpper, isAlphaNum, generalCategory,+                  GeneralCategory(OpenPunctuation, InitialQuote, FinalQuote,+                                  DashPunctuation, OtherSymbol)) import Data.List (deleteFirstsBy, elemIndex, nub, partition, sort, transpose) import qualified Data.Map as M-import Data.Maybe (fromMaybe, maybeToList, isJust)+import Data.Maybe (fromMaybe, maybeToList, isJust, isNothing, catMaybes) import Data.Sequence (ViewR (..), viewr) import Data.Text (Text) import qualified Data.Text as T import Text.Printf (printf) import Text.Pandoc.Builder (Blocks, Inlines, fromList, setMeta, trimInlines) import qualified Text.Pandoc.Builder as B-import Text.Pandoc.Class.PandocMonad (PandocMonad, fetchItem, getTimestamp)+import Text.Pandoc.Class (PandocMonad, readFileFromDirs, fetchItem, getTimestamp) import Text.Pandoc.CSV (CSVOptions (..), defaultCSVOptions, parseCSV) import Text.Pandoc.Definition import Text.Pandoc.Error@@ -38,6 +40,7 @@ import Text.Pandoc.Parsing import Text.Pandoc.Shared import Text.Pandoc.URI+import Text.Pandoc.Walk (walkM) import qualified Text.Pandoc.UTF8 as UTF8 import Data.Time.Format import System.FilePath (takeDirectory)@@ -114,18 +117,16 @@  metaFromDefList :: [([Inline], [[Block]])] -> Meta -> Meta metaFromDefList ds meta = adjustAuthors $ foldr f meta ds- where f (k,v) = setMeta (T.toLower $ stringify k) (mconcat $ map fromList v)+ where f (k,v) =+         case v of+           [[Plain ils]] ->  setMeta (T.toLower (stringify k)) $ MetaInlines ils+           _ -> setMeta (T.toLower (stringify k)) $ mconcat $ map fromList v        adjustAuthors (Meta metamap) = Meta $ M.adjust splitAuthors "author"-                                           $ M.adjust toPlain "date"-                                           $ M.adjust toPlain "title"                                            $ M.mapKeys (\k ->                                                  if k == "authors"                                                     then "author"                                                     else k) metamap-       toPlain (MetaBlocks [Para xs]) = MetaInlines xs-       toPlain x                      = x-       splitAuthors (MetaBlocks [Para xs])-                                      = MetaList $ map MetaInlines+       splitAuthors (MetaInlines xs)  = MetaList $ map MetaInlines                                                  $ splitAuthors' xs        splitAuthors x                 = x        splitAuthors'                  = map normalizeSpaces .@@ -148,44 +149,99 @@  parseRST :: PandocMonad m => RSTParser m Pandoc parseRST = do+  standalone <- getOption readerStandalone   optional blanklines -- skip blank lines at beginning of file-  startPos <- getPosition-  -- go through once just to get list of reference keys and notes-  -- docMinusKeys is the raw document with blanks where the keys were...-  let chunk = referenceKey-              <|> anchorDef-              <|> noteBlock-              <|> citationBlock-              <|> (snd <$> withRaw comment)-              <|> headerBlock-              <|> lineClump-  docMinusKeys <- Sources <$>-                  manyTill (do pos <- getPosition-                               t <- chunk-                               return (pos, t)) eof-  -- UGLY: we collapse source position information.-  -- TODO: fix the parser to use the F monad instead of two passes-  setInput docMinusKeys-  setPosition startPos-  st' <- getState-  let reversedNotes = stateNotes st'-  updateState $ \s -> s { stateNotes = reverse reversedNotes-                        , stateIdentifiers = mempty }-  -- now parse it for real...   blocks <- B.toList <$> parseBlocks   citations <- sort . M.toList . stateCitations <$> getState   citationItems <- mapM parseCitation citations   let refBlock = [Div ("citations",[],[]) $                  B.toList $ B.definitionList citationItems | not (null citationItems)]-  standalone <- getOption readerStandalone   state <- getState   let meta = stateMeta state   let (blocks', meta') = if standalone                             then titleTransform (blocks, meta)                             else (blocks, meta)+  let reversedNotes = stateNotes state+  updateState $ \s -> s { stateNotes = reverse reversedNotes }+  doc <- walkM resolveReferences =<<+         walkM resolveBlockSubstitutions+         (Pandoc meta' (blocks' ++ refBlock))   reportLogMessages-  return $ Pandoc meta' (blocks' ++ refBlock)+  return doc +resolveBlockSubstitutions :: PandocMonad m => Block -> RSTParser m Block+resolveBlockSubstitutions x@(Para [Link _attr _ (s,_)])+  | Just ref <- T.stripPrefix "##SUBST##" s = do+          substTable <- stateSubstitutions <$> getState+          let key@(Key key') = toKey $ stripFirstAndLast ref+          case M.lookup key substTable of+               Nothing     -> do+                 pos <- getPosition+                 logMessage $ ReferenceNotFound (tshow key') pos+                 return x+               Just target -> case+                 B.toList target of+                   [bl] -> return bl+                   bls -> return $ Div nullAttr bls+resolveBlockSubstitutions x = return x++resolveReferences :: PandocMonad m => Inline -> RSTParser m Inline+resolveReferences x@(Link _ ils (s,_))+  | Just ref <- T.stripPrefix "##REF##" s = do+      let isAnonKey (Key (T.uncons -> Just ('_',_))) = True+          isAnonKey _                                = False+      state <- getState+      let keyTable = stateKeys state+      let anonKeys = sort $ filter isAnonKey $ M.keys keyTable+      key <-  if ref == "_" -- anonymous key+                then+                  case anonKeys of+                    []    -> mzero -- TODO log?+                    (k:_) -> return k+                else return $ toKey ref+      ((src,tit), attr) <- lookupKey [] key+      -- if anonymous link, remove key so it won't be used again+      when (isAnonKey key) $ updateState $ \st ->+                              st{ stateKeys = M.delete key keyTable }+      return $ Link attr ils (src, tit)+  | Just ref <- T.stripPrefix "##NOTE##" s = do+      state <- getState+      let notes = stateNotes state+      case lookup ref notes of+        Nothing   -> do+          pos <- getPosition+          logMessage $ ReferenceNotFound ref pos+          return x+        Just raw  -> do+          -- We temporarily empty the note list while parsing the note,+          -- so that we don't get infinite loops with notes inside notes...+          -- Note references inside other notes are allowed in reST, but+          -- not yet in this implementation.+          updateState $ \st -> st{ stateNotes = [] }+          contents <- parseFromString' parseBlocks raw+          let newnotes = if ref == "*" || ref == "#" -- auto-numbered+                            -- delete the note so the next auto-numbered note+                            -- doesn't get the same contents:+                            then deleteFirstsBy (==) notes [(ref,raw)]+                            else notes+          updateState $ \st -> st{ stateNotes = newnotes }+          return $ Note (B.toList contents)+  | Just ref <- T.stripPrefix "##SUBST##" s = do+          substTable <- stateSubstitutions <$> getState+          let key@(Key key') = toKey $ stripFirstAndLast ref+          case M.lookup key substTable of+               Nothing     -> do+                 pos <- getPosition+                 logMessage $ ReferenceNotFound (tshow key') pos+                 return x+               Just target -> case+                 B.toList target of+                   [Para [t]] -> return t+                   [Para xs] -> return $ Span nullAttr xs+                   bls -> return $ Span nullAttr $ blocksToInlines bls+  | otherwise = return x+resolveReferences x = return x+ parseCitation :: PandocMonad m               => (Text, Text) -> RSTParser m (Inlines, [Blocks]) parseCitation (ref, raw) = do@@ -205,6 +261,10 @@ block = choice [ codeBlock                , blockQuote                , fieldList+               , optionList+               , referenceKey+               , noteBlock+               , citationBlock                , directive                , anchor                , comment@@ -228,7 +288,7 @@   guard $ indent >= minIndent   char ':'   name <- many1TillChar (noneOf "\n") (char ':')-  (() <$ lookAhead newline) <|> skipMany1 spaceChar+  (void (lookAhead newline)) <|> skipMany1 spaceChar   first <- anyLine   rest <- option "" $ try $ do lookAhead (count indent (char ' ') >> spaceChar)                                indentedBlock@@ -242,7 +302,10 @@   term <- parseInlineFromText name   contents <- parseFromString' parseBlocks raw   optional blanklines-  return (term, [contents])+  let defn = case B.toList contents of+                [Para ils] -> [B.plain $ B.fromList ils] -- see #7766+                _ -> [contents]+  return (term, defn)  fieldList :: PandocMonad m => RSTParser m Blocks fieldList = try $ do@@ -252,6 +315,51 @@      []     -> return mempty      items' -> return $ B.definitionList items' +optionList :: PandocMonad m => RSTParser m Blocks+optionList = B.definitionList <$> many1 optionListItem++optionListItem :: PandocMonad m => RSTParser m (Inlines, [Blocks])+optionListItem = try $ do+  opts <- snd <$> withRaw (do+     let anyOpt = shortOpt <|> longOpt <|> dosOpt+     anyOpt+     many $ try (char ',' <* many spaceChar *> anyOpt))+  -- at least two spaces+  rawfirst <- try (char ' ' *> many1 (char ' ') *> anyLineNewline)+                    <|> try (mempty <$ skipMany spaceChar <* newline)+  bodyElements <- do+    raw <- option "" indentedBlock+    parseFromString' parseBlocks $ (rawfirst <> raw) <> "\n\n"+  optional blanklines+  pure (B.code opts, [bodyElements])++shortOpt :: PandocMonad m => RSTParser m ()+shortOpt = try $ do+  char '-'+  alphaNum+  optional $ try (optional (char ' ') *> optArg)++optArg :: PandocMonad m => RSTParser m ()+optArg = do+  c <- letter <|> char '<'+  if c == '<'+     then void $ manyTill (noneOf "<>") (char '>')+     else skipMany (alphaNum <|> char '_' <|> char '-')++longOpt :: PandocMonad m => RSTParser m ()+longOpt = try $ do+  char '-'+  char '-'+  alphaNum+  skipMany1 (alphaNum <|> char '-' <|> char '_')+  optional $ try (oneOf " =" *> optArg)++dosOpt :: PandocMonad m => RSTParser m ()+dosOpt = try $ do+  char '/'+  alphaNum <|> char '?'+  optional $ try (char ' ' *> optArg)+ -- -- line block --@@ -307,7 +415,10 @@         Just ind -> (headerTable, ind + 1)         Nothing  -> (headerTable ++ [DoubleHeader c], length headerTable + 1)   setState (state { stateHeaderTable = headerTable' })-  attr <- registerHeader nullAttr txt+  attr@(ident,_,_) <- registerHeader nullAttr txt+  let key = toKey (stringify txt)+  updateState $ \s ->+    s { stateKeys = M.insert key (("#" <> ident,""), nullAttr) $ stateKeys s }   return $ B.headerWith attr level txt  doubleHeader' :: PandocMonad m => RSTParser m (Inlines, Char)@@ -336,7 +447,10 @@         Just ind -> (headerTable, ind + 1)         Nothing  -> (headerTable ++ [SingleHeader c], length headerTable + 1)   setState (state { stateHeaderTable = headerTable' })-  attr <- registerHeader nullAttr txt+  attr@(ident,_,_) <- registerHeader nullAttr txt+  let key = toKey (stringify txt)+  updateState $ \s ->+    s { stateKeys = M.insert key (("#" <> ident,""), nullAttr) $ stateKeys s }   return $ B.headerWith attr level txt  singleHeader' :: PandocMonad m => RSTParser m (Inlines, Char)@@ -558,7 +672,7 @@ listItem start = try $ do   (markerLength, first) <- rawListItem start   rest <- many (listContinuation markerLength)-  skipMany1 blankline <|> () <$ lookAhead start+  skipMany1 blankline <|> void (lookAhead start)   -- parsing with ListItemState forces markers at beginning of lines to   -- count as list item markers, even if not separated by blank space.   -- see definition of "endline"@@ -596,7 +710,7 @@ comment :: Monad m => RSTParser m Blocks comment = try $ do   string ".."-  skipMany1 spaceChar <|> (() <$ lookAhead newline)+  skipMany1 spaceChar <|> void (lookAhead newline)   -- notFollowedBy' directiveLabel -- comment comes after directive so unnec.   _ <- anyLine   optional indentedBlock@@ -628,13 +742,18 @@     if fieldIndent == 0        then return []        else many $ rawFieldListItem fieldIndent-  body <- option "" $ try $ blanklines >> indentedBlock+  let mbfile = trim <$> lookup "file" fields+  body <- case mbfile of+            Just f | label == "raw" -> do+               currentDir <- takeDirectory . sourceName <$> getPosition+               fromMaybe mempty <$> readFileFromDirs [currentDir] (T.unpack f)+            _ -> option "" $ try $ blanklines >> indentedBlock   optional blanklines   let body' = body <> "\n\n"       name = trim $ fromMaybe "" (lookup "name" fields)       classes = T.words $ maybe "" trim (lookup "class" fields)       keyvals = [(k, trim v) | (k, v) <- fields, k /= "name", k /= "class"]-      imgAttr cl = (name, classes ++ alignClasses, widthAttr ++ heightAttr)+      imgAttr cl = (name, classes, alignClasses, widthAttr ++ heightAttr)         where           alignClasses = T.words $ maybe "" trim (lookup cl fields) <>                           maybe "" (\x -> "align-" <> trim x)@@ -731,21 +850,25 @@         "figure" -> do            (caption, legend) <- parseFromString' extractCaption body'            let src = escapeURI $ trim top-           let (ident, cls, kvs) = imgAttr "class"-           let (figclasskv, kvs') = partition ((== "figclass") . fst) kvs-           let figattr = ("", concatMap (T.words . snd) figclasskv, [])+           let (imgident, imgcls, aligncls, imgkvs) = imgAttr "class"+           let (figclasskv, _) = partition ((== "figclass") . fst) keyvals+           let figcls = concatMap (T.words . snd) figclasskv+           let figattr = ("", figcls ++ aligncls, [])            let capt = B.caption Nothing (B.plain caption <> legend)+           let alt = maybe caption (B.text . trim) (lookup "alt" fields)            return $ B.figureWith figattr capt $-             B.plain (B.imageWith (ident, cls, kvs') src "" (B.text src))+             B.plain (B.imageWith (imgident, imgcls, imgkvs) src "" alt)         "image" -> do            let src = escapeURI $ trim top            let alt = B.str $ maybe "image" trim $ lookup "alt" fields-           let attr = imgAttr "class"+           let attr = (ident, cls ++ align, dims) where+                 (ident, cls, align, dims) = imgAttr "class"            return $ B.para                   $ case lookup "target" fields of                           Just t  -> B.link (escapeURI $ trim t) ""                                      $ B.imageWith attr src "" alt                           Nothing -> B.imageWith attr src "" alt+        "bibliography" -> pure $ B.divWith ("refs",[],[]) mempty         "class" -> do             let attrs = (name, T.words (trim top), map (second trimr) fields)             --  directive content or the first immediately following element@@ -789,7 +912,10 @@          let tspecs = zip aligns' widths          return $ B.singleton $ Table attr (B.caption Nothing (B.plain title))                                   tspecs thead tbody tfoot-       _ -> return mempty+       _ -> do+         pos <- getPosition+         logMessage $ SkippedContent body pos+         return mempty   where     -- only valid on the very first row of a table section     rowLength (Row _ rb) = sum $ cellLength <$> rb@@ -879,12 +1005,6 @@        Left e  ->          throwError $ fromParsecError (toSources rawcsv') e        Right rawrows -> do-         let singleParaToPlain bs =-               case B.toList bs of-                 [Para ils] -> B.fromList [Plain ils]-                 _          -> bs-         let parseCell t = singleParaToPlain-                <$> parseFromString' parseBlocks (t <> "\n\n")          let parseRow = mapM parseCell          rows <- mapM parseRow rawrows          let (headerRow,bodyRows,numOfCols) =@@ -913,6 +1033,17 @@                           [TableBody nullAttr 0 [] $ map toRow bodyRows]                           (TableFoot nullAttr []) +singleParaToPlain :: Blocks -> Blocks+singleParaToPlain bs =+  case B.toList bs of+    [Para ils] -> B.fromList [Plain ils]+    _          -> bs++parseCell :: PandocMonad m => Text -> RSTParser m Blocks+parseCell t = singleParaToPlain+   <$> parseFromString' parseBlocks (trim t <> "\n\n")++ -- TODO: --  - Only supports :format: fields with a single format for :raw: roles, --    change Text.Pandoc.Definition.Format to fix@@ -1049,27 +1180,24 @@ --- note block --- -noteBlock :: Monad m => RSTParser m Text+noteBlock :: Monad m => RSTParser m Blocks noteBlock = try $ do-  (ref, raw, replacement) <- noteBlock' noteMarker+  (ref, raw) <- noteBlock' noteMarker   updateState $ \s -> s { stateNotes = (ref, raw) : stateNotes s }-  -- return blanks so line count isn't affected-  return replacement+  return mempty -citationBlock :: Monad m => RSTParser m Text+citationBlock :: Monad m => RSTParser m Blocks citationBlock = try $ do-  (ref, raw, replacement) <- noteBlock' citationMarker+  (ref, raw) <- noteBlock' citationMarker   updateState $ \s ->      s { stateCitations = M.insert ref raw (stateCitations s),          stateKeys = M.insert (toKey ref) (("#" <> ref,""), ("",["citation"],[]))                                (stateKeys s) }-  -- return blanks so line count isn't affected-  return replacement+  return mempty  noteBlock' :: Monad m-           => RSTParser m Text -> RSTParser m (Text, Text, Text)+           => RSTParser m Text -> RSTParser m (Text, Text) noteBlock' marker = try $ do-  startPos <- getPosition   string ".."   spaceChar >> skipMany spaceChar   ref <- marker@@ -1077,10 +1205,8 @@         <|> (newline >> return "")   blanks <- option "" blanklines   rest <- option "" indentedBlock-  endPos <- getPosition   let raw = first <> "\n" <> blanks <> rest <> "\n"-  let replacement = T.replicate (sourceLine endPos - sourceLine startPos) "\n"-  return (ref, raw, replacement)+  return (ref, raw)  citationMarker :: Monad m => RSTParser m Text citationMarker = do@@ -1122,14 +1248,11 @@ referenceName :: PandocMonad m => RSTParser m Text referenceName = quotedReferenceName <|> simpleReferenceName -referenceKey :: PandocMonad m => RSTParser m Text+referenceKey :: PandocMonad m => RSTParser m Blocks referenceKey = do-  startPos <- getPosition   choice [substKey, anonymousKey, regularKey]   optional blanklines-  endPos <- getPosition-  -- return enough blanks to replace key-  return $ T.replicate (sourceLine endPos - sourceLine startPos) "\n"+  return mempty  targetURI :: Monad m => ParsecT Sources st m Text targetURI = do@@ -1153,21 +1276,21 @@   (alt,ref) <- withRaw $ trimInlines . mconcat                       <$> enclosed (char '|') (char '|') inline   res <- B.toList <$> directive'-  il <- case res of+  bls <- case res of              -- use alt unless :alt: attribute on image:              [Para [Image attr [Str "image"] (src,tit)]] ->-                return $ B.imageWith attr src tit alt+                return $ B.para $ B.imageWith attr src tit alt              [Para [Link _ [Image attr [Str "image"] (src,tit)] (src',tit')]] ->-                return $ B.link src' tit' (B.imageWith attr src tit alt)-             [Para ils] -> return $ B.fromList ils-             _          -> mzero+                return $ B.para $ B.link src' tit' (B.imageWith attr src tit alt)+             _          -> return $ B.fromList res   let key = toKey $ stripFirstAndLast ref   updateState $ \s -> s{ stateSubstitutions =-                          M.insert key il $ stateSubstitutions s }+                          M.insert key bls $ stateSubstitutions s }  anonymousKey :: PandocMonad m => RSTParser m () anonymousKey = try $ do   oneOfStrings [".. __:", "__"]+  skipMany1 spaceChar   src <- targetURI   -- we need to ensure that the keys are ordered by occurrence in   -- the document.@@ -1207,19 +1330,14 @@     updateState $ \s -> s { stateKeys = M.insert key ((src,""), nullAttr) $                             stateKeys s } -anchorDef :: PandocMonad m => RSTParser m Text-anchorDef = try $ do-  (refs, raw) <- withRaw $ try (referenceNames <* blanklines)-  forM_ refs $ \rawkey ->-    updateState $ \s -> s { stateKeys =-       M.insert (toKey rawkey) (("#" <> rawkey,""), nullAttr) $ stateKeys s }-  -- keep this for 2nd round of parsing, where we'll add the divs (anchor)-  return raw- anchor :: PandocMonad m => RSTParser m Blocks anchor = try $ do   refs <- referenceNames   blanklines+  forM_ refs $ \rawkey ->+    updateState $ \s -> s { stateKeys =+       M.insert (toKey rawkey) (("#" <> rawkey,""), nullAttr)+         (stateKeys s) }   b <- block   let addDiv ref = B.divWith (ref, [], [])   let emptySpanWithId id' = Span (id',[],[]) []@@ -1235,16 +1353,6 @@                 -- because it hides them from promoteHeader, see #4240        _ -> return $ foldr addDiv b refs -headerBlock :: PandocMonad m => RSTParser m Text-headerBlock = do-  ((txt, _), raw) <- withRaw (doubleHeader' <|> singleHeader')-  (ident,_,_) <- registerHeader nullAttr txt-  let key = toKey (stringify txt)-  updateState $ \s -> s { stateKeys = M.insert key (("#" <> ident,""), nullAttr)-                          $ stateKeys s }-  return raw-- -- -- tables --@@ -1254,7 +1362,6 @@ --    support for them -- -- Simple tables TODO:---  - column spans --  - multiline support --  - ensure that rightmost column span does not need to reach end --  - require at least 2 columns@@ -1263,67 +1370,105 @@ dashedLine ch = do   dashes <- many1 (char ch)   sp     <- many (char ' ')-  return (length dashes, length $ dashes ++ sp)+  return (length dashes, length sp)  simpleDashedLines :: Monad m => Char -> ParsecT Sources st m [(Int,Int)]-simpleDashedLines ch = try $ many1 (dashedLine ch)+simpleDashedLines ch = try $ do+  lines' <- many1 (dashedLine ch)+  skipMany spaceChar+  newline+  return $ addSpaces lines'+ where+  addSpaces [] = []+  addSpaces [(dashes, _)] = [(dashes, dashes)] -- Don't count trailing whitespaces+  addSpaces ((dashes, sp) : moreLines) =+    (dashes, dashes + sp) : addSpaces moreLines  -- Parse a table row separator-simpleTableSep :: Monad m => Char -> RSTParser m Char-simpleTableSep ch = try $ simpleDashedLines ch >> newline+simpleTableSep :: Monad m => Char -> RSTParser m ()+simpleTableSep ch = void (simpleDashedLines ch)  -- Parse a table footer-simpleTableFooter :: Monad m => RSTParser m Text-simpleTableFooter = try $ simpleTableSep '=' >> blanklines+simpleTableFooter :: Monad m => RSTParser m ()+simpleTableFooter = try $ simpleTableSep '=' >> void blanklines  -- Parse a raw line and split it into chunks by indices.-simpleTableRawLine :: Monad m => [Int] -> RSTParser m [Text]-simpleTableRawLine indices = simpleTableSplitLine indices <$> anyLine+simpleTableRawLine :: Monad m => [Int] -> RSTParser m [(Text, ColSpan)]+simpleTableRawLine indices = do+  row <- rowWithOptionalColSpan -simpleTableRawLineWithEmptyCell :: Monad m => [Int] -> RSTParser m [Text]-simpleTableRawLineWithEmptyCell indices = try $ do+  case simpleTableSplitLine indices row of+    Just rowLine -> return rowLine+    Nothing -> Prelude.fail "col spans don't match"++simpleTableRawLineWithInitialEmptyCell :: Monad m => [Int] -> RSTParser m [(Text, ColSpan)]+simpleTableRawLineWithInitialEmptyCell indices = try $ do   cs <- simpleTableRawLine indices   let isEmptyCell = T.all (\c -> c == ' ' || c == '\t')-  guard $ any isEmptyCell cs-  return cs+  case cs of+    c:_ | isEmptyCell (fst c) -> return cs+    _ -> mzero  -- Parse a table row and return a list of blocks (columns).-simpleTableRow :: PandocMonad m => [Int] -> RSTParser m [Blocks]+simpleTableRow :: PandocMonad m => [Int] -> RSTParser m [(Blocks, RowSpan, ColSpan)] simpleTableRow indices = do-  notFollowedBy' simpleTableFooter+  notFollowedBy' (void blanklines <|> simpleTableFooter)   firstLine <- simpleTableRawLine indices-  conLines  <- many $ simpleTableRawLineWithEmptyCell indices-  let cols = map T.unlines . transpose $ firstLine : conLines +++  conLines  <- many $ simpleTableRawLineWithInitialEmptyCell indices+  let cols = map T.unlines . transpose $ (map fst firstLine) : (map (map fst) conLines) ++                                   [replicate (length indices) ""                                     | not (null conLines)]-  mapM (parseFromString' parseBlocks) cols+  let rowParser = mapM parseCell cols+  fmap (\blocks -> zip3 blocks (repeat 1) (map snd firstLine)) rowParser -simpleTableSplitLine :: [Int] -> Text -> [Text]-simpleTableSplitLine indices line =-  map trimr-  $ tail $ splitTextByIndices (init indices) line+simpleTableSplitLine :: [Int] -> (Text, Maybe [Int]) -> Maybe [(Text, ColSpan)]+simpleTableSplitLine indices (line, maybeColspanIndices) =+  fmap (zip tableLines) columnSpans+ where+  splitTableLines lineIndices = map trimr $ drop 1 $ splitTextByIndices (init lineIndices) line+  (tableLines, columnSpans) = case maybeColspanIndices of+      Nothing -> (splitTableLines indices, Just $ repeat 1)+      Just colSpanIndices -> (splitTableLines colSpanIndices, colSpans indices colSpanIndices)  simpleTableHeader :: PandocMonad m                   => Bool  -- ^ Headerless table-                  -> RSTParser m ([Blocks], [Alignment], [Int])+                  -> RSTParser m ([[(Blocks, RowSpan, ColSpan)]], [Alignment], [Int]) simpleTableHeader headless = try $ do   optional blanklines+  dashes <- simpleDashedLines '='+   rawContent  <- if headless-                    then return ""-                    else simpleTableSep '=' >> anyLine-  dashes      <- if headless-                    then simpleDashedLines '='-                    else simpleDashedLines '=' <|> simpleDashedLines '-'-  newline-  let lines'   = map snd dashes-  let indices  = scanl (+) 0 lines'+                    then return [("", Nothing)]+                    else many1 $ notFollowedBy (simpleDashedLines '=') >> rowWithOptionalColSpan++  unless headless $ simpleTableSep '='++  let (lines', indices) = dashedLinesToLinesWithIndices dashes   let aligns   = replicate (length lines') AlignDefault   let rawHeads = if headless                     then []-                    else simpleTableSplitLine indices rawContent-  heads <- mapM ( parseFromString' (mconcat <$> many plain) . trim) rawHeads-  return (heads, aligns, indices)+                    else map (simpleTableSplitLine indices) rawContent +  when (any isNothing rawHeads) $ Prelude.fail "col spans don't match"++  let justRawHeads  = catMaybes rawHeads+  let rawHeads'     = map fst <$> justRawHeads+  let columnSpans   = map snd <$> justRawHeads+  heads <- mapM (mapM $ parseFromString' (mconcat <$> many plain) . trim) rawHeads'+  let headsWithSpans = zipWith3 zip3 heads singleRowSpans columnSpans+  return (headsWithSpans, aligns, indices)++rowWithOptionalColSpan :: Monad m+                       => RSTParser m (Text, Maybe [Int])+rowWithOptionalColSpan = do+  line <- anyLine+  colSpanHyphens <- optionMaybe $ simpleDashedLines '-'++  let colSpan = fmap colSpanFromHyphens colSpanHyphens+  return (line, colSpan)+ where+  colSpanFromHyphens colSpanHyphens = snd $ dashedLinesToLinesWithIndices colSpanHyphens+ -- Parse a simple table. simpleTable :: PandocMonad m             => Bool  -- ^ Headerless table@@ -1331,7 +1476,7 @@ simpleTable headless = do   let wrapIdFst (a, b, c) = (Identity a, b, c)       wrapId = fmap Identity-  tbl <- runIdentity <$> tableWith+  tbl <- runIdentity <$> tableWithSpans            (wrapIdFst <$> simpleTableHeader headless)            (wrapId <$> simpleTableRow)            sep simpleTableFooter@@ -1359,14 +1504,14 @@ --  inline :: PandocMonad m => RSTParser m Inlines-inline = choice [ note          -- can start with whitespace, so try before ws-                , link-                , strong-                , emph-                , code-                , subst-                , interpretedRole-                , inlineContent ] <?> "inline"+inline =+  (note          -- can start with whitespace, so try before ws+    <|> do notAfterString >>= guard+           (link <|> inlineAnchor <|> strong <|> emph)+    <|> code+    <|> subst+    <|> interpretedRole+    <|> inlineContent) <?> "inline"  -- strings, spaces and other characters that can appear either by -- themselves or within inline markup@@ -1375,31 +1520,31 @@                        , str                        , endline                        , smart-                       , hyphens                        , escapedChar                        , symbol ] <?> "inline content"  parseInlineFromText :: PandocMonad m => Text -> RSTParser m Inlines parseInlineFromText = parseFromString' (trimInlines . mconcat <$> many inline) -hyphens :: Monad m => RSTParser m Inlines-hyphens = do-  result <- many1Char (char '-')-  optional endline-  -- don't want to treat endline after hyphen or dash as a space-  return $ B.str result--escapedChar :: Monad m => ParsecT Sources st m Inlines+escapedChar :: Monad m => RSTParser m Inlines escapedChar = do c <- escaped anyChar-                 return $ if c == ' ' || c == '\n' || c == '\r'-                             -- '\ ' is null in RST-                             then mempty-                             else B.str $ T.singleton c+                 if c == ' ' || c == '\n' || c == '\r'+                    -- '\ ' is null in RST+                    then return mempty+                    else do+                      unless (canPrecedeOpener c) updateLastStrPos+                      return $ B.str $ T.singleton c +canPrecedeOpener :: Char -> Bool+canPrecedeOpener c =+  generalCategory c `elem`+   [OpenPunctuation, InitialQuote, FinalQuote, DashPunctuation, OtherSymbol]+ symbol :: Monad m => RSTParser m Inlines symbol = do-  result <- oneOf specialChars-  return $ B.str $ T.singleton result+  c <- oneOf specialChars+  unless (canPrecedeOpener c) updateLastStrPos+  return $ B.str $ T.singleton c  -- parses inline code, between codeStart and codeEnd code :: Monad m => RSTParser m Inlines@@ -1460,7 +1605,10 @@     "code" -> return $ B.codeWith attr contents     "span" -> return $ B.spanWith attr $ treatAsText contents     "raw" -> return $ B.rawInline (fromMaybe "" fmt) contents-    custom -> do+    custom+     | Just citeType <- T.stripPrefix "cite" custom+       -> cite citeType contents+     | otherwise -> do         customRoles <- stateRstCustomRoles <$> getState         case M.lookup custom customRoles of             Just (newRole, newFmt, newAttr) ->@@ -1481,6 +1629,40 @@            removeSpace (x:xs) = x : map headSpace xs            removeSpace []     = [] +cite :: PandocMonad m => Text -> Text -> RSTParser m Inlines+cite citeType rawcite = do+  let citations =+        case map parseCite (T.splitOn "," rawcite) of+                (c:cs)+                  | citeType == ":t" || citeType == ":ct"+                     -> c{ citationMode = AuthorInText } : cs+                  | citeType == ":year" || citeType == ":yearpar"+                     -> c{ citationMode = SuppressAuthor } : cs+                cs -> cs+  pure $ B.cite citations (B.str rawcite)++parseCite :: Text -> Citation+parseCite t =+  let (_, pref, suff, ident) = T.foldl go (ParseStart, "", "", "") t+  in  Citation{citationId = ident+              ,citationPrefix = B.toList $ B.text pref+              ,citationSuffix = B.toList $ B.text suff+              ,citationMode = NormalCitation+              ,citationNoteNum = 0+              ,citationHash = 0}+ where+   go (ParseStart, p, s, i) '{' = (ParsePrefix, p, s, i)+   go (ParseStart, p, s, i) c = (ParseId, p, s, T.snoc i c)+   go (ParsePrefix, p, s, i) '}' = (ParseId, p, s, i)+   go (ParsePrefix, p, s, i) c = (ParsePrefix, T.snoc p c, s, i)+   go (ParseId, p, s, i) '{' = (ParseSuffix, p, s, i)+   go (ParseId, p, s, i) c = (ParseId, p, s, T.snoc i c)+   go (ParseSuffix, p, s, i) '}' = (ParseSuffix, p, s, i)+   go (ParseSuffix, p, s, i) c = (ParseSuffix, p, T.snoc s c, i)++data ParseCiteState = ParseStart | ParsePrefix | ParseSuffix | ParseId+  deriving (Show)+ -- single words consisting of alphanumerics plus isolated (no two adjacent) -- internal hyphens, underscores, periods, colons and plus signs; -- no whitespace or other characters are allowed@@ -1510,7 +1692,7 @@       <|> (char '\\' >> ((\c -> ['\\',c]) <$> noneOf "\n"))       <|> (string "\n" <* notFollowedBy blankline)       <|> try (string "`" <*-                notFollowedBy (() <$ roleMarker) <*+                notFollowedBy (void roleMarker) <*                 lookAhead (satisfy isAlphaNum))        )   char '`'@@ -1549,48 +1731,44 @@   char '`'   notFollowedBy (char '`') -- `` marks start of inline code   label' <- trimInlines . mconcat <$>-             manyTill (notFollowedBy (char '`') >> inlineContent) (char '<')-  src <- trim <$> manyTillChar (noneOf ">\n") (char '>')+              manyTill (notFollowedBy (char '`') >> inlineContent) (char '<')+  src <- trim . T.pack . filter (/= '\n') <$> -- see #10279+           manyTill (noneOf ">\n" <|> (char '\n' <* notFollowedBy blankline))+                    (char '>')   skipSpaces   string "`_"   optional $ char '_' -- anonymous form+  let src' | isURI src = escapeURI src+           | otherwise =+              case T.unsnoc src of+                 Just (xs, '_') -> "##REF##" <> xs+                 _              -> src   let label'' = if label' == mempty                    then B.str src                    else label'-  -- `link <google_>` is a reference link to _google!-  ((src',tit),attr) <--    if isURI src-       then return ((src, ""), nullAttr)-       else-         case T.unsnoc src of-           Just (xs, '_') -> lookupKey [] (toKey xs)-           _              -> return ((src, ""), nullAttr)-  return $ B.linkWith attr (escapeURI src') tit label''+  let key = toKey $ stringify label'+  unless (key == Key mempty) $ do+    updateState $ \s -> s{+      stateKeys = M.insert key ((src',""), nullAttr) $ stateKeys s }+  return $ B.linkWith nullAttr src' "" label''  citationName :: PandocMonad m => RSTParser m Text citationName = do   raw <- citationMarker   return $ "[" <> raw <> "]" +-- We store the reference link label as the link target,+-- preceded by '##REF##'. This is replaced after the AST+-- has been built by the resolved reference. referenceLink :: PandocMonad m => RSTParser m Inlines referenceLink = try $ do   ref <- (referenceName <|> citationName) <* char '_'-  let label' = B.text ref-  let isAnonKey (Key (T.uncons -> Just ('_',_))) = True-      isAnonKey _                                = False-  state <- getState-  let keyTable = stateKeys state-  key <- option (toKey ref) $-                do char '_'-                   let anonKeys = sort $ filter isAnonKey $ M.keys keyTable-                   case anonKeys of-                        []    -> mzero-                        (k:_) -> return k-  ((src,tit), attr) <- lookupKey [] key-  -- if anonymous link, remove key so it won't be used again-  when (isAnonKey key) $ updateState $ \s ->-                          s{ stateKeys = M.delete key keyTable }-  return $ B.linkWith attr src tit label'+  isAnonymous <- (True <$ char '_') <|> pure False+  eof <|> notFollowedBy alphaNum+  let ref' = if isAnonymous+                then "_"+                else ref+  pure $ B.linkWith nullAttr ("##REF##" <> ref') "" (B.text ref)  -- We keep a list of oldkeys so we can detect lookup loops. lookupKey :: PandocMonad m@@ -1610,6 +1788,10 @@          let newkey = toKey rawkey          if newkey `elem` oldkeys             then do+              -- TODO the pos is not going to be accurate+              -- because we're calling this after the AST is+              -- constructed. Probably good to remove that+              -- parameter form CircularReference at some point.               logMessage $ CircularReference rawkey pos               return (("",""),nullAttr)             else lookupKey (key:oldkeys) newkey@@ -1631,42 +1813,64 @@ subst :: PandocMonad m => RSTParser m Inlines subst = try $ do   (_,ref) <- withRaw $ enclosed (char '|') (char '|') inline-  state <- getState-  let substTable = stateSubstitutions state-  let key = toKey $ stripFirstAndLast ref-  case M.lookup key substTable of-       Nothing     -> do-         pos <- getPosition-         logMessage $ ReferenceNotFound (tshow key) pos-         return mempty-       Just target -> return target+  let substlink = B.linkWith nullAttr ("##SUBST##" <> ref) "" (B.text ref)+  reflink <- option False (True <$ char '_')+  if reflink+     then do+       let linkref = T.drop 1 $ T.dropEnd 1 ref+       return $ B.linkWith nullAttr ("##REF##" <> linkref) "" substlink+     else return substlink  note :: PandocMonad m => RSTParser m Inlines note = try $ do   optional whitespace   ref <- noteMarker   char '_'-  state <- getState-  let notes = stateNotes state-  case lookup ref notes of-    Nothing   -> do-      pos <- getPosition-      logMessage $ ReferenceNotFound ref pos-      return mempty-    Just raw  -> do-      -- We temporarily empty the note list while parsing the note,-      -- so that we don't get infinite loops with notes inside notes...-      -- Note references inside other notes are allowed in reST, but-      -- not yet in this implementation.-      updateState $ \st -> st{ stateNotes = [] }-      contents <- parseFromString' parseBlocks raw-      let newnotes = if ref == "*" || ref == "#" -- auto-numbered-                        -- delete the note so the next auto-numbered note-                        -- doesn't get the same contents:-                        then deleteFirstsBy (==) notes [(ref,raw)]-                        else notes-      updateState $ \st -> st{ stateNotes = newnotes }-      return $ B.note contents+  pure $ B.linkWith nullAttr ("##NOTE##" <> ref) "" (B.text ref)  smart :: PandocMonad m => RSTParser m Inlines smart = smartPunctuation inline++inlineAnchor :: PandocMonad m => RSTParser m Inlines+inlineAnchor = try $ do+  char '_'+  name <- quotedReferenceName <|> simpleReferenceName+  let ident = textToIdentifier mempty name+  updateState $ \s ->+    s{ stateKeys = M.insert (toKey name) (("#" <> ident, ""), nullAttr)+                    (stateKeys s) }+  pure $ B.spanWith (ident,[],[]) (B.text name)++dashedLinesToLinesWithIndices :: [(Int, Int)] -> ([Int], [Int])+dashedLinesToLinesWithIndices dashes =+  let lines'  = map snd dashes+      indices = scanl (+) 0 lines'+  in  (lines', indices)++-- | Determines column spans by appying indices of a table border with column span indices.+--+-- The indices need to align.+colSpans :: [Int] -> [Int] -> Maybe [ColSpan]+colSpans [] []  = Just []+colSpans [] _   = Nothing+colSpans _ []   = Nothing+colSpans (index : indices) colSpanIndices@(colIndex : colSpanIndicesTail)+    | index /= colIndex = colSpans indices colSpanIndices+    | otherwise =+        -- For a matching index start counting the column spans.+        let (spanCount, remainingIndices, remainingColSpanindices) = colSpanCount indices colSpanIndicesTail 1+        in  (:) spanCount <$> colSpans remainingIndices remainingColSpanindices++-- | Counts column spans by consuming all non-matching indices until a matching one is encountered.+--+-- If the indices match, the end of a column span has been encountered and the+-- column count can be returned. Otherwise, if the indices don't match, add to+-- the span count until a matching index is found.+colSpanCount :: [Int] -> [Int] -> ColSpan -> (ColSpan, [Int], [Int])+colSpanCount [] colSpanIndices spanCount = (spanCount, [], colSpanIndices)+colSpanCount _ [] spanCount = (spanCount, [], [])+colSpanCount indices@(index : indicesTail) colSpanIndices@(colIndex : colSpanIndicesTail) spanCount+    | index == colIndex = case colSpanIndicesTail of+        [] -> (spanCount, indicesTail, colSpanIndicesTail)+        _ -> (spanCount, indices, colSpanIndices)+    | otherwise = colSpanCount indicesTail colSpanIndices $ spanCount + 1
src/Text/Pandoc/Readers/RTF.hs view
@@ -3,7 +3,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Readers.RTF-   Copyright   : Copyright (C) 2021-2023 John MacFarlane+   Copyright   : Copyright (C) 2021-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane (<jgm@berkeley.edu>)@@ -19,7 +19,8 @@ import qualified Data.Sequence as Seq import Control.Monad import Control.Monad.Except (throwError)-import Data.List (find, foldl')+import Crypto.Hash (hashWith, SHA1(SHA1))+import qualified Data.List as L import Data.Word (Word8, Word16) import Data.Default import Data.Text (Text)@@ -27,14 +28,14 @@ import qualified Data.Text.Read as TR import Text.Pandoc.Builder (Blocks, Inlines) import qualified Text.Pandoc.Builder as B-import Text.Pandoc.Class.PandocMonad (PandocMonad (..), insertMedia)+import Text.Pandoc.Class (PandocMonad (..), insertMedia, report) import Text.Pandoc.Definition import Text.Pandoc.Options import Text.Pandoc.Parsing+import Text.Pandoc.Logging (LogMessage(UnsupportedCodePage)) import Text.Pandoc.Shared (tshow) import Data.Char (isAlphaNum, chr, isAscii, isLetter, isSpace, ord) import qualified Data.ByteString.Lazy as BL-import Data.Digest.Pure.SHA (sha1, showDigest) import Data.Maybe (mapMaybe, fromMaybe) import Safe (lastMay, initSafe, headDef) -- import Debug.Trace@@ -217,7 +218,7 @@   | ControlSymbol !Char   | UnformattedText !Text   | BinData !BL.ByteString-  | HexVal !Word8+  | HexVals [Word8]   | Grouped [Tok]   deriving (Show, Eq) @@ -229,7 +230,7 @@   controlThing = do     char '\\' *>       ( controlWord-     <|> (HexVal <$> hexVal)+     <|> (HexVals <$> many1 hexVal)      <|> (ControlSymbol <$> anyChar) )   controlWord = do     name <- letterSequence@@ -304,6 +305,26 @@             [] -> []             (x:xs) -> f x : xs } +-- | @\\plain@ resets character formatting to default values.  Unlike a+-- full reset to 'def', it must leave paragraph-level properties (such as+-- whether we are inside a table, the list level, or the outline level)+-- intact, as well as contextual properties like the current hyperlink or+-- anchor.  Resetting these caused tables to be parsed as deeply nested+-- structures when cell paragraphs used @\\plain@ after @\\intbl@.+resetCharProps :: Properties -> Properties+resetCharProps g =+  g{ gBold = False+   , gItalic = False+   , gCaps = False+   , gDeleted = False+   , gSub = False+   , gSuper = False+   , gSmallCaps = False+   , gUnderline = False+   , gFontFamily = Nothing+   , gHidden = False+   }+ addFormatting :: (Properties, Text) -> Inlines addFormatting (_, "\n") = B.linebreak addFormatting (props, _) | gHidden props = mempty@@ -423,14 +444,27 @@ processTok bs (Tok pos tok') = do   setPosition pos   case tok' of-    HexVal{} -> return ()+    HexVals{} -> return ()     UnformattedText{} -> return ()     _ -> updateState $ \s -> s{ sEatChars = 0 }   case tok' of-    Grouped (Tok _ (ControlSymbol '*') : toks) ->-      bs <$ (do oldTextContent <- sTextContent <$> getState-                processTok mempty (Tok pos (Grouped toks))-                updateState $ \st -> st{ sTextContent = oldTextContent })+    Grouped (Tok _ (ControlSymbol '*') : toks@(firsttok:_)) ->+      case firsttok of+        Tok _ (ControlWord "shppict" _) -> inGroup (foldM processTok bs toks)+        Tok _ (ControlWord "shpinst" _) -> inGroup (foldM processTok bs toks)+        _ -> bs <$ (do oldTextContent <- sTextContent <$> getState+                       processTok mempty (Tok pos (Grouped toks))+                       updateState $ \st -> st{ sTextContent = oldTextContent })+    Grouped (Tok _ (ControlWord "shp" _) : toks) ->+      inGroup (foldM processTok bs toks)+    Grouped [ Tok _ (ControlWord "sp" _)+            , Tok _ (Grouped [Tok _ (ControlWord "sn" _),+                      Tok _ (UnformattedText sn)])+            , Tok _ (Grouped (Tok _ (ControlWord "sv" _) : svtoks))+            ] ->+      case sn of+        "pib" -> inGroup (foldM processTok bs svtoks)+        _ -> pure bs     Grouped (Tok _ (ControlWord "fonttbl" _) : toks) -> inGroup $ do       updateState $ \s -> s{ sFontTable = processFontTable toks }       pure bs@@ -498,19 +532,22 @@              addText (T.drop n t)           | otherwise -> do              updateState $ \s -> s{ sEatChars = n - T.length t }-    HexVal n -> bs <$ do+    HexVals ws -> bs <$ do       eatChars <- sEatChars <$> getState-      if eatChars == 0-         then do-           charset <- sCharSet <$> getState-           case charset of-             ANSI -> addText (T.singleton $ ansiToChar n)-             Mac  -> addText (T.singleton $ macToChar n)-             Pc   -> addText (T.singleton $ pcToChar n)-             Pca  -> addText (T.singleton $ pcaToChar n)-         else updateState $ \s -> s{ sEatChars = eatChars - 1 }+      let ws' = drop eatChars ws+      updateState $ \s -> s{ sEatChars = if null ws'+                                            then eatChars - length ws+                                            else 0 }+      charset <- sCharSet <$> getState+      case charset of+        ANSI -> addText $ T.pack $ map defaultAnsiWordToChar ws'+        Mac  -> addText $ T.pack $ map macToChar ws'+        Pc   -> addText $ T.pack $ map pcToChar ws'+        Pca  -> addText $ T.pack $ map pcaToChar ws'     ControlWord "ansi" _ -> bs <$       updateState (\s -> s{ sCharSet = ANSI })+    ControlWord "ansicpg" (Just cpg) | cpg /= 1252 -> bs <$+      report (UnsupportedCodePage cpg)     ControlWord "mac" _ -> bs <$       updateState (\s -> s{ sCharSet = Mac })     ControlWord "pc" _ -> bs <$@@ -529,9 +566,8 @@     ControlSymbol '~' -> bs <$ addText "\x00a0"     ControlSymbol '-' -> bs <$ addText "\x00ad"     ControlSymbol '_' -> bs <$ addText "\x2011"-    ControlWord "trowd" _ -> bs <$ do -- add new row-      updateState $ \s -> s{ sTableRows = TableRow [] : sTableRows s-                           , sCurrentCell = mempty }+    ControlWord "trowd" _ -> bs <$ beginTableRow -- begin new row+    ControlWord "row" _ -> bs <$ beginTableRow -- end current row     ControlWord "cell" _ -> bs <$ do       new <- emitBlocks mempty       curCell <- (<> new) . sCurrentCell <$> getState@@ -541,9 +577,10 @@                                     TableRow (curCell : cs) : rs                                   [] -> [TableRow [curCell]] -- shouldn't happen                            , sCurrentCell = mempty }-    ControlWord "intbl" _ ->-      emitBlocks bs <* modifyGroup (\g -> g{ gInTable = True })-    ControlWord "plain" _ -> bs <$ modifyGroup (const def)+    ControlWord "intbl" _ -> do+      ls <- closeLists 0 -- see #11364+      ((ls <>) <$> emitBlocks bs) <* modifyGroup (\g -> g{ gInTable = True })+    ControlWord "plain" _ -> bs <$ modifyGroup resetCharProps     ControlWord "lquote" _ -> bs <$ addText "\x2018"     ControlWord "rquote" _ -> bs <$ addText "\x2019"     ControlWord "ldblquote" _ -> bs <$ addText "\x201C"@@ -610,9 +647,10 @@       modifyGroup (\g -> g{ gUnderline = boolParam mbp })     ControlWord "ulnone" _ -> bs <$       modifyGroup (\g -> g{ gUnderline = False })-    ControlWord "pard" _ -> bs <$ do+    ControlWord "pard" _ -> do+      newbs <- emitBlocks bs       modifyGroup (const def)-      getStyleFormatting 0 >>= foldM processTok bs+      getStyleFormatting 0 >>= foldM processTok newbs     ControlWord "par" _ -> emitBlocks bs     _ -> pure bs @@ -654,6 +692,19 @@           closeLists lvl     _ -> pure mempty +-- Begin a new table row.  Both @\\trowd@ (which sets row defaults) and+-- @\\row@ (which ends a row) start a fresh row to be filled by subsequent+-- @\\cell@s.  We only push a new empty row when the current one already has+-- cells, so that documents repeating @\\trowd@ after @\\row@ (or omitting+-- @\\trowd@ between rows) both produce the same flat structure.+beginTableRow :: PandocMonad m => RTFParser m ()+beginTableRow =+  updateState $ \s ->+    s{ sTableRows = case sTableRows s of+                      TableRow [] : _ -> sTableRows s+                      rs -> TableRow [] : rs+     , sCurrentCell = mempty }+ closeTable :: PandocMonad m => RTFParser m Blocks closeTable = do   rawrows <- sTableRows <$> getState@@ -661,10 +712,13 @@      then return mempty      else do        let getCells (TableRow cs) = reverse cs-       let rows = map getCells . reverse $ rawrows+       -- drop empty rows produced by row terminators+       let rows = filter (not . null) . map getCells . reverse $ rawrows        updateState $ \s -> s{ sCurrentCell = mempty                             , sTableRows = [] }-       return $ B.simpleTable [] rows+       if null rows+          then return mempty+          else return $ B.simpleTable [] rows  closeContainers :: PandocMonad m => RTFParser m Blocks closeContainers = do@@ -767,27 +821,48 @@  -- {\field{\*\fldinst{HYPERLINK "http://pandoc.org"}}{\fldrslt foo}} handleField :: PandocMonad m => Blocks -> [Tok] -> RTFParser m Blocks-handleField bs-  (Tok _-    (Grouped-     (Tok _ (ControlSymbol '*')-     :Tok _ (ControlWord "fldinst" Nothing)-     :Tok _ (Grouped (Tok _ (UnformattedText insttext):rest))-     :_))-  :linktoks)-  | Just linkdest <- getHyperlink insttext-  = do let linkdest' = case rest of-                         (Tok _ (ControlSymbol '\\')-                          : Tok _ (UnformattedText t)-                          : _) | Just bkmrk <- T.stripPrefix "l" t-                           -> "#" <> unquote bkmrk-                         _ -> linkdest-       modifyGroup $ \g -> g{ gHyperlink = Just linkdest' }-       result <- foldM processTok bs linktoks-       modifyGroup $ \g -> g{ gHyperlink = Nothing }-       return result-handleField bs _ = pure bs+handleField bs ts = do+  let isFieldMod (Tok _ (ControlWord w _)) =+        w `elem` ["flddirty", "fldedit", "fldlock", "fldpriv"]+      isFieldMod _ = False +  let instructionTokens (Tok _ (Grouped toks)) = Just toks+      instructionTokens unformattedTok@(Tok _ (UnformattedText _)) = Just [unformattedTok]+      instructionTokens _ = Nothing+  case dropWhile isFieldMod ts of+    [Tok _ (Grouped+       (Tok _ (ControlSymbol '*')+       :Tok _ (ControlWord "fldinst" Nothing)+       :instrtoks+       :_)),+     Tok _ (Grouped+       (Tok _ (ControlWord "fldrslt" Nothing)+       :resulttoks))] -> do+         case instructionTokens instrtoks of+           Nothing -> pure bs+           Just instrtoks' ->+             case getHyperlink instrtoks' of+               Just linkdest -> do+                 modifyGroup $ \g -> g{ gHyperlink = Just linkdest }+                 result <- foldM processTok bs resulttoks+                 modifyGroup $ \g -> g{ gHyperlink = Nothing }+                 return result+               Nothing -> foldM processTok bs resulttoks+    _ -> pure bs++getHyperlink :: [Tok] -> Maybe Text+getHyperlink [] = Nothing+getHyperlink (Tok _ (UnformattedText w) : rest)+  | Just w' <- unquote <$> T.stripPrefix "HYPERLINK" (T.strip w)+    = if T.null w'+         then case rest of+                (Tok _ (ControlSymbol '\\') : Tok _ (UnformattedText b) : _)+                  | Just bkmrk <- unquote <$> T.stripPrefix "l " (T.strip b)+                    -> Just $ "#" <> bkmrk+                _ -> Just mempty+         else Just w'+getHyperlink (_:ts) = getHyperlink ts+ unquote :: Text -> Text unquote = T.dropWhile (=='"') . T.dropWhileEnd (=='"') . T.strip @@ -864,7 +939,7 @@                   _ -> mempty   let isBasedOn (Tok _ (ControlWord "sbasedon" (Just _))) = True       isBasedOn _ = False-  let styBasedOn = case find isBasedOn toks of+  let styBasedOn = case L.find isBasedOn toks of                      Just (Tok _ (ControlWord "sbasedon" (Just i))) -> Just i                      _ -> Nothing   let isStyleControl (Tok _ (ControlWord x _)) =@@ -889,7 +964,7 @@  handlePict :: PandocMonad m => [Tok] -> RTFParser m () handlePict toks = do-  let pict = foldl' getPictData def toks+  let pict = L.foldl' getPictData def toks   let altText = "image"   let bytes =         if picBinary pict@@ -903,7 +978,7 @@           Nothing -> (Nothing, "")   case mimetype of     Just mt -> do-      let pictname = showDigest (sha1 bytes) <> ext+      let pictname = show (hashWith SHA1 $ BL.toStrict bytes) <> ext       insertMedia pictname (Just mt) bytes       modifyGroup $ \g -> g{ gImage = Just pict{ picName = T.pack pictname,                                                  picBytes = bytes } }@@ -927,14 +1002,8 @@       _ -> pict  -getHyperlink :: Text -> Maybe Text-getHyperlink t =-  case T.stripPrefix "HYPERLINK" (T.strip t) of-    Nothing -> Nothing-    Just rest -> Just $ unquote rest- processFontTable :: [Tok] -> FontTable-processFontTable = snd . foldl' go (0, mempty)+processFontTable = snd . L.foldl' go (0, mempty)  where   go (fontnum, tbl) (Tok _ tok') =     case tok' of@@ -947,42 +1016,41 @@      (ControlWord "fdecor" _) -> (fontnum, IntMap.insert fontnum Decor tbl)      (ControlWord "ftech" _) -> (fontnum, IntMap.insert fontnum Tech tbl)      (ControlWord "fbidi" _) -> (fontnum, IntMap.insert fontnum Bidi tbl)-     (Grouped ts) -> foldl' go (fontnum, tbl) ts+     (Grouped ts) -> L.foldl' go (fontnum, tbl) ts      _ -> (fontnum, tbl) --ansiToChar :: Word8 -> Char-ansiToChar i = chr $+defaultAnsiWordToChar :: Word8 -> Char+defaultAnsiWordToChar i =   case i of-    128 -> 8364-    130 -> 8218-    131 -> 402-    132 -> 8222-    133 -> 8230-    134 -> 8224-    135 -> 8225-    136 -> 710-    137 -> 8240-    138 -> 352-    139 -> 8249-    140 -> 338-    142 -> 381-    145 -> 8216-    146 -> 8217-    147 -> 8220-    148 -> 8221-    149 -> 8226-    150 -> 8211-    151 -> 8212-    152 -> 732-    153 -> 8482-    154 -> 353-    155 -> 8250-    156 -> 339-    158 -> 382-    159 -> 376-    173 -> 0xAD-    _ -> fromIntegral i+    128 -> '\8364'+    130 -> '\8218'+    131 -> '\402'+    132 -> '\8222'+    133 -> '\8230'+    134 -> '\8224'+    135 -> '\8225'+    136 -> '\710'+    137 -> '\8240'+    138 -> '\352'+    139 -> '\8249'+    140 -> '\338'+    142 -> '\381'+    145 -> '\8216'+    146 -> '\8217'+    147 -> '\8220'+    148 -> '\8221'+    149 -> '\8226'+    150 -> '\8211'+    151 -> '\8212'+    152 -> '\732'+    153 -> '\8482'+    154 -> '\353'+    155 -> '\8250'+    156 -> '\339'+    158 -> '\382'+    159 -> '\376'+    173 -> '\xAD'+    _ -> chr (fromIntegral i)  macToChar :: Word8 -> Char macToChar i = chr $
src/Text/Pandoc/Readers/Roff.hs view
@@ -2,6 +2,7 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE TypeFamilies #-} {- |    Module      : Text.Pandoc.Readers.Roff    Copyright   : Copyright (C) 2018-2020 Yan Pashkovsky and John MacFarlane@@ -29,11 +30,11 @@ where  import Safe (lastDef)-import Control.Monad (void, mzero, mplus, guard)+import Control.Monad (void, guard) import Control.Monad.Except (throwError) import Text.Pandoc.Class.PandocMonad        (getResourcePath, readFileFromDirs, PandocMonad(..), report)-import Data.Char (isLower, toLower, toUpper, chr, isAscii, isAlphaNum)+import Data.Char (isLower, toLower, toUpper, isAlphaNum) import Data.Default (Default) import qualified Data.Map as M import Data.List (intercalate)@@ -42,10 +43,9 @@ import Text.Pandoc.Options import Text.Pandoc.Parsing import Text.Pandoc.Shared (safeRead)-import Text.Pandoc.RoffChar (characterCodes, combiningAccents)+import Text.Pandoc.Readers.Roff.Escape import qualified Data.Sequence as Seq import qualified Data.Foldable as Foldable-import qualified Data.Text.Normalize as Normalize  -- import Debug.Trace (traceShowId) @@ -65,6 +65,59 @@               | MacroArg Int               deriving Show +instance RoffLikeLexer RoffTokens where+  -- The token stream is a list of 'LinePart's+  type Token RoffTokens = [LinePart]+  type State RoffTokens = RoffState+  emit t = [RoffStr t]+  expandString = try $ do+    pos <- getPosition+    char '\\'+    char '*'+    cs <- escapeArg <|> countChar 1 anyChar+    s <- linePartsToText <$> resolveText cs pos+    addToInput s+  escString = try $ do+    pos <- getPosition+    (do cs <- escapeArg <|> countChar 1 anyChar+        resolveText cs pos)+      <|> mempty <$ char 'S'+  backslash = do+    char '\\'+    mode <- roffMode <$> getState+    case mode of+      -- experimentally, it seems you don't always need to double+      -- the backslash in macro defs.  It's essential with \\$1,+      -- but not with \\f[I].  So we make the second one optional.+      CopyMode   -> optional $ char '\\'+      NormalMode -> return ()+  checkDefined name = do+    macros <- customMacros <$> getState+    case M.lookup name macros of+      Just _  -> return [RoffStr "1"]+      Nothing -> return [RoffStr "0"]+  -- \E is ignored in copy mode+  escE = do+      mode <- roffMode <$> getState+      case mode of+        CopyMode   -> return mempty+        NormalMode -> return [RoffStr "\\"]+  escFont = do+    font <- escapeArg <|> countChar 1 alphaNum+    font' <- if T.null font || font == "P"+                then prevFont <$> getState+                else return $ foldr processFontLetter defaultFontSpec $ T.unpack font+    updateState $ \st -> st{ prevFont = currentFont st+                           , currentFont = font' }+    return [Font font']+    where+      processFontLetter c fs+                | isLower c    = processFontLetter (toUpper c) fs+      processFontLetter 'B' fs = fs{ fontBold = True }+      processFontLetter 'I' fs = fs{ fontItalic = True }+      processFontLetter 'C' fs = fs{ fontMonospace = True }+      processFontLetter _   fs = fs -- do nothing+ type Arg = [LinePart]  type TableOption = (T.Text, T.Text)@@ -133,198 +186,6 @@ spacetab :: (Stream s m Char, UpdateSourcePos s Char) => ParsecT s u m Char spacetab = char ' ' <|> char '\t' -characterCodeMap :: M.Map T.Text Char-characterCodeMap =-  M.fromList $ map (\(x,y) -> (y,x)) characterCodes--combiningAccentsMap :: M.Map T.Text Char-combiningAccentsMap =-  M.fromList $ map (\(x,y) -> (y,x)) combiningAccents--escape :: PandocMonad m => RoffLexer m [LinePart]-escape = try $ do-  backslash-  escapeGlyph <|> escapeNormal--escapeGlyph :: PandocMonad m => RoffLexer m [LinePart]-escapeGlyph = do-  c <- lookAhead (oneOf ['[','('])-  escapeArg >>= resolveGlyph c--resolveGlyph :: PandocMonad m => Char -> T.Text -> RoffLexer m [LinePart]-resolveGlyph delimChar glyph = do-  let cs = T.replace "_u" " u" glyph -- unicode glyphs separated by _-  (case T.words cs of-      []  -> mzero-      [s] -> case M.lookup s characterCodeMap `mplus` readUnicodeChar s of-               Nothing -> mzero-               Just c  -> return [RoffStr $ T.singleton c]-      (s:ss) -> do-        basechar <- case M.lookup s characterCodeMap `mplus`-                         readUnicodeChar s of-                      Nothing ->-                        case T.unpack s of-                          [ch] | isAscii ch && isAlphaNum ch ->-                                 return ch-                          _ -> mzero-                      Just c  -> return c-        let addAccents [] xs = return $ Normalize.normalize Normalize.NFC $-                                        T.reverse xs-            addAccents (a:as) xs =-              case M.lookup a combiningAccentsMap `mplus` readUnicodeChar a of-                Just x  -> addAccents as $ T.cons x xs-                Nothing -> mzero-        addAccents ss (T.singleton basechar) >>= \xs -> return [RoffStr xs])-      <|> case delimChar of-            '['  -> escUnknown ("\\[" <> glyph <> "]")-            '('  -> escUnknown ("\\(" <> glyph)-            '\'' -> escUnknown ("\\C'" <> glyph <> "'")-            _    -> Prelude.fail "resolveGlyph: unknown glyph delimiter"--readUnicodeChar :: T.Text -> Maybe Char-readUnicodeChar t = case T.uncons t of-  Just ('u', cs) | T.length cs > 3 -> chr <$> safeRead ("0x" <> cs)-  _ -> Nothing--escapeNormal :: PandocMonad m => RoffLexer m [LinePart]-escapeNormal = do-  c <- noneOf "{}"-  optional expandString-  case c of-    ' ' -> return [RoffStr " "]-    '"' -> mempty <$ skipMany (satisfy (/='\n')) -- line comment-    '#' -> mempty <$ manyTill anyChar newline-    '%' -> return mempty  -- optional hyphenation-    '&' -> return mempty  -- nonprintable zero-width-    ')' -> return mempty  -- nonprintable zero-width-    '*' -> escString-    ',' -> return mempty  -- to fix spacing after roman-    '-' -> return [RoffStr "-"]-    '.' -> return [RoffStr "."]-    '/' -> return mempty  -- to fix spacing before roman-    '0' -> return [RoffStr "\x2007"] -- digit-width space-    ':' -> return mempty  -- zero-width break-    'A' -> quoteArg >>= checkDefined-    'B' -> escIgnore 'B' [quoteArg]-    'C' -> quoteArg >>= resolveGlyph '\''-    'D' -> escIgnore 'D' [quoteArg]-    'E' -> do-      mode <- roffMode <$> getState-      case mode of-        CopyMode   -> return mempty-        NormalMode -> return [RoffStr "\\"]-    'H' -> escIgnore 'H' [quoteArg]-    'L' -> escIgnore 'L' [quoteArg]-    'M' -> escIgnore 'M' [escapeArg, countChar 1 (satisfy (/='\n'))]-    'N' -> escIgnore 'N' [quoteArg]-    'O' -> escIgnore 'O' [countChar 1 (oneOf ['0','1'])]-    'R' -> escIgnore 'R' [quoteArg]-    'S' -> escIgnore 'S' [quoteArg]-    'V' -> escIgnore 'V' [escapeArg, countChar 1 alphaNum]-    'X' -> escIgnore 'X' [quoteArg]-    'Y' -> escIgnore 'Y' [escapeArg, countChar 1 (satisfy (/='\n'))]-    'Z' -> escIgnore 'Z' [quoteArg]-    '\'' -> return [RoffStr "'"]-    '\n' -> return mempty  -- line continuation-    '^' -> return [RoffStr "\x200A"] -- 1/12 em space-    '_' -> return [RoffStr "_"]-    '`' -> return [RoffStr "`"]-    'a' -> return mempty  -- "non-interpreted leader character"-    'b' -> escIgnore 'b' [quoteArg]-    'c' -> return mempty  -- interrupt text processing-    'd' -> escIgnore 'd' [] -- forward down 1/2em-    'e' -> return [RoffStr "\\"]-    'f' -> escFont-    'g' -> escIgnore 'g' [escapeArg, countChar 1 (satisfy (/='\n'))]-    'h' -> escIgnore 'h' [quoteArg]-    'k' -> escIgnore 'k' [escapeArg, countChar 1 (satisfy (/='\n'))]-    'l' -> escIgnore 'l' [quoteArg]-    'm' -> escIgnore 'm' [escapeArg, countChar 1 (satisfy (/='\n'))]-    'n' -> escIgnore 'm' [escapeArg, countChar 1 (satisfy (/='\n'))]-    'o' -> escIgnore 'o' [quoteArg]-    'p' -> escIgnore 'p' []-    'r' -> escIgnore 'r' []-    's' -> escIgnore 's' [escapeArg, signedNumber]-    't' -> return [RoffStr "\t"]-    'u' -> escIgnore 'u' []-    'v' -> escIgnore 'v' [quoteArg]-    'w' -> escIgnore 'w' [quoteArg]-    'x' -> escIgnore 'x' [quoteArg]-    'z' -> escIgnore 'z' [countChar 1 anyChar]-    '|' -> return [RoffStr "\x2006"] --1/6 em space-    '~' -> return [RoffStr "\160"] -- nonbreaking space-    '\\' -> do-      mode <- roffMode <$> getState-      case mode of-        CopyMode   -> char '\\'-        NormalMode -> return '\\'-      return [RoffStr "\\"]-    _   -> return [RoffStr $ T.singleton c]-    -- man 7 groff: "If  a  backslash  is followed by a character that-    -- does not constitute a defined escape sequence, the backslash-    -- is  silently  ignored  and  the character maps to itself."--escIgnore :: PandocMonad m-          => Char-          -> [RoffLexer m T.Text]-          -> RoffLexer m [LinePart]-escIgnore c argparsers = do-  pos <- getPosition-  arg <- snd <$> withRaw (choice argparsers) <|> return ""-  report $ SkippedContent ("\\" <> T.cons c arg) pos-  return mempty--escUnknown :: PandocMonad m => T.Text -> RoffLexer m [LinePart]-escUnknown s = do-  pos <- getPosition-  report $ SkippedContent s pos-  return [RoffStr "\xFFFD"]--signedNumber :: PandocMonad m => RoffLexer m T.Text-signedNumber = try $ do-  sign <- option "" ("-" <$ char '-' <|> "" <$ char '+')-  ds <- many1Char digit-  return (sign <> ds)---- Parses: [..] or (..-escapeArg :: PandocMonad m => RoffLexer m T.Text-escapeArg = choice-    [ char '[' *> optional expandString *>-                  manyTillChar (noneOf ['\n',']']) (char ']')-    , char '(' *> optional expandString *>-                  countChar 2 (satisfy (/='\n'))-    ]--expandString :: PandocMonad m => RoffLexer m ()-expandString = try $ do-  pos <- getPosition-  char '\\'-  char '*'-  cs <- escapeArg <|> countChar 1 anyChar-  s <- linePartsToText <$> resolveText cs pos-  addToInput s---- Parses: '..'-quoteArg :: PandocMonad m => RoffLexer m T.Text-quoteArg = char '\'' *> manyTillChar (noneOf ['\n','\'']) (char '\'')--escFont :: PandocMonad m => RoffLexer m [LinePart]-escFont = do-  font <- escapeArg <|> countChar 1 alphaNum-  font' <- if T.null font || font == "P"-              then prevFont <$> getState-              else return $ foldr processFontLetter defaultFontSpec $ T.unpack font-  updateState $ \st -> st{ prevFont = currentFont st-                         , currentFont = font' }-  return [Font font']-  where-    processFontLetter c fs-              | isLower c    = processFontLetter (toUpper c) fs-    processFontLetter 'B' fs = fs{ fontBold = True }-    processFontLetter 'I' fs = fs{ fontItalic = True }-    processFontLetter 'C' fs = fs{ fontMonospace = True }-    processFontLetter _   fs = fs -- do nothing- -- separate function from lexMacro since real man files sometimes do not -- follow the rules lexComment :: PandocMonad m => RoffLexer m RoffTokens@@ -407,7 +268,8 @@     manyTill anyChar (try (string "T}"))   simpleCell = do     tabChar <- tableTabChar <$> getState-    many (notFollowedBy (char tabChar <|> newline) >> anyChar)+    many $ (char '\\' >> anyChar)+       <|> (notFollowedBy (char tabChar <|> newline) >> anyChar)  tableRow :: PandocMonad m => RoffLexer m [RoffTokens] tableRow = do@@ -624,20 +486,6 @@         char '"'         return [RoffStr "\""] -checkDefined :: PandocMonad m => T.Text -> RoffLexer m [LinePart]-checkDefined name = do-  macros <- customMacros <$> getState-  case M.lookup name macros of-    Just _  -> return [RoffStr "1"]-    Nothing -> return [RoffStr "0"]--escString :: PandocMonad m => RoffLexer m [LinePart]-escString = try $ do-  pos <- getPosition-  (do cs <- escapeArg <|> countChar 1 anyChar-      resolveText cs pos)-    <|> mempty <$ char 'S'- -- strings and macros share namespace resolveText :: PandocMonad m               => T.Text -> SourcePos -> RoffLexer m [LinePart]@@ -667,17 +515,6 @@ linePart :: PandocMonad m => RoffLexer m [LinePart] linePart = macroArg <|> escape <|>            regularText <|> quoteChar <|> spaceTabChar--backslash :: PandocMonad m => RoffLexer m ()-backslash = do-  char '\\'-  mode <- roffMode <$> getState-  case mode of-    -- experimentally, it seems you don't always need to double-    -- the backslash in macro defs.  It's essential with \\$1,-    -- but not with \\f[I].  So we make the second one optional.-    CopyMode   -> optional $ char '\\'-    NormalMode -> return ()  macroArg :: PandocMonad m => RoffLexer m [LinePart] macroArg = try $ do
+ src/Text/Pandoc/Readers/Roff/Escape.hs view
@@ -0,0 +1,222 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilyDependencies #-}+module Text.Pandoc.Readers.Roff.Escape+  ( escape,+    escapeArg,+    escIgnore,+    RoffLikeLexer(..),+  )+where+import Text.Pandoc.Class.PandocMonad+    ( PandocMonad(..), report, PandocMonad(..), report )+import Control.Monad+    ( mzero, mplus, mzero, mplus )+import Data.Char (chr, isAscii, isAlphaNum)+import qualified Data.Map as M+import qualified Data.Text as T+import Text.Pandoc.Logging (LogMessage(..))+import Text.Pandoc.Parsing+import Text.Pandoc.Shared (safeRead)+import qualified Data.Text.Normalize as Normalize+import Text.Pandoc.RoffChar (characterCodes, combiningAccents)++-- | Functions and typeclass for escaping special characters in languages+-- that inherit the Roff syntax.+--+-- For various reasons, the mdoc reader doesn't directly reuse the previously+-- existing roff lexer. The main one is to make it possible to simultaneously+-- process roff escapes and to tokenize mdoc macros correctly based on the+-- control line contents. The extracted interface here allows the same `escape`+-- function to work with lexers that target different token types and support+-- different subsets of the original roff language.++type Lexer m x = ParsecT Sources (State x) m++-- | Lexers for Roff macro+class (Monoid (Token x)) => RoffLikeLexer x where+  -- | Type family for the lexer state+  type State x = a | a -> x+  -- | Type family for the token type being lexed+  type Token x = a | a -> x+  -- | Turn a `T.Text` into a token of the output+  emit :: T.Text -> Token x+  -- | Attempt to parse a roff predefined string sequence and push its expansion+  -- onto the input stream.+  expandString :: PandocMonad m => Lexer m x ()+  -- | Parse the name of a defined string and return its expansion as a `Token`+  escString :: PandocMonad m => Lexer m x (Token x)+  -- | Parse the escape character+  backslash :: PandocMonad m => Lexer m x ()+  -- | If the given custom macro is defined in this document, emit a+  -- tokenized "1", otherwise emit a tokenized "0", implementing the roff+  -- escape @\A@.+  checkDefined :: PandocMonad m => T.Text -> Lexer m x (Token x)+  -- | Output an appropriate token for the @\E@ escape sequence. In roff, @\E@+  -- is an "escape character intended to not be interpreted in copy mode".+  -- If the lexer being defined doesn't implement copy mode, @\E@ can just be+  -- lexed by 'backslash'+  escE :: PandocMonad m => Lexer m x (Token x)+  -- | Lex the low-level roff font selection escape @\f@.+  escFont :: PandocMonad m => Lexer m x (Token x)+++characterCodeMap :: M.Map T.Text Char+characterCodeMap =+  M.fromList $ map (\(x,y) -> (y,x)) characterCodes++combiningAccentsMap :: M.Map T.Text Char+combiningAccentsMap =+  M.fromList $ map (\(x,y) -> (y,x)) combiningAccents++escape ::  (PandocMonad m, RoffLikeLexer x) => Lexer m x (Token x)+escape = try $ do+  backslash+  escapeGlyph <|> escapeNormal++escapeGlyph :: (PandocMonad m, RoffLikeLexer x) => Lexer m x (Token x)+escapeGlyph = do+  c <- lookAhead (oneOf ['[','('])+  escapeArg >>= resolveGlyph c++resolveGlyph :: (PandocMonad m, RoffLikeLexer x) => Char -> T.Text -> Lexer m x (Token x)+resolveGlyph delimChar glyph = do+  let cs = T.replace "_u" " u" glyph -- unicode glyphs separated by _+  (case T.words cs of+      []  -> mzero+      [s] -> case M.lookup s characterCodeMap `mplus` readUnicodeChar s of+               Nothing -> mzero+               Just c  -> return $ emit $ T.singleton c+      (s:ss) -> do+        basechar <- case M.lookup s characterCodeMap `mplus`+                         readUnicodeChar s of+                      Nothing ->+                        case T.unpack s of+                          [ch] | isAscii ch && isAlphaNum ch ->+                                 return ch+                          _ -> mzero+                      Just c  -> return c+        let addAccents [] xs = return $ Normalize.normalize Normalize.NFC $+                                        T.reverse xs+            addAccents (a:as) xs =+              case M.lookup a combiningAccentsMap `mplus` readUnicodeChar a of+                Just x  -> addAccents as $ T.cons x xs+                Nothing -> mzero+        addAccents ss (T.singleton basechar) >>= \xs -> return $ emit xs)+      <|> case delimChar of+            '['  -> escUnknown ("\\[" <> glyph <> "]")+            '('  -> escUnknown ("\\(" <> glyph)+            '\'' -> escUnknown ("\\C'" <> glyph <> "'")+            _    -> Prelude.fail "resolveGlyph: unknown glyph delimiter"++readUnicodeChar :: T.Text -> Maybe Char+readUnicodeChar t = case T.uncons t of+  Just ('u', cs) | T.length cs > 3 -> chr <$> safeRead ("0x" <> cs)+  _ -> Nothing++escapeNormal :: (PandocMonad m, RoffLikeLexer x) => Lexer m x (Token x)+escapeNormal = do+  c <- noneOf "{}"+  optional expandString+  let groffSkip = [escapeArg, countChar 1 (satisfy (/='\n'))]+  case c of+    ' ' -> return $ emit " " -- mandoc_char(7) says this should be a nonbreaking space+    '"' -> mempty <$ skipMany (satisfy (/='\n')) -- line comment+    '#' -> mempty <$ manyTill anyChar newline+    '%' -> return mempty  -- optional hyphenation+    '&' -> return mempty  -- nonprintable zero-width+    ')' -> return mempty  -- nonprintable zero-width+    '*' -> escString+    ',' -> return mempty  -- to fix spacing after roman+    '-' -> return $ emit "-"+    '.' -> return $ emit "."+    '/' -> return mempty  -- to fix spacing before roman+    '0' -> return $ emit "\x2007" -- digit-width space+    ':' -> return mempty  -- zero-width break+    'A' -> quoteArg >>= checkDefined+    'B' -> escIgnore 'B' [quoteArg]+    'C' -> quoteArg >>= resolveGlyph '\''+    'D' -> escIgnore 'D' [quoteArg]+    'E' -> escE+    'F' -> escIgnore 'F' groffSkip+    'H' -> escIgnore 'H' [quoteArg]+    'L' -> escIgnore 'L' [quoteArg]+    'M' -> escIgnore 'M' groffSkip+    'N' -> escIgnore 'N' [quoteArg]+    'O' -> escIgnore 'O' [countChar 1 (oneOf ['0','1'])]+    'R' -> escIgnore 'R' [quoteArg]+    'S' -> escIgnore 'S' [quoteArg]+    'V' -> escIgnore 'V' groffSkip+    'X' -> escIgnore 'X' [quoteArg]+    'Y' -> escIgnore 'Y' groffSkip+    'Z' -> escIgnore 'Z' [quoteArg]+    '\'' -> return $ emit "'"+    '\n' -> return mempty  -- line continuation+    '^' -> return $ emit "\x200A" -- 1/12 em space+    '_' -> return $ emit "_"+    '`' -> return $ emit "`"+    'a' -> return mempty  -- "non-interpreted leader character"+    'b' -> escIgnore 'b' [quoteArg]+    'c' -> return mempty  -- interrupt text processing+    'd' -> escIgnore 'd' [] -- forward down 1/2em+    'e' -> return $ emit "\\"+    'f' -> escFont+    'g' -> escIgnore 'g' groffSkip+    'h' -> escIgnore 'h' [quoteArg]+    'k' -> escIgnore 'k' groffSkip+    'l' -> escIgnore 'l' [quoteArg]+    'm' -> escIgnore 'm' groffSkip+    'n' -> escIgnore 'm' groffSkip+    'o' -> escIgnore 'o' [quoteArg]+    'p' -> escIgnore 'p' []+    'r' -> escIgnore 'r' []+    's' -> escIgnore 's' [escapeArg, signedNumber]+    't' -> return $ emit "\t"+    'u' -> escIgnore 'u' []+    'v' -> escIgnore 'v' [quoteArg]+    'w' -> escIgnore 'w' [quoteArg]+    'x' -> escIgnore 'x' [quoteArg]+    'z' -> escIgnore 'z' [countChar 1 anyChar]+    '|' -> return $ emit "\x2006" --1/6 em space+    '~' -> return $ emit "\160" -- nonbreaking space+    '\\' -> return $ emit "\\"+    _   -> return $ emit $ T.singleton c+    -- man 7 groff: "If  a  backslash  is followed by a character that+    -- does not constitute a defined escape sequence, the backslash+    -- is  silently  ignored  and  the character maps to itself."++escIgnore :: (PandocMonad m, RoffLikeLexer x)+          => Char+          -> [Lexer m x T.Text]+          -> Lexer m x (Token x)+escIgnore c argparsers = do+  pos <- getPosition+  arg <- snd <$> withRaw (choice argparsers) <|> return ""+  report $ SkippedContent ("\\" <> T.cons c arg) pos+  return mempty++escUnknown :: (PandocMonad m, RoffLikeLexer x) => T.Text -> Lexer m x (Token x)+escUnknown s = do+  pos <- getPosition+  report $ SkippedContent s pos+  return $ emit "\xFFFD"++signedNumber :: (PandocMonad m, RoffLikeLexer x) => Lexer m x T.Text+signedNumber = try $ do+  sign <- option "" ("-" <$ char '-' <|> "" <$ char '+')+  ds <- many1Char digit+  return (sign <> ds)++-- Parses: [..] or (..+escapeArg :: (PandocMonad m, RoffLikeLexer x) => Lexer m x T.Text+escapeArg = choice+    [ char '[' *> optional expandString *>+                  manyTillChar (noneOf ['\n',']']) (char ']')+    , char '(' *> optional expandString *>+                  countChar 2 (satisfy (/='\n'))+    ]++-- Parses: '..'+quoteArg :: (PandocMonad m, RoffLikeLexer x) => Lexer m x T.Text+quoteArg = char '\'' *> manyTillChar (noneOf ['\n','\'']) (char '\'')
src/Text/Pandoc/Readers/TWiki.hs view
@@ -16,7 +16,7 @@  import Control.Monad import Control.Monad.Except (throwError)-import Data.Char (isAlphaNum)+import Data.Char (isAlphaNum, isDigit, isUpper, isLower, isLetter) import qualified Data.Foldable as F import Data.Maybe (fromMaybe) import Data.Text (Text)@@ -222,9 +222,11 @@                               (TableHead nullAttr $ toHeaderRow heads)                               [TableBody nullAttr 0 [] $ map toRow rows]                               (TableFoot nullAttr [])-    align rows      = replicate (columCount rows) (AlignDefault, ColWidthDefault)-    columns rows    = replicate (columCount rows) mempty-    columCount rows = length $ head rows+    align rows      = replicate (columnCount rows)+                         (AlignDefault, ColWidthDefault)+    columns rows    = replicate (columnCount rows) mempty+    columnCount (r:_) = length r+    columnCount []  = 0     toRow           = Row nullAttr . map B.simpleCell     toHeaderRow l = [toRow l | not (null l)] @@ -467,17 +469,29 @@   st <- getState   guard $ stateAllowLinks st   setState $ st{ stateAllowLinks = False }-  (url, title, content) <- linkText+  (url, title, classes, content) <- linkText <|> simpleWikiLink   setState $ st{ stateAllowLinks = True }-  return $ B.link url title content+  return $ B.linkWith ("",classes,[]) url title content -linkText :: PandocMonad m => TWParser m (Text, Text, B.Inlines)+linkText :: PandocMonad m => TWParser m (Text, Text, [Text], B.Inlines) linkText = do   string "[["   url <- T.pack <$> many1Till anyChar (char ']')   content <- option (B.str url) (mconcat <$> linkContent)   char ']'-  return (url, "", content)+  return (url, "", [], content)   where     linkContent      = char '[' >> many1Till anyChar (char ']') >>= parseLinkContent . T.pack     parseLinkContent = parseFromString' $ many1 inline++simpleWikiLink :: PandocMonad m => TWParser m (Text, Text, [Text], B.Inlines)+simpleWikiLink = do+  w <- wikiWord+  return (w, "", ["wikilink"], B.str w)+ where+   wikiWord = do+     cs <- many1 $ satisfy (\x -> isLetter x && isUpper x)+     ds <- many1 $ satisfy (\x -> isDigit x || (isLetter x && isLower x))+     es <- many1 $ satisfy (\x -> isLetter x && isUpper x)+     fs <- many $ satisfy isAlphaNum+     return $ T.pack $ cs ++ ds ++ es ++ fs
src/Text/Pandoc/Readers/Textile.hs view
@@ -3,7 +3,7 @@ {- |    Module      : Text.Pandoc.Readers.Textile    Copyright   : Copyright (C) 2010-2012 Paul Rivier-                               2010-2023 John MacFarlane+                               2010-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : Paul Rivier <paul*rivier#demotera*com>@@ -38,7 +38,8 @@ import Control.Monad (guard, liftM) import Control.Monad.Except (throwError) import Data.Char (digitToInt, isUpper)-import Data.List (intersperse, transpose, foldl')+import Data.List (intersperse, transpose)+import qualified Data.List as L import Data.List.NonEmpty (NonEmpty(..), nonEmpty) import qualified Data.Map as M import Data.Text (Text)@@ -412,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)]@@ -501,6 +506,7 @@                 , endline                 , code                 , escapedInline+                , spanGroup                 , inlineMarkup                 , groupedInlineMarkup                 , rawHtmlInline@@ -525,9 +531,21 @@                       , simpleInline (char '-' <* notFollowedBy (char '-')) B.strikeout                       , simpleInline (char '^') B.superscript                       , simpleInline (char '~') B.subscript-                      , simpleInline (char '%') id                       ] +-- "The <span> tag is created by percent % signs between whitespaces."+-- e.g. My mother has %{color:green;}green% eyes.+spanGroup :: PandocMonad m => TextileParser m Inlines+spanGroup = try $ do+  notAfterString >>= guard+  char '%' *> notFollowedBy whitespace+  attr <- option nullAttr attributes+  contents <- mconcat <$> manyTill+   (try (((B.space <>) <$> try (whitespace *> notFollowedBy newline *> inline))+         <|> try (notFollowedBy newline *> inline)))+   (try (char '%' <* lookAhead (newline <|> ' ' <$ whitespace)))+  pure $ B.spanWith attr contents+ -- | Trademark, registered, copyright mark :: PandocMonad m => TextileParser m Inlines mark = try $ char '(' >> (try tm <|> try reg <|> copy)@@ -685,9 +703,12 @@  -- | Any special symbol defined in wordBoundaries symbol :: PandocMonad m => TextileParser m Inlines-symbol = B.str . T.singleton <$> (notFollowedBy newline *>-                                  notFollowedBy rawHtmlBlock *>-                                  oneOf wordBoundaries)+symbol = do+  c <- notFollowedBy newline *>+         notFollowedBy rawHtmlBlock *>+         oneOf wordBoundaries+  updateLastStrPos+  pure $ B.str . T.singleton $ c  -- | Inline code code :: PandocMonad m => TextileParser m Inlines@@ -716,7 +737,7 @@  -- | Html / CSS attributes attributes :: PandocMonad m => TextileParser m Attr-attributes = foldl' (flip ($)) ("",[],[]) <$>+attributes = L.foldl' (flip ($)) ("",[],[]) <$>   try (do special <- option id specialAttribute           attrs <- many attribute           return (special : attrs))@@ -775,12 +796,14 @@              -> (Inlines -> Inlines)                  -- ^ Inline constructor              -> TextileParser m Inlines  -- ^ content parser (to be used repeatedly) simpleInline border construct = try $ do-  notAfterString+  notAfterString >>= guard   border *> notFollowedBy (oneOf " \t\n\r")   attr <- attributes   body <- trimInlines . mconcat <$>           withQuoteContext InSingleQuote-            (manyTill (notFollowedBy newline >> inline)+            (manyTill (((B.space <>) <$>+                         try (whitespace *> notFollowedBy newline >> inline))+                     <|> try (notFollowedBy newline >> inline))              (try border <* notFollowedBy alphaNum))   return $ construct $         if attr == nullAttr
src/Text/Pandoc/Readers/TikiWiki.hs view
@@ -24,8 +24,7 @@ import Data.Text (Text) import qualified Data.Text as T import qualified Text.Pandoc.Builder as B-import Text.Pandoc.Class.CommonState (CommonState (..))-import Text.Pandoc.Class.PandocMonad (PandocMonad (..))+import Text.Pandoc.Class.PandocMonad (PandocMonad (..), getVerbosity) import Text.Pandoc.Definition import Text.Pandoc.Logging (Verbosity (..)) import Text.Pandoc.Options@@ -71,7 +70,7 @@  block :: PandocMonad m => TikiWikiParser m B.Blocks block = do-  verbosity <- getsCommonState stVerbosity+  verbosity <- getVerbosity   pos <- getPosition   res <- mempty <$ skipMany1 blankline          <|> blockElements@@ -157,8 +156,9 @@   return $ B.simpleTable (headers rows) rows   where     -- The headers are as many empty strings as the number of columns-    -- in the first row-    headers rows = replicate (length $ head rows) ((B.plain . B.str) "")+-- in the first row+    headers [] = []+    headers (r:_) = replicate (length r) ((B.plain . B.str) "")  para :: PandocMonad m => TikiWikiParser m B.Blocks para =  fmap (result . mconcat) ( many1Till inline endOfParaElement)@@ -226,10 +226,9 @@ -- fixListNesting nestall | trace ("\n\nfixListNesting: " ++ (show nestall)) False = undefined -- fixListNesting nestall@(first:second:rest) = fixListNesting (first:second:rest) =-  let secondBlock = head $ B.toList second in-    case secondBlock of-      BulletList _ -> fixListNesting $ mappend (recurseOnList first) (recurseOnList second) : rest-      OrderedList _ _ -> fixListNesting $ mappend (recurseOnList first) (recurseOnList second) : rest+    case B.toList second of+      (BulletList _ : _) -> fixListNesting $ mappend (recurseOnList first) (recurseOnList second) : rest+      (OrderedList _ _ : _) -> fixListNesting $ mappend (recurseOnList first) (recurseOnList second) : rest       _ -> recurseOnList first : fixListNesting (second:rest)  -- This function walks the Block structure for fixListNesting,@@ -239,10 +238,9 @@ -- recurseOnList item | trace ("rOL: " ++ (show $ length $ B.toList item) ++ ", " ++ (show $ B.toList item)) False = undefined recurseOnList items   | length (B.toList items) == 1 =-    let itemBlock = head $ B.toList items in-      case itemBlock of-        BulletList listItems -> B.bulletList $ fixListNesting $ map B.fromList listItems-        OrderedList _ listItems -> B.orderedList $ fixListNesting $ map B.fromList listItems+      case B.toList items of+        (BulletList listItems : _) -> B.bulletList $ fixListNesting $ map B.fromList listItems+        (OrderedList _ listItems : _) -> B.orderedList $ fixListNesting $ map B.fromList listItems         _ -> items    -- The otherwise works because we constructed the blocks, and we
src/Text/Pandoc/Readers/Typst.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE RankNTypes #-}+{-# LANGUAGE BangPatterns #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE OverloadedStrings #-}@@ -28,12 +29,14 @@ 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)+import Data.Maybe (catMaybes, fromMaybe, isJust) import Data.Sequence (Seq) import qualified Data.Sequence as Seq import qualified Data.Set as Set@@ -50,13 +53,14 @@ import Typst.Methods (formatNumber, applyPureFunction) import Typst.Types import qualified Data.Vector as V---- import Debug.Trace+import System.FilePath (takeDirectory)+import qualified System.FilePath.Windows as Windows+import qualified System.FilePath.Posix as Posix  -- | Read Typst from an input string and return a Pandoc document. readTypst :: (PandocMonad m, ToSources a)            => ReaderOptions -> a -> m Pandoc-readTypst _opts inp = do+readTypst opts inp = do   let sources = toSources inp   let inputName = case sources of         Sources ((pos, _):_) -> sourceName pos@@ -69,13 +73,14 @@                   currentUTCTime = getCurrentTime,                   lookupEnvVar = fmap (fmap T.unpack) . lookupEnv . T.pack,                   checkExistence = fileExists }-      res <- evaluateTypst ops inputName parsed+      res <- evaluateTypst ops (readerTypstInputs opts) inputName parsed       case res of         Left e -> throwError $ PandocParseError $ tshow e         Right content -> do-          let labs = findLabels [content]+          let content' = fixNesting content+          let labs = findLabels [content']           runParserT pPandoc defaultPState{ sLabels = labs }-            inputName [content] >>=+            inputName [content'] >>=               either (throwError . PandocParseError . T.pack . show) pure  pBlockElt :: PandocMonad m => P m B.Blocks@@ -90,7 +95,7 @@           ignored ("unknown block element " <> tname <>                    " at " <> tshow pos)           pure mempty-        Just handler -> handler mbident fields+        Just handler -> handler pos mbident fields     _ -> pure mempty  pInline :: PandocMonad m => P m B.Inlines@@ -105,8 +110,10 @@           B.math . writeTeX <$> pMathMany (Seq.singleton res)     Elt name@(Identifier tname) pos fields -> do       labs <- sLabels <$> getState-      labelTarget <- (do VLabel t <- getField "target" fields-                         True <$ guard (t `elem` labs))+      labelTarget <- (do result <- getField "target" fields+                         case result of+                           VLabel t | t `elem` labs -> pure True+                           _ -> pure False)                   <|> pure False       if tname == "ref" && not labelTarget          then do@@ -118,52 +125,70 @@                ignored ("unknown inline element " <> tname <>                         " at " <> tshow pos)                pure mempty-             Just handler -> handler Nothing (M.mapKeys targetToKey fields)+             Just handler -> handler pos Nothing (M.mapKeys targetToKey fields)          else do           case M.lookup name inlineHandlers of             Nothing -> do               ignored ("unknown inline element " <> tname <>                        " at " <> tshow pos)               pure mempty-            Just handler -> handler Nothing fields+            Just handler -> handler pos Nothing fields +-- Pull block elements out of inline elements, e.g.+-- Elt "smallcaps" [ Elt "heading" [..] ] ->+-- Elt "heading" [ Elt "smallcaps" [..]]. See #11017.+fixNesting :: Content -> Content+fixNesting el@(Elt name pos fields)+  | Just (VContent elts) <- M.lookup "body" fields+  = let elts' = fmap fixNesting elts+        fields' = M.insert "body" (VContent elts') fields+        in if isBlock el+              then Elt name pos fields'+              else case getField "body" fields' of+                        Just ([el'@(Elt name' pos' fields'')] :: Seq Content)+                          | isBlock el'+                          , not (isInline el')+                          , "body" `M.member` fields''+                          -> Elt name' pos' $+                               M.insert "body" (VContent+                                                (Seq.singleton+                                                  (Elt name pos fields'')))+                                        fields'+                        _ -> Elt name pos fields'+fixNesting x = x+ pPandoc :: PandocMonad m => P m B.Pandoc pPandoc = do   Elt "document" _ fields <- pTok isDocument   bs <- getField "body" fields >>= pWithContents pBlocks-  pure $ B.doc bs-  -- The following alternative code would add metadata from the-  -- fields on the document element. It is commented out because-  -- the typst metadata doesn't print anything by default, in contrast-  -- to pandoc with its usual templates.  Hence, with this code,-  -- converting a typst document might yield a double title, author, etc.-  ---  -- title <- (getField "title" fields >>= pWithContents pInlines) <|>-  --             pure mempty-  -- authors <- (getField "author" fields >>=-  --                         mapM (pWithContents pInlines) . V.toList) <|>-  --            ((:[]) <$> (getField "author" fields >>=-  --                          (\x -> guard (not (null x)) *>-  --                            pWithContents pInlines x))) <|>-  --             pure []-  -- date <- (getField "date" fields >>= pWithContents pInlines) <|>-  --             pure mempty-  -- keywords <- (getField "keywords" fields >>=-  --                mapM (pWithContents pInlines) . V.toList)-  --               <|> pure []-  -- pure $-  --   (if title == mempty-  --       then id-  --       else B.setMeta "title" title) .-  --   (if null authors-  --       then id-  --       else B.setMeta "author" authors) .-  --   (if null date-  --       then id-  --       else B.setMeta "date" date) .-  --   (if null keywords-  --       then id-  --       else B.setMeta "keywords" keywords) $ B.doc bs+  title <- (getField "title" fields >>= pWithContents pInlines) <|>+              pure mempty+  authors <- (getField "author" fields >>=+                          mapM (pWithContents pInlines) . V.toList) <|>+             ((:[]) <$> (getField "author" fields >>=+                           (\x -> guard (not (null x)) *>+                             pWithContents pInlines x))) <|>+              pure []+  date <- (getField "date" fields >>= pWithContents pInlines) <|>+              pure mempty+  keywords <- (getField "keywords" fields >>=+                 mapM (pWithContents pInlines) . V.toList)+                <|> pure []+  meta <- sMeta <$> getState+  let meta' =+        (if title == mempty || isJust (lookupMeta "title" meta)+            then id+            else B.setMeta "title" title) .+        (if null authors+            then id+            else B.setMeta "author" authors) .+        (if null date+            then id+            else B.setMeta "date" date) .+        (if null keywords+            then id+            else B.setMeta "keywords" keywords) $ meta+  pure $ Pandoc meta' (B.toList bs)  pBlocks :: PandocMonad m => P m B.Blocks pBlocks = mconcat <$> many pBlock@@ -206,43 +231,55 @@ blockKeys :: Set.Set Identifier blockKeys = Set.fromList $ M.keys   (blockHandlers :: M.Map Identifier-     (Maybe Text -> M.Map Identifier Val -> P PandocPure B.Blocks))+     (Maybe SourcePos -> Maybe Text ->+      M.Map Identifier Val -> P PandocPure B.Blocks))  inlineKeys :: Set.Set Identifier inlineKeys = Set.fromList $ M.keys   (inlineHandlers :: M.Map Identifier-     (Maybe Text -> M.Map Identifier Val -> P PandocPure B.Inlines))+     (Maybe SourcePos -> Maybe Text ->+      M.Map Identifier Val -> P PandocPure B.Inlines))  blockHandlers :: PandocMonad m =>                    M.Map Identifier-                   (Maybe Text -> M.Map Identifier Val -> P m B.Blocks)+                   (Maybe SourcePos -> Maybe Text ->+                    M.Map Identifier Val -> P m B.Blocks) blockHandlers = M.fromList-  [("text", \_ fields -> do+  [("text", \_ _ fields -> do       body <- getField "body" fields       -- sometimes text elements include para breaks       notFollowedBy $ void $ pWithContents pInlines body       pWithContents pBlocks body)-  ,("box", \_ fields -> do+  ,("title", \_ _ fields -> do       body <- getField "body" fields+      case body of+        VContent cs -> do+          ils <- pWithContents pInlines cs <|> pure mempty+          updateState $ \s -> s{ sMeta = B.setMeta "title" ils (sMeta s) }+          pure mempty+        _ -> pure mempty)+  ,("box", \_ _ fields -> do+      body <- getField "body" fields       B.divWith ("", ["box"], []) <$> pWithContents pBlocks body)-  ,("heading", \mbident fields -> do+  ,("heading", \_ mbident fields -> do       body <- getField "body" fields       lev <- getField "level" fields <|> pure 1       B.headerWith (fromMaybe "" mbident,[],[]) lev          <$> pWithContents pInlines body)-  ,("quote", \_ fields -> do+  ,("quote", \_ _ fields -> do       getField "block" fields >>= guard       body <- getField "body" fields >>= pWithContents pBlocks-      attribution <--        ((\x -> B.para ("\x2104\xa0" <> x)) <$>-          (getField "attribution" fields >>= pWithContents pInlines))-        <|> pure mempty+      attribution' <- getField "attribution" fields+      attribution <- if attribution' == mempty+                        then pure mempty+                        else (\x -> B.para ("\x2014\xa0" <> x)) <$>+                              (pWithContents pInlines attribution')       pure $ B.blockQuote $ body <> attribution)-  ,("list", \_ fields -> do+  ,("list", \_ _ fields -> do       children <- V.toList <$> getField "children" fields       B.bulletList <$> mapM (pWithContents pBlocks) children)-  ,("list.item", \_ fields -> getField "body" fields >>= pWithContents pBlocks)-  ,("enum", \_ fields -> do+  ,("list.item", \_ _ fields -> getField "body" fields >>= pWithContents pBlocks)+  ,("enum", \_ _ fields -> do       children <- V.toList <$> getField "children" fields       mbstart <- getField "start" fields       start <- case mbstart of@@ -271,8 +308,8 @@               _ -> (B.DefaultStyle, B.DefaultDelim)       let listAttr = (start, sty, delim)       B.orderedListWith listAttr <$> mapM (pWithContents pBlocks) children)-  ,("enum.item", \_ fields -> getField "body" fields >>= pWithContents pBlocks)-  ,("terms", \_ fields -> do+  ,("enum.item", \_ _ fields -> getField "body" fields >>= pWithContents pBlocks)+  ,("terms", \_ _ fields -> do       children <- V.toList <$> getField "children" fields       B.definitionList         <$> mapM@@ -284,38 +321,38 @@               _ -> pure (mempty, [])           )           children)-  ,("terms.item", \_ fields -> getField "body" fields >>= pWithContents pBlocks)-  ,("raw", \mbident fields -> do+  ,("terms.item", \_ _ fields -> getField "body" fields >>= pWithContents pBlocks)+  ,("raw", \_ mbident fields -> do       txt <- T.filter (/= '\r') <$> getField "text" fields       mblang <- getField "lang" fields       let attr = (fromMaybe "" mbident, maybe [] (\l -> [l]) mblang, [])       pure $ B.codeBlockWith attr txt)-  ,("parbreak", \_ _ -> pure mempty)-  ,("block", \mbident fields ->-      B.divWith (fromMaybe "" mbident, [], [])+  ,("parbreak", \_ _ _ -> pure mempty)+  ,("block", \_ mbident fields ->+      maybe id (\ident -> B.divWith (ident, [], [])) mbident         <$> (getField "body" fields >>= pWithContents pBlocks))-  ,("place", \_ fields -> do+  ,("place", \_ _ fields -> do       ignored "parameters of place"       getField "body" fields >>= pWithContents pBlocks)-  ,("columns", \_ fields -> do+  ,("columns", \_ _ fields -> do       (cnt :: Integer) <- getField "count" fields       B.divWith ("", ["columns-flow"], [("count", T.pack (show cnt))])         <$> (getField "body" fields >>= pWithContents pBlocks))-  ,("rect", \_ fields ->+  ,("rect", \_ _ fields ->       B.divWith ("", ["rect"], []) <$> (getField "body" fields >>= pWithContents pBlocks))-  ,("circle", \_ fields ->+  ,("circle", \_ _ fields ->       B.divWith ("", ["circle"], []) <$> (getField "body" fields >>= pWithContents pBlocks))-  ,("ellipse", \_ fields ->+  ,("ellipse", \_ _ fields ->       B.divWith ("", ["ellipse"], []) <$> (getField "body" fields >>= pWithContents pBlocks))-  ,("polygon", \_ fields ->+  ,("polygon", \_ _ fields ->       B.divWith ("", ["polygon"], []) <$> (getField "body" fields >>= pWithContents pBlocks))-  ,("square", \_ fields ->+  ,("square", \_ _ fields ->       B.divWith ("", ["square"], []) <$> (getField "body" fields >>= pWithContents pBlocks))-  ,("align", \_ fields -> do+  ,("align", \_ _ fields -> do       alignment <- getField "alignment" fields       B.divWith ("", [], [("align", repr alignment)])         <$> (getField "body" fields >>= pWithContents pBlocks))-  ,("stack", \_ fields -> do+  ,("stack", \_ _ fields -> do       (dir :: Direction) <- getField "dir" fields `mplus` pure Ltr       rawchildren <- getField "children" fields       children <-@@ -330,9 +367,9 @@         B.divWith ("", [], [("stack", repr (VDirection dir))]) $           mconcat $             map (B.divWith ("", [], [])) children)-  ,("grid", \mbident fields -> parseTable mbident fields)-  ,("table", \mbident fields -> parseTable mbident fields)-  ,("figure", \mbident fields -> do+  ,("grid", \_ mbident fields -> parseTable mbident fields)+  ,("table", \_ mbident fields -> parseTable mbident fields)+  ,("figure", \_ mbident fields -> do       body <- getField "body" fields >>= pWithContents pBlocks       (mbCaption :: Maybe (Seq Content)) <- getField "caption" fields       (caption :: B.Blocks) <- maybe mempty (pWithContents pBlocks) mbCaption@@ -342,13 +379,13 @@             (B.Table attr (B.Caption Nothing (B.toList caption)) colspecs thead tbodies tfoot)         _ -> B.figureWith (fromMaybe "" mbident, [], [])                           (B.Caption Nothing (B.toList caption)) body)-  ,("line", \_ fields ->+  ,("line", \_ _ fields ->       case ( M.lookup "start" fields               >> M.lookup "end" fields               >> M.lookup "angle" fields ) of         Nothing -> pure B.horizontalRule         _ -> pure mempty)-  ,("numbering", \_ fields -> do+  ,("numbering", \_ _ fields -> do       numStyle <- getField "numbering" fields       (nums :: V.Vector Integer) <- getField "numbers" fields       let toText v = fromMaybe "" $ fromVal v@@ -361,14 +398,43 @@                   Failure _ -> "?"               _ -> "?"       pure $ B.plain . B.text . mconcat . map toNum $ V.toList nums)-  ,("footnote.entry", \_ fields ->+  ,("footnote.entry", \_ _ fields ->       getField "body" fields >>= pWithContents pBlocks)+  ,("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)+  ,("rotate", \_ _ fields -> do+      body <- getField "body" fields >>= pWithContents pBlocks+      let kvs = case M.lookup "angle" fields of+                    Just (VAngle ang) -> [("angle", T.pack $ show ang)]+                    _ -> []+      pure $ B.divWith ("", ["rotate"], kvs) body)   ]  inlineHandlers :: PandocMonad m =>-    M.Map Identifier (Maybe Text -> M.Map Identifier Val -> P m B.Inlines)+    M.Map Identifier (Maybe SourcePos -> Maybe Text ->+                      M.Map Identifier Val -> P m B.Inlines) inlineHandlers = M.fromList-  [("ref", \_ fields -> do+  [("ref", \_ _ fields -> do       VLabel target <- getField "target" fields       supplement' <- getField "supplement" fields       supplement <- case supplement' of@@ -379,17 +445,17 @@                            pure $ B.text ("[" <> target <> "]")                       _ -> pure mempty       pure $ B.linkWith ("", ["ref"], []) ("#" <> target) "" supplement)-  ,("linebreak", \_ _ -> pure B.linebreak)-  ,("text", \_ fields -> do+  ,("linebreak", \_ _ _ -> pure B.linebreak)+  ,("text", \_ _ fields -> do       body <- getField "body" fields       (mbweight :: Maybe Text) <- getField "weight" fields       case mbweight of         Just "bold" -> B.strong <$> pWithContents pInlines body         _ -> pWithContents pInlines body)-  ,("raw", \_ fields -> B.code . T.filter (/= '\r') <$> getField "text" fields)-  ,("footnote", \_ fields ->+  ,("raw", \_ _ fields -> B.code . T.filter (/= '\r') <$> getField "text" fields)+  ,("footnote", \_ _ fields ->       B.note <$> (getField "body" fields >>= pWithContents pBlocks))-  ,("cite", \_ fields -> do+  ,("cite", \_ _ fields -> do       VLabel key <- getField "key" fields       (form :: Text) <- getField "form" fields <|> pure "normal"       let citation =@@ -404,38 +470,38 @@                 B.citationHash = 0               }       pure $ B.cite [citation] (B.text $ "[" <> key <> "]"))-  ,("lower", \_ fields -> do+  ,("lower", \_ _ fields -> do       body <- getField "text" fields       walk (modString T.toLower) <$> pWithContents pInlines body)-  ,("upper", \_ fields -> do+  ,("upper", \_ _ fields -> do       body <- getField "text" fields       walk (modString T.toUpper) <$> pWithContents pInlines body)-  ,("emph", \_ fields -> do+  ,("emph", \_ _ fields -> do       body <- getField "body" fields       B.emph <$> pWithContents pInlines body)-  ,("strong", \_ fields -> do+  ,("strong", \_ _ fields -> do       body <- getField "body" fields       B.strong <$> pWithContents pInlines body)-  ,("sub", \_ fields -> do+  ,("sub", \_ _ fields -> do       body <- getField "body" fields       B.subscript <$> pWithContents pInlines body)-  ,("super", \_ fields -> do+  ,("super", \_ _ fields -> do       body <- getField "body" fields       B.superscript <$> pWithContents pInlines body)-  ,("strike", \_ fields -> do+  ,("strike", \_ _ fields -> do       body <- getField "body" fields       B.strikeout <$> pWithContents pInlines body)-  ,("smallcaps", \_ fields -> do+  ,("smallcaps", \_ _ fields -> do       body <- getField "body" fields       B.smallcaps <$> pWithContents pInlines body)-  ,("underline", \_ fields -> do+  ,("underline", \_ _ fields -> do       body <- getField "body" fields       B.underline <$> pWithContents pInlines body)-  ,("quote", \_ fields -> do+  ,("quote", \_ _ fields -> do       (getField "block" fields <|> pure False) >>= guard . not       body <- getInlineBody fields >>= pWithContents pInlines       pure $ B.doubleQuoted $ B.trimInlines body)-  ,("link", \_ fields -> do+  ,("link", \_ _ fields -> do       dest <- getField "dest" fields       src <- case dest of         VString t -> pure t@@ -443,7 +509,7 @@         VDict _ -> do           ignored "link to location, linking to #"           pure "#"-        _ -> fail $ "Expected string or label for dest"+        _ -> fail "Expected string or label for dest"       body <- getField "body" fields       description <-         if null body@@ -460,9 +526,15 @@                pWithContents                 (B.fromList . blocksToInlines . B.toList <$> pBlocks) body       pure $ B.link src "" description)-  ,("image", \_ fields -> do-      path <- getField "path" fields+  ,("image", \mbpos _ fields -> do+      path <- getField "source" fields <|> getField "path" fields       alt <- (B.text <$> getField "alt" fields) `mplus` pure mempty+      let basedir = maybe "." (takeDirectory . sourceName) mbpos+      let isAbsolutePath p = Posix.isAbsolute p || Windows.isAbsolute p+      let path' = T.pack $+                  if isAbsolutePath path || basedir == "."+                     then path+                     else basedir Posix.</> path       (mbwidth :: Maybe Text) <-         fmap (renderLength False) <$> getField "width" fields       (mbheight :: Maybe Text) <-@@ -473,11 +545,11 @@               maybe [] (\x -> [("width", x)]) mbwidth                 ++ maybe [] (\x -> [("height", x)]) mbheight             )-      pure $ B.imageWith attr path "" alt)-  ,("box", \_ fields -> do+      pure $ B.imageWith attr path' "" alt)+  ,("box", \_ _ fields -> do       body <- getField "body" fields       B.spanWith ("", ["box"], []) <$> pWithContents pInlines body)-  ,("h", \_ fields -> do+  ,("h", \_ _ fields -> do       amount <- getField "amount" fields `mplus` pure (LExact 1 LEm)       let em = case amount of             LExact x LEm -> toRational x@@ -485,18 +557,29 @@               LExact x LPt -> toRational x / 12               _ -> 1 / 3 -- guess!       pure $ B.text $ getSpaceChars em)-  ,("place", \_ fields -> do+  ,("place", \_ _ fields -> do       ignored "parameters of place"       getField "body" fields >>= pWithContents pInlines)-  ,("align", \_ fields -> do+  ,("align", \_ _ fields -> do       alignment <- getField "alignment" fields       B.spanWith ("", [], [("align", repr alignment)])         <$> (getField "body" fields >>= pWithContents pInlines))-  ,("sys.version", \_ _ -> pure $ B.text "typst-hs")-  ,("math.equation", \_ fields -> do+  ,("sys.version", \_ _ _ -> pure $ B.text "typst-hs")+  ,("math.equation", \_ _ fields -> do       body <- getField "body" fields       display <- getField "block" fields       (if display then B.displayMath else B.math) . writeTeX <$> pMathMany body)+  ,("pad", \_ _ fields ->  -- ignore paddingy+      getField "body" fields >>= pWithContents pInlines)+  ,("block", \_ mbident fields ->+      maybe id (\ident -> B.spanWith (ident, [], [])) mbident+        <$> (getField "body" fields >>= pWithContents pInlines))+  ,("rotate", \_ _ fields -> do+      body <- getField "body" fields >>= pWithContents pInlines+      let kvs = case M.lookup "angle" fields of+                    Just (VAngle ang) -> [("angle", T.pack $ show ang)]+                    _ -> []+      pure $ B.spanWith ("", ["rotate"], kvs) body)   ]  getInlineBody :: PandocMonad m => M.Map Identifier Val -> P m (Seq Content)@@ -513,9 +596,12 @@    isParbreak _ = False  pPara :: PandocMonad m => P m B.Blocks-pPara =-  B.para . B.trimInlines . collapseAdjacentCites . mconcat-    <$> (many1 pInline <* optional pParBreak)+pPara = do+  ils <- B.trimInlines . collapseAdjacentCites . mconcat <$> many1 pInline+  optional pParBreak+  pure $ if ils == mempty+         then mempty+         else B.para ils  pParBreak :: PandocMonad m => P m () pParBreak =@@ -537,7 +623,8 @@  pInlines :: PandocMonad m => P m B.Inlines pInlines =-  collapseAdjacentCites . mconcat <$> many pInline+  mappend <$> (collapseAdjacentCites . mconcat <$> many pInline)+          <*> ((B.softbreak <$ pParBreak) <|> pure mempty)  collapseAdjacentCites :: B.Inlines -> B.Inlines collapseAdjacentCites = B.fromList . foldr go [] . B.toList
src/Text/Pandoc/Readers/Typst/Math.hs view
@@ -207,6 +207,20 @@       case mbAnn of         Nothing -> pure x         Just ann -> EOver False x <$> pMathGrouped ann+    Elt "math.underparen" _ fields -> do+      mbAnn <- getField "annotation" fields+      body <- getField "body" fields >>= pMathGrouped+      let x = EUnder False body (ESymbol TUnder "\9181")+      case mbAnn of+        Nothing -> pure x+        Just ann -> EUnder False x <$> pMathGrouped ann+    Elt "math.overparen" _ fields -> do+      mbAnn <- getField "annotation" fields+      body <- getField "body" fields >>= pMathGrouped+      let x = EOver False body (ESymbol TOver "\9180")+      case mbAnn of+        Nothing -> pure x+        Just ann -> EOver False x <$> pMathGrouped ann     Elt "math.scripts" _ fields -> getField "body" fields >>= pMathGrouped     Elt "math.limits" _ fields -> getField "body" fields >>= pMathGrouped     Elt "math.root" _ fields -> do
src/Text/Pandoc/Readers/Typst/Parsing.hs view
@@ -27,15 +27,18 @@     ( Identifier, Content(Elt), FromVal(..), Val(VNone) ) import Text.Pandoc.Class.PandocMonad ( PandocMonad, report ) import Text.Pandoc.Logging (LogMessage(..))+import Text.Pandoc.Definition -newtype PState = PState-        { sLabels :: [Text]}+data PState = PState+        { sLabels :: [Text]+        , sMeta :: Meta }         deriving (Show)  defaultPState :: PState defaultPState =   PState-  { sLabels = [] }+  { sLabels = []+  , sMeta = mempty }  type P m a = ParsecT [Content] PState m a -- state tracks a list of labels in the document
src/Text/Pandoc/Readers/Vimwiki.hs view
@@ -54,16 +54,9 @@ import Data.Maybe import Data.Text (Text) import qualified Data.Text as T+import Safe (lastMay) import Text.Pandoc.Builder (Blocks, Inlines, fromList, toList, trimInlines)-import qualified Text.Pandoc.Builder as B (blockQuote, bulletList, code,-                                           codeBlockWith, definitionList,-                                           displayMath, divWith, emph,-                                           headerWith, horizontalRule, image,-                                           imageWith, link, math, orderedList,-                                           para, plain, setMeta, simpleTable,-                                           softbreak, space, spanWith, str,-                                           strikeout, strong, subscript,-                                           superscript)+import qualified Text.Pandoc.Builder as B import Text.Pandoc.Class.PandocMonad (PandocMonad (..)) import Text.Pandoc.Definition (Attr, Block (BulletList, OrderedList),                                Inline (Space), ListNumberDelim (..),@@ -249,14 +242,13 @@  nameValue :: Text -> Maybe (Text, Text) nameValue s =-  let t = splitTextBy (== '=') s in-    if length t /= 2-      then Nothing-      else let (a, b) = (head t, last t) in-             if (T.length b < 2) || ((T.head b, T.last b) /= ('"', '"'))-               then Nothing-               else Just (a, stripFirstAndLast b)-+  case splitTextBy (== '=') s of+    [a,b]+      | T.length b >= 2+      , "\"" `T.isPrefixOf` b+      , "\"" `T.isSuffixOf` b+      -> Just (a, stripFirstAndLast b)+    _ -> Nothing  displayMath :: PandocMonad m => VwParser m Blocks displayMath = try $ do@@ -291,8 +283,8 @@  mixedList :: PandocMonad m => VwParser m Blocks mixedList = try $ do-  (bl, _) <- mixedList' (-1)-  return $ head bl+  ((bl:_), _) <- mixedList' (-1)+  return bl  mixedList' :: PandocMonad m => Int -> VwParser m ([Blocks], Int) mixedList' prevInd = do@@ -407,8 +399,8 @@ -- headerless table table2 :: PandocMonad m => VwParser m ([Blocks], [[Blocks]]) table2 = try $ do-  trs <- many1 tableRow-  return (replicate (length $ head trs) mempty, trs)+  trs@(firstrow:_) <- many1 tableRow+  return (replicate (length firstrow) mempty, trs)  tableHeaderSeparator :: PandocMonad m => VwParser m () tableHeaderSeparator = try $ do@@ -507,26 +499,23 @@  strong :: PandocMonad m => VwParser m Inlines strong = try $ do-  s <- lookAhead $ char '*' *> many1 (noneOf "*") <* char '*'-  guard $ (head s `notElem` spaceChars)-             && (last s `notElem` spaceChars)   char '*'-  contents <- mconcat <$>manyTill inline' (char '*'-    >> notFollowedBy alphaNum)-  return $ B.spanWith (makeId contents, [], []) mempty-    <> B.strong contents+  notFollowedBy (oneOf spaceChars)+  contents <- mconcat <$> many1Till inline'+                           (try (char '*' *> notFollowedBy alphaNum))+  guard $ lastMay (toList contents) /= Just Space+  return $ B.spanWith (makeId contents, [], []) mempty <> B.strong contents  makeId :: Inlines -> Text makeId i = T.concat (stringify <$> toList i)  emph :: PandocMonad m => VwParser m Inlines emph = try $ do-  s <- lookAhead $ char '_' *> many1 (noneOf "_") <* char '_'-  guard $ (head s `notElem` spaceChars)-          && (last s `notElem` spaceChars)   char '_'-  contents <- mconcat <$>manyTill inline' (char '_'-    >> notFollowedBy alphaNum)+  notFollowedBy (oneOf spaceChars)+  contents <- mconcat <$> many1Till inline'+                           (try (char '_' *> notFollowedBy alphaNum))+  guard $ lastMay (toList contents) /= Just Space   return $ B.emph contents  strikeout :: PandocMonad m => VwParser m Inlines@@ -558,17 +547,14 @@                   then do                     url <- manyTillChar anyChar $ char '|'                     lab <- mconcat <$> manyTill inline (string "]]")-                    let tit = if isURI url-                                 then ""-                                 else "wikilink"-                    return $ B.link (procLink url) tit lab+                    return $ B.linkWith (attr url) (procLink url) "" lab                   else do                     manyTill anyChar (string "]]") -- not using try here because [[hell]o]] is not rendered as a link in vimwiki-                    let tit = if isURI contents-                                 then ""-                                 else "wikilink"-                    return $ B.link (procLink contents) tit (B.str contents)+                    return $ B.linkWith (attr contents) (procLink contents) "" (B.str contents)+  where+    attr t | isURI t = B.nullAttr+           | otherwise = (mempty, ["wikilink"], mempty)  image :: PandocMonad m => VwParser m Inlines image = try $ do@@ -601,8 +587,8 @@ procLink' s   | T.take 6 s == "local:" = "file" <> T.drop 5 s   | T.take 6 s == "diary:" = "diary/" <> T.drop 6 s-  | or ((`T.isPrefixOf` s) <$> [ "http:", "https:", "ftp:", "file:", "mailto:",-                              "news:", "telnet:" ])+  | any (`T.isPrefixOf` s) [ "http:", "https:", "ftp:", "file:", "mailto:",+                             "news:", "telnet:" ]                              = s   | s == ""                  = ""   | T.last s == '/'          = s@@ -624,8 +610,9 @@   char ':'   s <- manyTillChar (noneOf spaceChars) (try (char ':' >> lookAhead space))   guard $ not $ "::" `T.isInfixOf` (":" <> s <> ":")-  let ss = splitTextBy (==':') s-  return $ mconcat $ makeTagSpan' (head ss):(makeTagSpan <$> tail ss)+  case splitTextBy (==':') s of+    [] -> fail "tag doesn't contain :"+    (x:xs) -> return $ mconcat $ makeTagSpan' x : (makeTagSpan <$> xs)  todoMark :: PandocMonad m => VwParser m Inlines todoMark = try $ do
+ src/Text/Pandoc/Readers/XML.hs view
@@ -0,0 +1,543 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}++-- |+--   Module      : Text.Pandoc.Readers.XML+--   Copyright   : Copyright (C) 2025- Massimiliano Farinella and John MacFarlane+--   License     : GNU GPL, version 2 or above+--+--   Maintainer  : Massimiliano Farinella <massifrg@gmail.com>+--   Stability   : WIP+--   Portability : portable+--+-- Conversion of (Pandoc specific) xml to 'Pandoc' document.+module Text.Pandoc.Readers.XML (readXML) where++import Control.Monad (msum)+import Control.Monad.Except (throwError)+import Control.Monad.State.Strict (StateT (runStateT), modify)+import Data.Char (isSpace)+import Data.Default (Default (..))+import qualified Data.List as L+import qualified Data.Map as M+import Data.Maybe (catMaybes, fromMaybe, mapMaybe)+import qualified Data.Set as S (Set, fromList, member)+import Data.Text (Text)+import qualified Data.Text as T+import Data.Text.Lazy (fromStrict)+import Data.Version (Version, makeVersion)+import Text.Pandoc.Builder+import Text.Pandoc.Class.PandocMonad+import Text.Pandoc.Error (PandocError (..))+import Text.Pandoc.Options+import Text.Pandoc.Parsing (ToSources, toSources)+import Text.Pandoc.Sources (sourcesToText)+import Text.Pandoc.Version (pandocVersion)+import Text.Pandoc.XML (lookupEntity)+import Text.Pandoc.XML.Light+import Text.Pandoc.XMLFormat+import Text.Read (readMaybe)++-- TODO: use xmlPath state to give better context when an error occurs++type XMLReader m = StateT XMLReaderState m++data XMLReaderState = XMLReaderState+  { xmlApiVersion :: Version,+    xmlMeta :: Meta,+    xmlContent :: [Content],+    xmlPath :: [Text]+  }+  deriving (Show)++instance Default XMLReaderState where+  def =+    XMLReaderState+      { xmlApiVersion = pandocVersion,+        xmlMeta = mempty,+        xmlContent = [],+        xmlPath = ["root"]+      }++readXML :: (PandocMonad m, ToSources a) => ReaderOptions -> a -> m Pandoc+readXML _ inp = do+  let sources = toSources inp+  tree <-+    either (throwError . PandocXMLError "") return $+      parseXMLContents (fromStrict . sourcesToText $ sources)+  (bs, st') <- flip runStateT (def {xmlContent = tree}) $ mapM parseBlock tree+  let blockList = toList $ concatMany bs+  return $ Pandoc (xmlMeta st') blockList++concatMany :: [Many a] -> Many a+concatMany = Many . mconcat . map unMany++parseBlocks :: (PandocMonad m) => [Content] -> XMLReader m Blocks+parseBlocks contents = concatMany <$> mapM parseBlock contents++getBlocks :: (PandocMonad m) => Element -> XMLReader m Blocks+getBlocks e = parseBlocks (elContent e)++elementName :: Element -> Text+elementName e = qName $ elName e++attrValue :: Text -> Element -> Text+attrValue attr =+  fromMaybe "" . maybeAttrValue attr++maybeAttrValue :: Text -> Element -> Maybe Text+maybeAttrValue attr elt =+  lookupAttrBy (\x -> qName x == attr) (elAttribs elt)++parseBlock :: (PandocMonad m) => Content -> XMLReader m Blocks+parseBlock (Text (CData CDataRaw _ _)) = return mempty -- DOCTYPE+parseBlock (Text (CData _ s _)) =+  if T.all isSpace s+    then return mempty+    else do+      throwError $ PandocXMLError "" "non-space characters out of inline context"+parseBlock (CRef x) = do+  throwError $ PandocXMLError "" ("reference \"" <> x <> "\" out of inline context")+parseBlock (Elem e) = do+  let name = elementName e+   in case (name) of+        "Pandoc" -> parsePandoc+        "?xml" -> return mempty+        "blocks" -> getBlocks e+        "meta" ->+          let entry_els = childrenNamed tgNameMetaMapEntry e+           in do+                entries <- catMaybes <$> mapM parseMetaMapEntry entry_els+                mapM_ (uncurry addMeta) entries+                return mempty+        "Para" -> para <$> getInlines (elContent e)+        "Plain" -> do+          ils <- getInlines (elContent e)+          return $ singleton . Plain . toList $ ils+        "Header" -> (headerWith attr level) <$> getInlines (elContent e)+          where+            level = textToInt (attrValue atNameLevel e) 1+            attr = filterAttrAttributes [atNameLevel] $ attrFromElement e+        "HorizontalRule" -> return horizontalRule+        "BlockQuote" -> do+          contents <- getBlocks e+          return $ blockQuote contents+        "Div" -> do+          contents <- getBlocks e+          return $ divWith (attrFromElement e) contents+        "BulletList" -> do+          items <- getListItems e+          return $ bulletList items+        "OrderedList" -> do+          items <- getListItems e+          return $ orderedListWith (getListAttributes e) items+        "DefinitionList" -> do+          let items_contents = getContentsOfElements (isElementNamed tgNameDefListItem) (elContent e)+          items <- mapM parseDefinitionListItem items_contents+          return $ definitionList items+        "Figure" -> do+          let attr = attrFromElement e+              (maybe_caption_el, contents) = partitionFirstChildNamed "Caption" $ elContent e+          figure_caption <- case (maybe_caption_el) of+            Just (caption_el) -> parseCaption $ elContent caption_el+            Nothing -> pure emptyCaption+          blocks <- parseBlocks contents+          return $ figureWith attr figure_caption blocks+        "CodeBlock" -> do+          let attr = attrFromElement e+          return $ codeBlockWith attr $ strContentRecursive e+        "RawBlock" -> do+          let format = (attrValue atNameFormat e)+          return $ rawBlock format $ strContentRecursive e+        "LineBlock" -> do+          lins <- mapM getInlines (contentsOfChildren tgNameLineItem (elContent e))+          return $ lineBlock lins+        "Table" -> do+          -- TODO: check unexpected items+          let attr = attrFromElement e+              (maybe_caption_el, after_caption) = partitionFirstChildNamed "Caption" $ elContent e+              children = elementsWithNames (S.fromList [tgNameColspecs, "TableHead", "TableBody", "TableFoot"]) after_caption+              is_element tag el = tag == elementName el+          colspecs <- getColspecs $ L.find (is_element tgNameColspecs) children+          tbs <- getTableBodies $ filter (is_element "TableBody") children+          th <- getTableHead $ L.find (is_element "TableHead") children+          tf <- getTableFoot $ L.find (is_element "TableFoot") children+          capt <- parseMaybeCaptionElement maybe_caption_el+          case colspecs of+            Nothing -> return mempty+            Just cs -> return $ fromList [Table attr capt cs th tbs tf]+        _ -> do+          throwError $ PandocXMLError "" ("unexpected element \"" <> name <> "\" in blocks context")+  where+    parsePandoc = do+      let version = maybeAttrValue atNameApiVersion e+          apiversion = case (version) of+            Just (v) -> makeVersion $ map (read . T.unpack) $ T.splitOn "," v+            Nothing -> pandocVersion+       in modify $ \st -> st {xmlApiVersion = apiversion}+      getBlocks e++getListItems :: (PandocMonad m) => Element -> XMLReader m [Blocks]+getListItems e =+  let items_els = childrenNamed tgNameListItem e+   in do+        mapM getBlocks items_els++getContentsOfElements :: (Content -> Bool) -> [Content] -> [[Content]]+getContentsOfElements filter_element contents = mapMaybe element_contents $ filter filter_element contents+  where+    element_contents :: Content -> Maybe [Content]+    element_contents c = case (c) of+      Elem e -> Just (elContent e)+      _ -> Nothing++strContentRecursive :: Element -> Text+strContentRecursive =+  strContent+    . (\e' -> e' {elContent = map elementToStr $ elContent e'})++elementToStr :: Content -> Content+elementToStr (Elem e') = Text $ CData CDataText (strContentRecursive e') Nothing+elementToStr x = x++textToInt :: Text -> Int -> Int+textToInt t deflt =+  let safe_to_int :: Text -> Maybe Int+      safe_to_int s = readMaybe $ T.unpack s+   in case (safe_to_int t) of+        Nothing -> deflt+        Just (n) -> n++parseInline :: (PandocMonad m) => Content -> XMLReader m Inlines+parseInline (Text (CData _ s _)) =+  return $ text s+parseInline (CRef ref) =+  return $+    maybe (text $ T.toUpper ref) text $+      lookupEntity ref+parseInline (Elem e) =+  let name = elementName e+   in case (name) of+        "Space" ->+          let count = textToInt (attrValue atNameSpaceCount e) 1+           in return $ fromList $ replicate count Space+        "Str" -> return $ fromList [Str $ attrValue atNameStrContent e]+        "Emph" -> innerInlines emph+        "Strong" -> innerInlines strong+        "Strikeout" -> innerInlines strikeout+        "Subscript" -> innerInlines subscript+        "Superscript" -> innerInlines superscript+        "Underline" -> innerInlines underline+        "SoftBreak" -> return softbreak+        "LineBreak" -> return linebreak+        "SmallCaps" -> innerInlines smallcaps+        "Quoted" -> case (attrValue atNameQuoteType e) of+          "SingleQuote" -> innerInlines singleQuoted+          _ -> innerInlines doubleQuoted+        "Math" -> case (attrValue atNameMathType e) of+          "DisplayMath" -> pure $ displayMath $ strContentRecursive e+          _ -> pure $ math $ strContentRecursive e+        "Span" -> innerInlines $ spanWith (attrFromElement e)+        "Code" -> do+          let attr = attrFromElement e+          return $ codeWith attr $ strContentRecursive e+        "Link" -> innerInlines $ linkWith attr url title+          where+            url = attrValue atNameLinkUrl e+            title = attrValue atNameTitle e+            attr = filterAttrAttributes [atNameLinkUrl, atNameTitle] $ attrFromElement e+        "Image" -> innerInlines $ imageWith attr url title+          where+            url = attrValue atNameImageUrl e+            title = attrValue atNameTitle e+            attr = filterAttrAttributes [atNameImageUrl, atNameTitle] $ attrFromElement e+        "RawInline" -> do+          let format = (attrValue atNameFormat e)+          return $ rawInline format $ strContentRecursive e+        "Note" -> do+          contents <- getBlocks e+          return $ note contents+        "Cite" ->+          let (maybe_citations_el, contents) = partitionFirstChildNamed tgNameCitations $ elContent e+           in case (maybe_citations_el) of+                Just citations_el -> do+                  citations <- parseCitations $ elContent citations_el+                  (innerInlines' contents) $ cite citations+                Nothing -> getInlines contents+        _ -> do+          throwError $ PandocXMLError "" ("unexpected element \"" <> name <> "\" in inline context")+  where+    innerInlines' contents f =+      f . concatMany+        <$> mapM parseInline contents+    innerInlines f = innerInlines' (elContent e) f++getInlines :: (PandocMonad m) => [Content] -> XMLReader m Inlines+getInlines contents = concatMany <$> mapM parseInline contents++getListAttributes :: Element -> ListAttributes+getListAttributes e = (start, style, delim)+  where+    start = textToInt (attrValue atNameStart e) 1+    style = case (attrValue atNameNumberStyle e) of+      "Example" -> Example+      "Decimal" -> Decimal+      "LowerRoman" -> LowerRoman+      "UpperRoman" -> UpperRoman+      "LowerAlpha" -> LowerAlpha+      "UpperAlpha" -> UpperAlpha+      _ -> DefaultStyle+    delim = case (attrValue atNameNumberDelim e) of+      "Period" -> Period+      "OneParen" -> OneParen+      "TwoParens" -> TwoParens+      _ -> DefaultDelim++contentsOfChildren :: Text -> [Content] -> [[Content]]+contentsOfChildren tag contents = mapMaybe childrenElementWithTag contents+  where+    childrenElementWithTag :: Content -> Maybe [Content]+    childrenElementWithTag c = case (c) of+      (Elem e) -> if tag == elementName e then Just (elContent e) else Nothing+      _ -> Nothing++alignmentFromText :: Text -> Alignment+alignmentFromText t = case t of+  "AlignLeft" -> AlignLeft+  "AlignRight" -> AlignRight+  "AlignCenter" -> AlignCenter+  _ -> AlignDefault++getColWidth :: Text -> ColWidth+getColWidth txt = case reads (T.unpack txt) of+  [(value, "")] -> if value == 0.0 then ColWidthDefault else ColWidth value+  _ -> ColWidthDefault++getColspecs :: (PandocMonad m) => Maybe Element -> XMLReader m (Maybe [ColSpec])+getColspecs Nothing = pure Nothing+getColspecs (Just cs) = do+  return $ Just $ map elementToColSpec (childrenNamed "ColSpec" cs)+  where+    elementToColSpec e = (alignmentFromText $ attrValue atNameAlignment e, getColWidth $ attrValue atNameColWidth e)++getTableBody :: (PandocMonad m) => Element -> XMLReader m (Maybe TableBody)+getTableBody body_el = do+  let attr = filterAttrAttributes [atNameRowHeadColumns] $ attrFromElement body_el+      bh = childrenNamed tgNameBodyHeader body_el+      bb = childrenNamed tgNameBodyBody body_el+      headcols = textToInt (attrValue atNameRowHeadColumns body_el) 0+  hrows <- mconcat <$> mapM getRows bh+  brows <- mconcat <$> mapM getRows bb+  return $ Just $ TableBody attr (RowHeadColumns headcols) hrows brows++getTableBodies :: (PandocMonad m) => [Element] -> XMLReader m [TableBody]+getTableBodies body_elements = do+  catMaybes <$> mapM getTableBody body_elements++getTableHead :: (PandocMonad m) => Maybe Element -> XMLReader m TableHead+getTableHead maybe_e = case maybe_e of+  Just e -> do+    let attr = attrFromElement e+    rows <- getRows e+    return $ TableHead attr rows+  Nothing -> return $ TableHead nullAttr []++getTableFoot :: (PandocMonad m) => Maybe Element -> XMLReader m TableFoot+getTableFoot maybe_e = case maybe_e of+  Just e -> do+    let attr = attrFromElement e+    rows <- getRows e+    return $ TableFoot attr rows+  Nothing -> return $ TableFoot nullAttr []++getCell :: (PandocMonad m) => Element -> XMLReader m Cell+getCell c = do+  let alignment = alignmentFromText $ attrValue atNameAlignment c+      rowspan = RowSpan $ textToInt (attrValue atNameRowspan c) 1+      colspan = ColSpan $ textToInt (attrValue atNameColspan c) 1+      attr = filterAttrAttributes [atNameAlignment, atNameRowspan, atNameColspan] $ attrFromElement c+  blocks <- getBlocks c+  return $ Cell attr alignment rowspan colspan (toList blocks)++getRows :: (PandocMonad m) => Element -> XMLReader m [Row]+getRows e = mapM getRow $ childrenNamed "Row" e+  where+    getRow r = do+      cells <- mapM getCell (childrenNamed "Cell" r)+      return $ Row (attrFromElement r) cells++parseCitations :: (PandocMonad m) => [Content] -> XMLReader m [Citation]+parseCitations contents = do+  maybecitations <- mapM getCitation contents+  return $ catMaybes maybecitations+  where+    getCitation :: (PandocMonad m) => Content -> XMLReader m (Maybe Citation)+    getCitation content = case (content) of+      (Elem e) ->+        if qName (elName e) == "Citation"+          then do+            p <- inlinesOfChildrenNamed tgNameCitationPrefix e+            s <- inlinesOfChildrenNamed tgNameCitationSuffix e+            return $+              Just+                ( Citation+                    { citationId = attrValue "id" e,+                      citationPrefix = toList p,+                      citationSuffix = toList s,+                      citationMode = case (attrValue atNameCitationMode e) of+                        "AuthorInText" -> AuthorInText+                        "SuppressAuthor" -> SuppressAuthor+                        _ -> NormalCitation,+                      citationNoteNum = textToInt (attrValue atNameCitationNoteNum e) 0,+                      citationHash = textToInt (attrValue atNameCitationHash e) 0+                    }+                )+          else do+            return Nothing+      _ -> do+        return Nothing+      where+        inlinesOfChildrenNamed tag e = getInlines $ concatMap (\e' -> elContent e') (childrenNamed tag e)++parseMaybeCaptionElement :: (PandocMonad m) => Maybe Element -> XMLReader m Caption+parseMaybeCaptionElement Nothing = pure emptyCaption+parseMaybeCaptionElement (Just e) = parseCaption $ elContent e++parseCaption :: (PandocMonad m) => [Content] -> XMLReader m Caption+parseCaption contents =+  let (maybe_shortcaption_el, caption_contents) = partitionFirstChildNamed tgNameShortCaption contents+   in do+        blocks <- parseBlocks caption_contents+        case (maybe_shortcaption_el) of+          Just shortcaption_el -> do+            short_caption <- getInlines (elContent shortcaption_el)+            return $ caption (Just $ toList short_caption) blocks+          Nothing -> return $ caption Nothing blocks++parseDefinitionListItem :: (PandocMonad m) => [Content] -> XMLReader m (Inlines, [Blocks])+parseDefinitionListItem contents = do+  let term_contents = getContentsOfElements (isElementNamed tgNameDefListTerm) contents+      defs_elements = elementContents $ filter (isElementNamed tgNameDefListDef) contents+  term_inlines <- getInlines (concat term_contents)+  defs <- mapM getBlocks defs_elements+  return (term_inlines, defs)++elementContents :: [Content] -> [Element]+elementContents contents = mapMaybe toElement contents+  where+    toElement :: Content -> Maybe Element+    toElement (Elem e) = Just e+    toElement _ = Nothing++isElementNamed :: Text -> Content -> Bool+isElementNamed t c = case (c) of+  Elem e -> t == elementName e+  _ -> False++childrenNamed :: Text -> Element -> [Element]+childrenNamed tag e = elementContents $ filter (isElementNamed tag) (elContent e)++elementsWithNames :: S.Set Text -> [Content] -> [Element]+elementsWithNames tags contents = mapMaybe isElementWithNameInSet contents+  where+    isElementWithNameInSet c = case (c) of+      Elem el ->+        if (elementName el) `S.member` tags+          then Just el+          else Nothing+      _ -> Nothing++partitionFirstChildNamed :: Text -> [Content] -> (Maybe Element, [Content])+partitionFirstChildNamed tag contents = case (contents) of+  (Text (CData _ s _) : rest) ->+    if T.all isSpace s+      then partitionFirstChildNamed tag rest+      else (Nothing, contents)+  (Elem e : rest) ->+    if tag == elementName e+      then (Just e, rest)+      else (Nothing, contents)+  _ -> (Nothing, contents)++type PandocAttr = (Text, [Text], [(Text, Text)])++filterAttributes :: S.Set Text -> [(Text, Text)] -> [(Text, Text)]+filterAttributes to_be_removed a = filter keep_attr a+  where+    keep_attr (k, _) = not (k `S.member` to_be_removed)++filterAttrAttributes :: [Text] -> PandocAttr -> PandocAttr+filterAttrAttributes to_be_removed (idn, classes, a) = (idn, classes, filtered)+  where+    filtered = filterAttributes (S.fromList to_be_removed) a++attrFromElement :: Element -> PandocAttr+attrFromElement e = filterAttrAttributes ["id", "class"] (idn, classes, attributes)+  where+    idn = attrValue "id" e+    classes = T.words $ attrValue "class" e+    attributes = map (\a -> (qName $ attrKey a, attrVal a)) $ elAttribs e++addMeta :: (PandocMonad m) => (ToMetaValue a) => Text -> a -> XMLReader m ()+addMeta field val = modify (setMeta field val)++instance HasMeta XMLReaderState where+  setMeta field v s = s {xmlMeta = setMeta field v (xmlMeta s)}++  deleteMeta field s = s {xmlMeta = deleteMeta field (xmlMeta s)}++parseMetaMapEntry :: (PandocMonad m) => Element -> XMLReader m (Maybe (Text, MetaValue))+parseMetaMapEntry e =+  let key = attrValue atNameMetaMapEntryKey e+   in case (key) of+        "" -> pure Nothing+        k -> do+          maybe_value <- parseMetaMapEntryContents $ elContent e+          case (maybe_value) of+            Nothing -> return Nothing+            Just v -> return $ Just (k, v)++parseMetaMapEntryContents :: (PandocMonad m) => [Content] -> XMLReader m (Maybe MetaValue)+parseMetaMapEntryContents cs = msum <$> mapM parseMeta cs++getElementText :: Element -> T.Text+getElementText el = T.concat [cdData c | Text c <- elContent el]++parseMeta :: (PandocMonad m) => Content -> XMLReader m (Maybe MetaValue)+parseMeta (Text (CData CDataRaw _ _)) = return Nothing+parseMeta (Text (CData _ s _)) =+  if T.all isSpace s+    then return Nothing+    else do+      throwError $ PandocXMLError "" "non-space characters out of inline context in metadata"+parseMeta (CRef x) =+  throwError $ PandocXMLError "" ("reference \"" <> x <> "\" out of inline context")+parseMeta (Elem e) = do+  let name = elementName e+   in case (name) of+        "MetaBool" -> case (attrValue atNameMetaBoolValue e) of+          "true" -> return $ Just $ MetaBool True+          _ -> return $ Just $ MetaBool False+        "MetaString" -> return $ Just $ MetaString (getElementText e)+        "MetaInlines" -> do+          inlines <- getInlines (elContent e)+          return $ Just $ MetaInlines $ toList inlines+        "MetaBlocks" -> do+          blocks <- getBlocks e+          return $ Just $ MetaBlocks $ toList blocks+        "MetaList" -> do+          maybe_items <- mapM parseMeta $ elContent e+          let items = catMaybes maybe_items+           in -- TODO: report empty MetaList?+              return $ Just $ MetaList items+        "MetaMap" ->+          let entry_els = childrenNamed tgNameMetaMapEntry e+           in do+                entries <- catMaybes <$> mapM parseMetaMapEntry entry_els+                if null entries+                  then+                    -- TODO: report empty MetaMap+                    return Nothing+                  else return $ Just $ MetaMap $ M.fromList entries+        _ -> do+          throwError $ PandocXMLError "" ("unexpected element \"" <> name <> "\" in metadata")
+ src/Text/Pandoc/Readers/Xlsx.hs view
@@ -0,0 +1,40 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+   Module      : Text.Pandoc.Readers.Xlsx+   Copyright   : © 2025 Anton Antic+   License     : GNU GPL, version 2 or above++   Maintainer  : Anton Antic <anton@everworker.ai>+   Stability   : alpha+   Portability : portable++Conversion of XLSX (Excel spreadsheet) documents to 'Pandoc' document.+-}+module Text.Pandoc.Readers.Xlsx (readXlsx) where++import qualified Data.ByteString.Lazy as B+import qualified Data.Text as T+import Codec.Archive.Zip (toArchiveOrFail)+import Control.Monad.Except (throwError)+import Text.Pandoc.Class.PandocMonad (PandocMonad)+import Text.Pandoc.Definition (Pandoc(..))+import Text.Pandoc.Error (PandocError(..))+import Text.Pandoc.Options (ReaderOptions)+import Text.Pandoc.Readers.Xlsx.Parse (archiveToXlsx)+import Text.Pandoc.Readers.Xlsx.Sheets (xlsxToOutput)++-- | Read XLSX file into Pandoc AST+readXlsx :: PandocMonad m => ReaderOptions -> B.ByteString -> m Pandoc+readXlsx opts bytes =+  case toArchiveOrFail bytes of+    Right archive ->+      case archiveToXlsx archive of+        Right xlsx -> do+          let (meta, blocks) = xlsxToOutput opts xlsx+          return $ Pandoc meta blocks+        Left err ->+          throwError $ PandocParseError $ "Failed to parse XLSX: " <> err++    Left err ->+      throwError $ PandocParseError $+        "Failed to unpack XLSX archive: " <> T.pack err
+ src/Text/Pandoc/Readers/Xlsx/Cells.hs view
@@ -0,0 +1,63 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+   Module      : Text.Pandoc.Readers.Xlsx.Cells+   Copyright   : © 2025 Anton Antic+   License     : GNU GPL, version 2 or above++   Maintainer  : Anton Antic <anton@everworker.ai>+   Stability   : alpha+   Portability : portable++Cell types and parsing for XLSX.+-}+module Text.Pandoc.Readers.Xlsx.Cells+  ( CellRef(..)+  , XlsxCell(..)+  , CellValue(..)+  , parseCellRef+  ) where++import qualified Data.Text as T+import Data.Text (Text)+import Data.Char (ord, isAlpha)+import Text.Read (readMaybe)++-- | Cell reference (A1 notation)+data CellRef = CellRef+  { cellRefCol :: Int    -- 1-based (A=1, B=2, ..., AA=27)+  , cellRefRow :: Int    -- 1-based+  } deriving (Show, Eq, Ord)++-- | Cell value types+data CellValue+  = TextValue Text+  | NumberValue Double+  | EmptyValue+  deriving (Show, Eq)++-- | Parsed cell+data XlsxCell = XlsxCell+  { cellRef :: CellRef+  , cellValue :: CellValue+  , cellBold :: Bool+  , cellItalic :: Bool+  } deriving (Show)++-- | Parse cell reference (A1 → CellRef)+parseCellRef :: Text -> Either Text CellRef+parseCellRef ref = do+  let (colStr, rowStr) = T.span isAlpha ref++  row <- case readMaybe (T.unpack rowStr) of+    Just r | r > 0 -> Right r+    _ -> Left $ "Invalid row: " <> rowStr++  col <- parseColumn colStr++  return $ CellRef col row++-- | Parse column (A=1, Z=26, AA=27, etc.)+parseColumn :: Text -> Either Text Int+parseColumn colStr+  | T.null colStr = Left "Empty column"+  | otherwise = Right $ T.foldl' (\acc c -> acc * 26 + (ord c - ord 'A' + 1)) 0 colStr
+ src/Text/Pandoc/Readers/Xlsx/Parse.hs view
@@ -0,0 +1,296 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+   Module      : Text.Pandoc.Readers.Xlsx.Parse+   Copyright   : © 2025 Anton Antic+   License     : GNU GPL, version 2 or above++   Maintainer  : Anton Antic <anton@everworker.ai>+   Stability   : alpha+   Portability : portable++Parsing of XLSX archive to intermediate representation.+-}+module Text.Pandoc.Readers.Xlsx.Parse+  ( Xlsx(..)+  , XlsxWorkbook(..)+  , XlsxSheet(..)+  , SheetId(..)+  , SharedStrings+  , Styles(..)+  , FontInfo(..)+  , archiveToXlsx+  ) where++import Codec.Archive.Zip (Archive, Entry, findEntryByPath, fromEntry)+import Data.List (find)+import qualified Data.Map.Strict as M+import Data.Maybe (mapMaybe, fromMaybe)+import qualified Data.Text as T+import qualified Data.Text.Lazy.Encoding as TL+import Data.Text (Text)+import qualified Data.Vector as V+import System.FilePath (splitFileName)+import Text.Pandoc.Readers.OOXML.Shared+import Text.Pandoc.Readers.Xlsx.Cells+import Text.Pandoc.XML.Light+import Text.Read (readMaybe)++-- | Sheet identifier+newtype SheetId = SheetId Int deriving (Show, Eq, Ord)++-- | Shared strings table (Vector for O(1) lookup)+type SharedStrings = V.Vector Text++-- | Font information+data FontInfo = FontInfo+  { fontBold :: Bool+  , fontItalic :: Bool+  , fontUnderline :: Bool+  } deriving (Show)++-- | Style information+data Styles = Styles+  { styleFonts :: V.Vector FontInfo+  } deriving (Show)++-- | Complete XLSX document+data Xlsx = Xlsx+  { xlsxWorkbook :: XlsxWorkbook+  , xlsxSheets :: [XlsxSheet]+  , xlsxSharedStrings :: SharedStrings+  , xlsxStyles :: Styles+  } deriving (Show)++-- | Workbook information+data XlsxWorkbook = XlsxWorkbook+  { workbookSheetNames :: [(SheetId, Text, Text)]  -- (id, name, relId)+  } deriving (Show)++-- | Individual worksheet+data XlsxSheet = XlsxSheet+  { sheetId :: SheetId+  , sheetName :: Text+  , sheetCells :: M.Map CellRef XlsxCell+  } deriving (Show)++-- | Parse XLSX archive+archiveToXlsx :: Archive -> Either Text Xlsx+archiveToXlsx archive = do+  -- Find and parse workbook.xml+  workbookPath <- getWorkbookXmlPath archive+  workbookElem <- loadXMLFromArchive archive workbookPath+  workbook <- parseWorkbook workbookElem+    `addContext` ("Parsing workbook.xml from: " <> T.pack workbookPath)++  -- Load workbook relationships+  workbookRels <- loadRelationships archive (relsPathFor workbookPath)++  -- Parse shared strings (look for sharedStrings relationship)+  sharedStrings <- case findRelWithTarget workbookRels "sharedStrings" of+    Just (_, target) -> do+      let path = "xl/" ++ T.unpack target+      el <- loadXMLFromArchive archive path+      parseSharedStrings el+    Nothing -> Right V.empty++  -- Parse styles+  styles <- case findRelWithTarget workbookRels "styles" of+    Just (_, target) -> do+      let path = "xl/" ++ T.unpack target+      el <- loadXMLFromArchive archive path+      parseStyles el+    Nothing -> Right $ Styles V.empty++  -- Parse worksheets+  sheets <- mapM (\sheetInfo -> parseSheet archive workbookRels sharedStrings styles sheetInfo)+                 (workbookSheetNames workbook)++  return $ Xlsx workbook sheets sharedStrings styles++-- | Find workbook.xml via root relationships+getWorkbookXmlPath :: Archive -> Either Text FilePath+getWorkbookXmlPath archive = do+  relsEntry <- maybeToEither "Missing _rels/.rels" $+               findEntryByPath "_rels/.rels" archive+  relsElem <- parseXMLFromEntry relsEntry++  let relElems = onlyElems $ elContent relsElem+  case find isOfficeDocRel relElems of+    Nothing -> Left "No workbook.xml relationship found"+    Just rel -> do+      target <- maybeToEither "Missing Target" $ findAttr (unqual "Target") rel+      return $ T.unpack target+  where+    isOfficeDocRel el =+      case (findAttr (unqual "Type") el, findAttr (unqual "Target") el) of+        (Just relType, Just target) ->+          "officeDocument" `T.isInfixOf` relType && "workbook" `T.isInfixOf` target+        _ -> False++-- | Parse workbook.xml+parseWorkbook :: Element -> Either Text XlsxWorkbook+parseWorkbook wbElem = do+  let ns = elemToNameSpaces wbElem++  -- Find sheets element (match by local name only)+  sheets <- maybeToEither "Missing <sheets>" $+            find (\e -> qName (elName e) == "sheets") (onlyElems $ elContent wbElem)++  let sheetElems = filter (\e -> qName (elName e) == "sheet") (onlyElems $ elContent sheets)+  sheetRefs <- mapM (parseSheetRef ns) (zip [1..] sheetElems)++  return $ XlsxWorkbook sheetRefs++parseSheetRef :: NameSpaces -> (Int, Element) -> Either Text (SheetId, Text, Text)+parseSheetRef ns (idx, sheetElem) = do+  let name = fromMaybe ("Sheet" <> T.pack (show idx)) $+             findAttr (unqual "name") sheetElem+  relId <- maybeToEither "Missing r:id" $+           findAttrByName ns "r" "id" sheetElem+  return (SheetId idx, name, relId)++-- | Parse shared strings+parseSharedStrings :: Element -> Either Text SharedStrings+parseSharedStrings sstElem = do+  let siElems = filter (\e -> qName (elName e) == "si") (onlyElems $ elContent sstElem)+      strings = map extractString siElems+  return $ V.fromList strings+  where+    extractString siElem =+      case find (\e -> qName (elName e) == "t") (onlyElems $ elContent siElem) of+        Just tElem -> strContent tElem+        Nothing -> getAllText siElem++-- | Parse styles (fonts only for MVP)+parseStyles :: Element -> Either Text Styles+parseStyles stylesElem = do+  -- Parse fonts (match by local name)+  let fontsElem = find (\e -> qName (elName e) == "fonts") (onlyElems $ elContent stylesElem)+      fontElems = maybe [] (\fe -> filter (\e -> qName (elName e) == "font") (onlyElems $ elContent fe)) fontsElem+      fonts = V.fromList $ map (parseFont mempty) fontElems++  return $ Styles fonts++parseFont :: NameSpaces -> Element -> FontInfo+parseFont _ns fontElem =+  FontInfo+    { fontBold = any (\e -> qName (elName e) == "b") (onlyElems $ elContent fontElem)+    , fontItalic = any (\e -> qName (elName e) == "i") (onlyElems $ elContent fontElem)+    , fontUnderline = any (\e -> qName (elName e) == "u") (onlyElems $ elContent fontElem)+    }++-- | Parse individual worksheet+parseSheet :: Archive -> [(Text, Text)] -> SharedStrings -> Styles -> (SheetId, Text, Text) -> Either Text XlsxSheet+parseSheet archive rels sharedStrings styles (sid, name, relId) = do+  target <- maybeToEither ("Sheet relationship not found: " <> relId) $+            lookup relId rels++  let sheetPath = "xl/" ++ T.unpack target+  sheetElem <- loadXMLFromArchive archive sheetPath++  cells <- parseSheetCells sheetElem sharedStrings styles++  return $ XlsxSheet sid name cells++-- | Parse sheet cells+parseSheetCells :: Element -> SharedStrings -> Styles -> Either Text (M.Map CellRef XlsxCell)+parseSheetCells sheetElem sharedStrings styles = do+  -- Find sheetData by local name+  case find (\e -> qName (elName e) == "sheetData") (onlyElems $ elContent sheetElem) of+    Nothing -> return M.empty+    Just sheetData -> do+      let rowElems = filter (\e -> qName (elName e) == "row") (onlyElems $ elContent sheetData)+          cellElems = concatMap (\r -> filter (\e -> qName (elName e) == "c") (onlyElems $ elContent r)) rowElems+          cells = mapMaybe (parseCell sharedStrings styles) cellElems+      return $ M.fromList [(cellRef c, c) | c <- cells]++-- | Parse individual cell+parseCell :: SharedStrings -> Styles -> Element -> Maybe XlsxCell+parseCell sharedStrings styles cElem = do+  -- Get cell reference+  refText <- findAttr (unqual "r") cElem+  cellRefParsed <- either (const Nothing) Just $ parseCellRef refText++  -- Get cell type (default to number if missing)+  let cellType = fromMaybe "" $ findAttr (unqual "t") cElem+      styleIdx = findAttr (unqual "s") cElem >>= readMaybe . T.unpack++  -- Get value (match by local name)+  let vElem = find (\e -> qName (elName e) == "v") (onlyElems $ elContent cElem)+      vText = maybe "" strContent vElem++  -- Parse value based on type+  let value = if cellType == "s"+              then+                -- Shared string+                case readMaybe (T.unpack vText) of+                  Just idx | idx >= 0 && idx < V.length sharedStrings ->+                    TextValue (sharedStrings V.! idx)+                  _ -> EmptyValue+              else if T.null vText+                then EmptyValue+                else+                  -- Number+                  case readMaybe (T.unpack vText) of+                    Just n -> NumberValue n+                    Nothing -> TextValue vText++  -- Get formatting from style+  let (bold, italic) = case styleIdx of+        Just idx | idx >= 0 && idx < V.length (styleFonts styles) ->+          let font = styleFonts styles V.! idx+           in (fontBold font, fontItalic font)+        _ -> (False, False)++  return $ XlsxCell cellRefParsed value bold italic++-- Helper functions+loadXMLFromArchive :: Archive -> FilePath -> Either Text Element+loadXMLFromArchive archive path = do+  entry <- maybeToEither ("Entry not found: " <> T.pack path) $+           findEntryByPath path archive+  parseXMLFromEntry entry++parseXMLFromEntry :: Entry -> Either Text Element+parseXMLFromEntry entry =+  let lazyText = TL.decodeUtf8 $ fromEntry entry+   in parseXMLElement lazyText++loadRelationships :: Archive -> FilePath -> Either Text [(Text, Text)]+loadRelationships archive relsPath =+  case findEntryByPath relsPath archive of+    Nothing -> Right []+    Just entry -> do+      relsElem <- parseXMLFromEntry entry+      let relElems = onlyElems $ elContent relsElem+      return $ mapMaybe extractRel relElems+  where+    extractRel el = do+      relId <- findAttr (unqual "Id") el+      target <- findAttr (unqual "Target") el+      return (relId, target)++relsPathFor :: FilePath -> FilePath+relsPathFor path =+  let (dir, file) = splitFileName path+   in dir ++ "/_rels/" ++ file ++ ".rels"++findRelWithTarget :: [(Text, Text)] -> Text -> Maybe (Text, Text)+findRelWithTarget rels targetName =+  find (\(_, target) -> targetName `T.isInfixOf` target) rels++maybeToEither :: Text -> Maybe a -> Either Text a+maybeToEither err Nothing = Left err+maybeToEither _ (Just x) = Right x++getAllText :: Element -> Text+getAllText el =+  let textFromContent (Text cdata) = cdData cdata+      textFromContent (Elem e) = getAllText e+      textFromContent _ = ""+      texts = map textFromContent (elContent el)+   in T.unwords $ filter (not . T.null) texts++addContext :: Either Text a -> Text -> Either Text a+addContext (Right x) _ = Right x+addContext (Left err) ctx = Left (err <> " (context: " <> ctx <> ")")
+ src/Text/Pandoc/Readers/Xlsx/Sheets.hs view
@@ -0,0 +1,112 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+   Module      : Text.Pandoc.Readers.Xlsx.Sheets+   Copyright   : © 2025 Anton Antic+   License     : GNU GPL, version 2 or above++   Maintainer  : Anton Antic <anton@everworker.ai>+   Stability   : alpha+   Portability : portable++Conversion of XLSX sheets to Pandoc AST.+-}+module Text.Pandoc.Readers.Xlsx.Sheets+  ( xlsxToOutput+  ) where++import qualified Data.Map.Strict as M+import qualified Data.Text as T+import Data.List (sort, dropWhileEnd)+import Data.Char (isSpace)+import Text.Pandoc.Definition+import Text.Pandoc.Options (ReaderOptions)+import Text.Pandoc.Readers.Xlsx.Parse+import Text.Pandoc.Readers.Xlsx.Cells+import qualified Text.Pandoc.Builder as B++-- | Convert XLSX to Pandoc output+xlsxToOutput :: ReaderOptions -> Xlsx -> (Meta, [Block])+xlsxToOutput _opts xlsx =+  let sheets = xlsxSheets xlsx+      sheetBlocks = concatMap sheetToBlocks sheets+   in (mempty, sheetBlocks)++-- | Convert sheet to blocks (header + table)+sheetToBlocks :: XlsxSheet -> [Block]+sheetToBlocks sheet =+  let SheetId n = sheetId sheet+      name = sheetName sheet+      sheetIdent = "sheet-" <> T.pack (show n)+      header = Header 2 (sheetIdent, [], []) (B.toList (B.text name))++      -- Convert cells to table+      tableBlock = case cellsToTable sheet of+        Just tbl -> [tbl]+        Nothing -> []  -- Empty sheet+   in header : tableBlock++-- | Convert cells to Pandoc Table+cellsToTable :: XlsxSheet -> Maybe Block+cellsToTable sheet+  | M.null (sheetCells sheet) = Nothing+  | otherwise =+      let cells = sheetCells sheet+          -- Get bounds+          refs = sort $ M.keys cells+          minCol = minimum $ map cellRefCol refs+          maxCol = maximum $ map cellRefCol refs+          minRow = minimum $ map cellRefRow refs+          maxRow = maximum $ map cellRefRow refs++          -- Build dense grid+          grid = [ [ M.lookup (CellRef col row) cells+                   | col <- [minCol..maxCol]+                   ]+                 | row <- [minRow..maxRow]+                 ]++          -- First row is header (simple heuristic)+          (headerRow, bodyRows) = case grid of+            (h:bs) -> (h, bs)+            [] -> ([], [])++          -- Filter out trailing empty rows (rows with only whitespace)+          filteredBodyRows = dropWhileEnd isEmptyRow bodyRows++          makeCell mcell = case mcell of+            Just cell ->+              let inlines = cellToInlines cell+               in Cell nullAttr AlignDefault (RowSpan 1) (ColSpan 1) [Plain inlines]+            Nothing ->+              Cell nullAttr AlignDefault (RowSpan 1) (ColSpan 1) [Plain []]++          numCols = length headerRow+          colSpec = replicate numCols (AlignDefault, ColWidthDefault)+          thead = TableHead nullAttr [Row nullAttr $ map makeCell headerRow]+          tbody = [TableBody nullAttr 0 [] $ map (Row nullAttr . map makeCell) filteredBodyRows]+          tfoot = TableFoot nullAttr []++       in Just $ Table nullAttr (Caption Nothing []) colSpec thead tbody tfoot++-- | Check if a row contains only whitespace or empty cells+isEmptyRow :: [Maybe XlsxCell] -> Bool+isEmptyRow = all isEmptyCell+  where+    isEmptyCell Nothing = True+    isEmptyCell (Just cell) = case cellValue cell of+      EmptyValue -> True+      TextValue t -> T.all isSpace t+      NumberValue _ -> False++-- | Convert cell to Pandoc inlines+cellToInlines :: XlsxCell -> [Inline]+cellToInlines cell =+  let base = case cellValue cell of+        TextValue t -> B.toList $ B.text t+        NumberValue n -> [Str $ T.pack $ show n]+        EmptyValue -> []++      applyBold inls = if cellBold cell then [Strong inls] else inls+      applyItalic inls = if cellItalic cell then [Emph inls] else inls++   in applyItalic $ applyBold base
src/Text/Pandoc/RoffChar.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.RoffChar-   Copyright   : Copyright (C) 2007-2023 John MacFarlane+   Copyright   : Copyright (C) 2007-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -19,24 +19,25 @@ import qualified Data.Text as T  -- | These are the escapes specifically mentioned in groff_man(7),--- plus @ and ellipsis.+-- plus @ and ellipsis. We use the \(aq form when possible (with+-- two-letter escapes), because these are compatible with all forms+-- of roff (#10716). standardEscapes :: [(Char, T.Text)] standardEscapes =   [ ('\160', "\\ ")-  , ('\'', "\\[aq]")-  , ('‘', "\\[oq]")-  , ('’', "\\[cq]")-  , ('"', "\\[dq]")-  , ('“', "\\[lq]")-  , ('”', "\\[rq]")-  , ('—', "\\[em]")-  , ('–', "\\[en]")-  , ('`', "\\[ga]")-  , ('^', "\\[ha]")-  , ('~', "\\[ti]")-  , ('-', "\\-")-  , ('\\', "\\[rs]")-  , ('@', "\\[at]") -- because we use @ as a table and math delimiter+  , ('\'', "\\(aq")+  , ('‘', "\\(oq")+  , ('’', "\\(cq")+  , ('"', "\\(dq")+  , ('“', "\\(lq")+  , ('”', "\\(rq")+  , ('—', "\\(em")+  , ('–', "\\(en")+  , ('`', "\\(ga")+  , ('^', "\\(ha")+  , ('~', "\\(ti")+  , ('\\', "\\(rs")+  , ('@', "\\(at") -- because we use @ as a table and math delimiter   , ('\x2026', "\\&...")  -- because u2026 doesn't render on tty   ] 
src/Text/Pandoc/Scripting.hs view
@@ -3,9 +3,9 @@ {-# LANGUAGE ScopedTypeVariables  #-} {- | Module      : Text.Pandoc.Scripting-Copyright   : © 2022-2023 Albert Krewinkel+Copyright   : © 2022-2024 Albert Krewinkel License     : GPL-2.0-or-later-Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>  Central data structure for scripting engines. -}
src/Text/Pandoc/SelfContained.hs view
@@ -4,7 +4,7 @@ {-# LANGUAGE TupleSections     #-} {- |    Module      : Text.Pandoc.SelfContained-   Copyright   : Copyright (C) 2011-2023 John MacFarlane+   Copyright   : Copyright (C) 2011-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -24,7 +24,7 @@ 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 Crypto.Hash (hashWith, SHA1(SHA1)) import Network.URI (escapeURIString) import System.FilePath (takeDirectory, takeExtension, (</>)) import Text.HTML.TagSoup@@ -43,7 +43,6 @@ 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@@ -52,8 +51,11 @@ makeDataURI (mime, raw) =   if textual      then "data:" <> mime' <> "," <> T.pack (escapeURIString isOk (toString raw))-     else "data:" <> mime' <> ";base64," <> toText (encode raw)+     else "data:" <> mime' <> ";base64," <> toText (encode raw')   where textual = "text/" `T.isPrefixOf` mime+        raw' = if "+xml" `T.isSuffixOf` mime+                  then B.filter (/= '\r') raw  -- strip off CRs+                  else raw         mime' = if textual && T.any (== ';') mime                    then mime <> ";charset=utf-8"                    else mime  -- mime type already has charset@@ -87,7 +89,7 @@       ((t:xs') ++) <$> convertTags rest convertTags (t@(TagOpen "script" as):tc@(TagClose "script"):ts) =   case fromAttrib "src" t of-       ""  -> (t:) <$> convertTags ts+       ""  -> ([t, tc] ++) <$> convertTags ts        src -> do            let typeAttr = fromAttrib "type" t            res <- getData typeAttr src@@ -102,7 +104,9 @@                      "application/x-javascript" `T.isPrefixOf` mime) &&                      not ("</script" `B.isInfixOf` bs) ->                      return $-                       TagOpen "script" [("type", typeAttr)|not (T.null typeAttr)]+                       TagOpen "script" [(k,v) | (k,v) <- as+                                               , k == "type" ||+                                                 "data-" `T.isPrefixOf` k]                        : TagText (toText bs)                        : TagClose "script"                        : rest@@ -124,7 +128,8 @@                      (("href",dataUri) : [(x,y) | (x,y) <- as, x /= "href"]) :                      rest                 Fetched (mime, bs)-                  | "text/css" `T.isPrefixOf` mime+                  | ("text/css" `T.isPrefixOf` mime ||+                      fromAttrib "rel" t == "stylesheet")                     && T.null (fromAttrib "media" t)                     && not ("</" `B.isInfixOf` bs) -> do                       rest <- convertTags $@@ -145,7 +150,11 @@ convertTags (t@(TagOpen tagname as):ts)   | any (isSourceAttribute tagname) as      = do-       as' <- mapM processAttribute as+       let inlineSvgs = tagname == "img" &&+                        case T.words <$> lookup "class" as of+                          Nothing -> False+                          Just cs -> "inline-svg" `elem` cs+       as' <- mapM (processAttribute inlineSvgs) as        let attrs = addRole "img" $ addAriaLabel $ rights as'        let svgContents = lefts as'        rest <- convertTags ts@@ -200,17 +209,16 @@                       return $ TagOpen "svg" attrs'' :                                  map ensureUniqueId tags' ++ rest'                     _ -> return $ TagOpen tagname attrs : rest-  where processAttribute (x,y) =+  where processAttribute inlineSvgs (x,y) =            if isSourceAttribute tagname (x,y)               then do                 res <- getData (fromAttrib "type" t) y                 case res of                   AlreadyDataURI enc -> return $ Right (x, enc)-                  Fetched ("image/svg+xml", bs) -> do+                  Fetched ("image/svg+xml", bs) | inlineSvgs -> do                     -- we filter CR in the hash to ensure that Windows                     -- and non-Windows tests agree:-                    let hash = T.pack $ take 20 $ showDigest $-                                        sha1 $ L.fromStrict+                    let hash = T.pack $ take 20 $ show $ hashWith SHA1                                              $ B.filter (/='\r') bs                     return $ Left (hash, getSvgTags (toText bs))                   Fetched (mt,bs) -> return $ Right (x, makeDataURI (mt,bs))@@ -258,10 +266,13 @@   dropPointZero t = case T.stripSuffix ".0" t of                        Nothing -> t                        Just t' -> t'-  combinedAttrs = imgAttrs +++  combinedAttrs =+    [(k, v) | (k, v) <- imgAttrs+            , k /= "class"] ++     [(k, v) | (k, v) <- svgAttrs             , isNothing (lookup k imgAttrs)-            , k `notElem` ["xmlns", "xmlns:xlink", "version"]]+            , k `notElem` ["xmlns", "xmlns:xlink", "version", "class"]] +++    mergedClasses   parseViewBox t =     case map (safeRead . addZero) $ T.words t of       [Just llx, Just lly, Just urx, Just ury] -> Just (llx, lly, urx, ury)@@ -274,6 +285,9 @@         lookup "viewBox" svgAttrs >>= parseViewBox   (mbHeight :: Maybe Int) = lookup "height" combinedAttrs >>= safeRead   (mbWidth :: Maybe Int) = lookup "width" combinedAttrs >>= safeRead+  mergedClasses = case (lookup "class" imgAttrs, lookup "class" svgAttrs) of+                    (Just c1, Just c2) -> [("class", c1 <> " " <> c2)]+                    _ -> []  cssURLs :: PandocMonad m         => FilePath -> ByteString -> m ByteString@@ -405,17 +419,22 @@                   return res                else return raw'       return $ Fetched (mime, result)-   handler e = case e of-                 PandocResourceNotFound r -> do-                   report $ CouldNotFetchResource r ""-                   return $ CouldNotFetch e-                 PandocHttpError u er -> do-                   report $ CouldNotFetchResource u (tshow er)-                   return $ CouldNotFetch e-                 _ -> throwError e---+   handler e+      -- If fetch failed and we have a fragment and/or query,+      -- try the fetch again without these, since the resource+      -- may be local (see #1477, #11021)+     | T.any (\c -> c == '?' || c == '#') src && not (isURI src)+       = getData mimetype (removeQueryAndFragment src)+     | otherwise+       = case e of+          PandocResourceNotFound r -> do+            report $ CouldNotFetchResource r ""+            return $ CouldNotFetch e+          PandocHttpError u er -> do+            report $ CouldNotFetchResource u er+            return $ CouldNotFetch e+          _ -> throwError e+   removeQueryAndFragment = T.takeWhile (\c -> c /= '#' && c /= '?')  -- | Convert HTML into self-contained HTML, incorporating images, -- scripts, and CSS using data: URIs.
src/Text/Pandoc/Shared.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE BangPatterns          #-} {-# LANGUAGE CPP                   #-} {-# LANGUAGE FlexibleContexts      #-} {-# LANGUAGE MultiParamTypeClasses #-}@@ -8,7 +9,7 @@ {-# LANGUAGE OverloadedStrings     #-} {- |    Module      : Text.Pandoc.Shared-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -50,22 +51,20 @@                      linesToPara,                      figureDiv,                      makeSections,+                     makeSectionsWithOffsets,                      combineAttr,                      uniqueIdent,                      inlineListToIdentifier,                      textToIdentifier,                      isHeaderBlock,-                     headerShift,-                     stripEmptyParagraphs,+                     hasLineBreaks,                      onlySimpleTableCells,                      isTightList,                      taskListItemFromAscii,                      taskListItemToAscii,                      handleTaskListItem,                      addMetaField,-                     eastAsianLineBreakFilter,                      htmlSpanLikeElements,-                     filterIpynbOutput,                      formatCode,                      -- * TagSoup HTML handling                      renderTags',@@ -93,8 +92,8 @@ import Data.Char (isAlpha, isLower, isSpace, isUpper, toLower, isAlphaNum,                   generalCategory, GeneralCategory(NonSpacingMark,                   SpacingCombiningMark, EnclosingMark, ConnectorPunctuation))-import Data.List (find, foldl', groupBy, intercalate, intersperse,-                  union, sortOn)+import Data.List (find, groupBy, intercalate, intersperse, union)+import qualified Data.List as L import qualified Data.Map as M import Data.Maybe (mapMaybe) import Data.Monoid (Any (..) )@@ -102,6 +101,7 @@ import Data.Sequence (ViewL (..), ViewR (..), viewl, viewr) import qualified Data.Set as Set import qualified Data.Text as T+import qualified Text.Emoji as Emoji import System.Directory import System.FilePath (isPathSeparator, splitDirectories) import qualified System.FilePath.Posix as Posix@@ -113,7 +113,6 @@ import Text.Pandoc.Asciify (toAsciiText) import Text.Pandoc.Definition import Text.Pandoc.Extensions (Extensions, Extension(..), extensionEnabled)-import Text.Pandoc.Generic (bottomUp) import Text.DocLayout (charWidth) import Text.Pandoc.Walk -- for addPandocAttributes:@@ -142,23 +141,27 @@ -- /not/ indices but text widths, which will be different for East Asian -- characters, emojis, etc. splitTextByIndices :: [Int] -> T.Text -> [T.Text]-splitTextByIndices ns = splitTextByRelIndices (zipWith (-) ns (0:ns)) . T.unpack+splitTextByIndices ns = splitByRelWidths (zipWith (-) ns (0:ns))  where-  splitTextByRelIndices [] cs = [T.pack cs]-  splitTextByRelIndices (x:xs) cs =-    let (first, rest) = splitAt' x cs-     in T.pack first : splitTextByRelIndices xs rest+  splitByRelWidths [] t = [t]+  splitByRelWidths (w:ws) t =+    let (first, rest) = splitAtWidth w t+     in first : splitByRelWidths ws rest --- | Returns a pair whose first element is a prefix of @t@ and that has--- width @n@, and whose second is the remainder of the string.+-- | Split a @Text@ at a given display width, where width is determined+-- by 'charWidth' (East Asian characters, emojis, etc. count as 2). -- -- Note: Do *not* replace this with 'T.splitAt', which is not sensitive -- to character widths!-splitAt' :: Int {-^ n -} -> [Char] {-^ t -} -> ([Char],[Char])-splitAt' _ []          = ([],[])-splitAt' n xs | n <= 0 = ([],xs)-splitAt' n (x:xs)      = (x:ys,zs)-  where (ys,zs) = splitAt' (n - charWidth x) xs+splitAtWidth :: Int -> T.Text -> (T.Text, T.Text)+splitAtWidth n t+  | n <= 0    = (T.empty, t)+  | otherwise = T.splitAt (go 0 0 t) t+  where+    go !idx !w t'+      | w >= n    = idx+      | T.null t' = idx+      | otherwise = go (idx + 1) (w + charWidth (T.head t')) (T.tail t')  -- -- Text processing@@ -239,20 +242,23 @@ toRomanNumeral :: Int -> T.Text toRomanNumeral x   | x >= 4000 || x < 0 = "?"-  | x >= 1000 = "M" <> toRomanNumeral (x - 1000)-  | x >= 900  = "CM" <> toRomanNumeral (x - 900)-  | x >= 500  = "D" <> toRomanNumeral (x - 500)-  | x >= 400  = "CD" <> toRomanNumeral (x - 400)-  | x >= 100  = "C" <> toRomanNumeral (x - 100)-  | x >= 90   = "XC" <> toRomanNumeral (x - 90)-  | x >= 50   = "L"  <> toRomanNumeral (x - 50)-  | x >= 40   = "XL" <> toRomanNumeral (x - 40)-  | x >= 10   = "X" <> toRomanNumeral (x - 10)-  | x == 9    = "IX"-  | x >= 5    = "V" <> toRomanNumeral (x - 5)-  | x == 4    = "IV"-  | x >= 1    = "I" <> toRomanNumeral (x - 1)-  | otherwise = ""+  | otherwise = T.pack (go x)+  where+    go n+      | n >= 1000 = 'M'       : go (n - 1000)+      | n >= 900  = 'C' : 'M' : go (n - 900)+      | n >= 500  = 'D'       : go (n - 500)+      | n >= 400  = 'C' : 'D' : go (n - 400)+      | n >= 100  = 'C'       : go (n - 100)+      | n >= 90   = 'X' : 'C' : go (n - 90)+      | n >= 50   = 'L'       : go (n - 50)+      | n >= 40   = 'X' : 'L' : go (n - 40)+      | n >= 10   = 'X'       : go (n - 10)+      | n == 9    = "IX"+      | n >= 5    = 'V'       : go (n - 5)+      | n == 4    = "IV"+      | n >= 1    = 'I'       : go (n - 1)+      | otherwise = []  -- | Convert tabs to spaces. Tabs will be preserved if tab stop is set to 0. tabFilter :: Int       -- ^ Tab stop@@ -265,7 +271,7 @@          in  if T.null s2                 then s1                 else s1 <> T.replicate-                       (tabStop - (T.length s1 `mod` tabStop)) (T.pack " ")+                       (tabStop - (T.length s1 `mod` tabStop)) " "                        <> go (T.drop 1 s2)  --@@ -302,7 +308,7 @@   :: forall b . HasAttributes (Cm () b) => [(T.Text, T.Text)] -> b -> b addPandocAttributes [] bs = bs addPandocAttributes kvs bs =-  unCm . addAttributes (("wrapper","1"):kvs) $ (Cm bs :: Cm () b)+  unCm . addAttributes kvs $ (Cm bs :: Cm () b)  -- | Generate infinite lazy list of markers for an ordered list, -- depending on list attributes.@@ -411,9 +417,9 @@   let (others, final) = (init items, last items)   in  case reverse (B.toList final) of            (Para a:xs)-             | null [Para x | Para x <- xs ++ concatMap B.toList others]+             | not (any isPara xs || any (any isPara . B.toList) others)              -> others ++ [B.fromList (reverse (Plain a : xs))]-           _ | null [Para x | Para x <- concatMap B.toList items]+           _ | not (any (any isPara . B.toList) items)              -> items            _ -> map (fmap plainToPara) items @@ -469,7 +475,7 @@ -- | Convert Pandoc inline list to plain text identifier. inlineListToIdentifier :: Extensions -> [Inline] -> T.Text inlineListToIdentifier exts =-  textToIdentifier exts . stringify . walk unEmojify+  textToIdentifier exts . stringify . unEmojify   where     unEmojify :: [Inline] -> [Inline]     unEmojify@@ -477,7 +483,10 @@         extensionEnabled Ext_ascii_identifiers exts = walk unEmoji       | otherwise = id     unEmoji (Span ("",["emoji"],[("data-emoji",ename)]) _) = Str ename+    unEmoji (Str t) = Str (Emoji.replaceEmojis emojisToAliases t)     unEmoji x = x+    emojisToAliases t [] = t+    emojisToAliases _ (a:_) = a  -- | Convert string to plain text identifier. textToIdentifier :: Extensions -> T.Text -> T.Text@@ -513,12 +522,20 @@ -- adjusted so that the lowest header level is n. -- (There may still be gaps in header level if the author leaves them.) makeSections :: Bool -> Maybe Int -> [Block] -> [Block]-makeSections numbering mbBaseLevel bs =-  S.evalState (go bs) []+makeSections = makeSectionsWithOffsets []++-- | Like 'makeSections', but with a parameter for number offsets+-- (a list of 'Int's, the first of which is added to the level 1+-- section number, the second to the level 2, and so on).+makeSectionsWithOffsets :: [Int] -> Bool -> Maybe Int -> [Block] -> [Block]+makeSectionsWithOffsets numoffsets numbering mbBaseLevel bs =+  S.evalState (go bs) numoffsets  where   getLevel (Header level _ _) = Min level   getLevel _ = Min 99-  minLevel = getMin $ query getLevel bs+  minLevel = if all (== 0) numoffsets+                then getMin $ query getLevel bs+                else 1 -- see #5071, for backwards compatibility   go :: [Block] -> S.State [Int] [Block]   go (Header level (ident,classes,kvs) title':xs) = do     lastnum <- S.get@@ -540,9 +557,14 @@                         ("number", T.intercalate "." (map tshow newnum)) : kvs                   _ -> kvs     let divattr = (ident, "section":classes, kvs')-    let attr = ("",classes,kvs')+    let isHeadingAttr ("epub:type",_) = False+        isHeadingAttr ("role",v) =+          v `elem` ["tab", "presentation", "none", "treeitem",+                    "menuitem", "button", "heading"]+        isHeadingAttr _ = True+    let hattr = ("",classes, filter isHeadingAttr kvs')     return $-      Div divattr (Header level' attr title' : sectionContents') : rest'+      Div divattr (Header level' hattr title' : sectionContents') : rest'   go (Div divattr@(dident,dclasses,_) (Header level hattr title':ys) : xs)       | all (\case                Header level' _ _ -> level' > level@@ -595,34 +617,23 @@                      x  -> x     numIdent n = baseIdent <> "-" <> tshow n +-- | True if inlines include a LineBreak (possibly embedded), with the exception+-- of line breaks in Notes.+hasLineBreaks :: [Inline] -> Bool+hasLineBreaks = getAny . query isLineBreak . walk removeNote+  where+    removeNote :: Inline -> Inline+    removeNote (Note _) = Str ""+    removeNote x        = x+    isLineBreak :: Inline -> Any+    isLineBreak LineBreak = Any True+    isLineBreak _         = Any False+ -- | True if block is a Header block. isHeaderBlock :: Block -> Bool isHeaderBlock Header{} = True isHeaderBlock _        = False --- | Shift header levels up or down.-headerShift :: Int -> Pandoc -> Pandoc-headerShift n (Pandoc meta (Header m _ ils : bs))-  | n < 0-  , m + n == 0 = headerShift n $-                 B.setTitle (B.fromList ils) $ Pandoc meta bs-headerShift n (Pandoc meta bs) = Pandoc meta (walk shift bs)-- where-   shift :: Block -> Block-   shift (Header level attr inner)-     | level + n > 0  = Header (level + n) attr inner-     | otherwise      = Para inner-   shift x            = x---- | Remove empty paragraphs.-stripEmptyParagraphs :: Pandoc -> Pandoc-stripEmptyParagraphs = walk go-  where go :: [Block] -> [Block]-        go = filter (not . isEmptyParagraph)-        isEmptyParagraph (Para []) = True-        isEmptyParagraph _         = False- -- | Detect if table rows contain only cells consisting of a single -- paragraph that has no @LineBreak@. onlySimpleTableCells :: [[[Block]]] -> Bool@@ -692,64 +703,10 @@         tolist (MetaList ys) = ys         tolist y             = [y] --- | Remove soft breaks between East Asian characters.-eastAsianLineBreakFilter :: Pandoc -> Pandoc-eastAsianLineBreakFilter = bottomUp go-  where go (x:SoftBreak:y:zs)-          | Just (_, b) <- T.unsnoc $ stringify x-          , Just (c, _) <- T.uncons $ stringify y-          , charWidth b == 2-          , charWidth c == 2-          = x:y:zs-          | otherwise-          = x:SoftBreak:y:zs-        go xs-          = xs- -- | Set of HTML elements that are represented as Span with a class equal as -- the element tag itself. htmlSpanLikeElements :: Set.Set T.Text-htmlSpanLikeElements = Set.fromList ["kbd", "mark", "dfn"]---- | Process ipynb output cells.  If mode is Nothing,--- remove all output.  If mode is Just format, select--- best output for the format.  If format is not ipynb,--- strip out ANSI escape sequences from CodeBlocks (see #5633).-filterIpynbOutput :: Maybe Format -> Pandoc -> Pandoc-filterIpynbOutput mode = walk go-  where go (Div (ident, "output":os, kvs) bs) =-          case mode of-            Nothing  -> Div (ident, "output":os, kvs) []-            -- "best" for ipynb includes all formats:-            Just fmt-              | fmt == Format "ipynb"-                          -> Div (ident, "output":os, kvs) bs-              | otherwise -> Div (ident, "output":os, kvs) $-                              walk removeANSI $-                              take 1 $ sortOn rank bs-                 where-                  rank (RawBlock (Format "html") _)-                    | fmt == Format "html" = 1 :: Int-                    | fmt == Format "markdown" = 3-                    | otherwise = 4-                  rank (RawBlock (Format "latex") _)-                    | fmt == Format "latex" = 1-                    | fmt == Format "markdown" = 3-                    | otherwise = 4-                  rank (RawBlock f _)-                    | fmt == f = 1-                    | otherwise = 4-                  rank (Para [Image{}]) = 2-                  rank _ = 3-                  removeANSI (CodeBlock attr code) =-                    CodeBlock attr (removeANSIEscapes code)-                  removeANSI x = x-                  removeANSIEscapes t-                    | Just cs <- T.stripPrefix "\x1b[" t =-                        removeANSIEscapes $ T.drop 1 $ T.dropWhile (/='m') cs-                    | Just (c, cs) <- T.uncons t = T.cons c $ removeANSIEscapes cs-                    | otherwise = ""-        go x = x+htmlSpanLikeElements = Set.fromList ["kbd", "mark", "dfn", "abbr"]  -- | Reformat 'Inlines' as code, putting the stringlike parts in 'Code' -- elements while bringing other inline formatting outside.@@ -778,11 +735,12 @@ -- | Render HTML tags. renderTags' :: [Tag T.Text] -> T.Text renderTags' = renderTagsOptions-               renderOptions{ optMinimize = matchTags ["hr", "br", "img",-                                                       "meta", "link", "col",-                                                       "use", "path", "rect"]-                            , optRawTag   = matchTags ["script", "style"] }-              where matchTags tags = flip elem tags . T.toLower+               renderOptions{ optMinimize = \t -> T.toLower t `Set.member` minimizeTags+                            , optRawTag   = \t -> T.toLower t `Set.member` rawTags }+  where+    minimizeTags = Set.fromList ["hr","br","img","meta","link","col",+                                 "use","path","rect"]+    rawTags = Set.fromList ["script","style"]  -- -- File handling@@ -798,7 +756,7 @@ -- | Canonicalizes a file path by removing redundant @.@ and @..@. makeCanonical :: FilePath -> FilePath makeCanonical = Posix.joinPath . transformPathParts . splitDirectories- where  transformPathParts = reverse . foldl' go []+ where  transformPathParts = reverse . L.foldl' go []         go as        "."  = as         go ("..":as) ".." = ["..", ".."] <> as         go (_:as)    ".." = as@@ -814,7 +772,7 @@ -- > collapseFilePath "parent/foo/.." ==  "parent" -- > collapseFilePath "/parent/foo/../../bar" ==  "/bar" collapseFilePath :: FilePath -> FilePath-collapseFilePath = Posix.joinPath . reverse . foldl' go [] . splitDirectories+collapseFilePath = Posix.joinPath . reverse . L.foldl' go [] . splitDirectories   where     go rs "." = rs     go r@(p:rs) ".." = case p of
src/Text/Pandoc/Slides.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Slides-   Copyright   : Copyright (C) 2012-2023 John MacFarlane+   Copyright   : Copyright (C) 2012-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>
src/Text/Pandoc/Sources.hs view
@@ -6,7 +6,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Sources-   Copyright   : Copyright (C) 2021-2023 John MacFarlane+   Copyright   : Copyright (C) 2021-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>
src/Text/Pandoc/TeX.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE FlexibleInstances #-} {- |    Module      : Text.Pandoc.TeX-   Copyright   : Copyright (C) 2017-2023 John MacFarlane+   Copyright   : Copyright (C) 2017-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>
src/Text/Pandoc/Templates.hs view
@@ -4,7 +4,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Templates-   Copyright   : Copyright (C) 2009-2023 John MacFarlane+   Copyright   : Copyright (C) 2009-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -102,17 +102,17 @@        "native"  -> return ""        "csljson" -> return ""        "json"    -> return ""-       "docx"    -> return ""+       "xml"     -> return ""        "fb2"     -> return ""        "pptx"    -> return ""        "ipynb"   -> return ""        "asciidoctor" -> getDefaultTemplate "asciidoc"        "asciidoc_legacy" -> getDefaultTemplate "asciidoc"+       "docx"    -> getDefaultTemplate "openxml"        "odt"     -> getDefaultTemplate "opendocument"        "html"    -> getDefaultTemplate "html5"        "docbook" -> getDefaultTemplate "docbook5"        "epub"    -> getDefaultTemplate "epub3"-       "beamer"  -> getDefaultTemplate "latex"        "jats"    -> getDefaultTemplate "jats_archiving"        "markdown_strict"   -> getDefaultTemplate "markdown"        "multimarkdown"     -> getDefaultTemplate "markdown"@@ -121,6 +121,11 @@        "markdown_phpextra" -> getDefaultTemplate "markdown"        "gfm"               -> getDefaultTemplate "commonmark"        "commonmark_x"      -> getDefaultTemplate "commonmark"+       "bbcode_phpbb"      -> getDefaultTemplate "bbcode"+       "bbcode_fluxbb"     -> getDefaultTemplate "bbcode"+       "bbcode_steam"      -> getDefaultTemplate "bbcode"+       "bbcode_hubzilla"   -> getDefaultTemplate "bbcode"+       "bbcode_xenforo"    -> getDefaultTemplate "bbcode"        _        -> do          let fname = "templates" </> "default" <.> T.unpack format          readDataFile fname >>= toTextM fname
+ src/Text/Pandoc/Transforms.hs view
@@ -0,0 +1,169 @@+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE StrictData          #-}+{- |+   Module      : Text.Pandoc.Transforms+   Copyright   : © 2006-2024 John MacFarlane+   License     : GPL-2.0-or-later+   Maintainer  : John MacFarlane <jgm@berkeley@edu>++Transformation of a Pandoc document post-parsing+-}+module Text.Pandoc.Transforms+  ( Transform+  , applyTransforms+  , adjustLinksAndIds+  , eastAsianLineBreakFilter+  , filterIpynbOutput+  , headerShift+  ) where++import Data.List (sortOn)+import Data.Text (Text)+import Network.URI (unEscapeString)+import Text.DocLayout (charWidth)+import Text.Pandoc.Definition+  ( Pandoc (..), Attr, Block (..), Format (..), Inline (..) )+import Text.Pandoc.Generic (bottomUp)+import Text.Pandoc.Options (Extensions)+import Text.Pandoc.Shared (stringify, textToIdentifier)+import Text.Pandoc.Walk (walk)+import qualified Data.Text as T+import qualified Text.Pandoc.Builder as B++-- | Transformation of a Pandoc document post-parsing+type Transform = Pandoc -> Pandoc++-- | Apply a list of transforms to a document, in order.+applyTransforms :: Monad m => [Transform] -> Pandoc -> m Pandoc+applyTransforms transforms d = return $ foldr ($) d transforms++-- | Prefixes identifiers with a string derived from the filepath of+-- @thisfile@; fixes links to targets in @allfiles@ accordingly.+adjustLinksAndIds :: Extensions        -- ^ defines how IDs are generated+                  -> Text              -- ^ thisfile+                  -> [Text]            -- ^ allfiles+                  -> Transform+adjustLinksAndIds exts thisfile allfiles+  | length allfiles > 1 = walk fixInline . walk fixBlock+  | otherwise           = id+ where+  -- fix ids in blocks+  fixBlock :: Block -> Block+  fixBlock (CodeBlock attr t) = CodeBlock (fixAttrs attr) t+  fixBlock (Header lev attr ils) = Header lev (fixAttrs attr) ils+  fixBlock (Table attr cap cols th tbs tf) =+     Table (fixAttrs attr) cap cols th tbs tf+  fixBlock (Div attr bs) = Div (fixAttrs attr) bs+  fixBlock x = x++  -- fix ids and links in inlines+  fixInline :: Inline -> Inline+  fixInline (Code attr t) = Code (fixAttrs attr) t+  fixInline (Link attr ils (url,tit)) =+    Link (fixAttrs attr) ils (fixURL url,tit)+  fixInline (Image attr ils (url,tit)) =+    Image (fixAttrs attr) ils (fixURL url,tit)+  fixInline (Span attr ils) = Span (fixAttrs attr) ils+  fixInline x = x++  -- add thisfile as prefix of identifier+  fixAttrs :: Attr -> Attr+  fixAttrs (i,cs,kvs)+    | T.null i = (i,cs,kvs)+    | otherwise =+        (T.intercalate "__"+          (filter (not . T.null) [toIdent thisfile, i]),+        cs, kvs)++  -- turns a filepath into an identifier+  toIdent :: Text -> Text+  toIdent = textToIdentifier exts . T.intercalate "__" .+            T.split (\c -> c == '/' || c == '\\')++  -- if URL begins with file from allfiles, convert to+  -- an internal link with the appropriate identifier+  fixURL :: Text -> Text+  fixURL u =+    let (a,b) = T.break (== '#') $ T.pack . unEscapeString . T.unpack $ u+        filepart = if T.null a+                      then toIdent thisfile+                      else toIdent a+        fragpart = T.dropWhile (== '#') b+     in if T.null a || a `elem` allfiles+           then "#" <> T.intercalate "__"+                         (filter (not . T.null) [filepart, fragpart])+           else u++-- | Process ipynb output cells.  If mode is Nothing,+-- remove all output.  If mode is Just format, select+-- best output for the format.  If format is not ipynb,+-- strip out ANSI escape sequences from CodeBlocks (see #5633).+filterIpynbOutput :: Maybe Format -> Pandoc -> Pandoc+filterIpynbOutput mode = walk go+  where go (Div (ident, "output":os, kvs) bs) =+          case mode of+            Nothing  -> Div (ident, "output":os, kvs) []+            -- "best" for ipynb includes all formats:+            Just fmt+              | fmt == Format "ipynb"+                          -> Div (ident, "output":os, kvs) bs+              | otherwise -> Div (ident, "output":os, kvs) $+                              walk removeANSI $+                              take 1 $ sortOn rank bs+                 where+                  rank (RawBlock (Format "html") _)+                    | fmt == Format "html" = 1 :: Int+                    | fmt == Format "markdown" = 3+                    | otherwise = 4+                  rank (RawBlock (Format "latex") _)+                    | fmt == Format "latex" = 1+                    | fmt == Format "markdown" = 3+                    | otherwise = 4+                  rank (RawBlock f _)+                    | fmt == f = 1+                    | otherwise = 4+                  rank (Para [Image{}]) = 2+                  rank _ = 3+                  removeANSI (CodeBlock attr code) =+                    CodeBlock attr (removeANSIEscapes code)+                  removeANSI x = x+                  removeANSIEscapes t+                    | Just cs <- T.stripPrefix "\x1b[" t =+                        removeANSIEscapes $ T.drop 1 $ T.dropWhile (/='m') cs+                    | Just (c, cs) <- T.uncons t = T.cons c $ removeANSIEscapes cs+                    | otherwise = ""+        go x = x++-- | Remove soft breaks between East Asian characters.+eastAsianLineBreakFilter :: Pandoc -> Pandoc+eastAsianLineBreakFilter = bottomUp go+  where go (x:SoftBreak:y:zs)+          | Just (_, b) <- T.unsnoc $ stringify x+          , Just (c, _) <- T.uncons $ stringify y+          , charWidth b == 2+          , charWidth c == 2+          = x:y:zs+          | otherwise+          = x:SoftBreak:y:zs+        go xs+          = xs++-- | Shift header levels up or down.+headerShift :: Int -> Pandoc -> Pandoc+headerShift n (Pandoc meta (Header m _ ils : bs))+  | n < 0+  , m + n == 0 = headerShift n $+                 B.setTitle (B.fromList ils) $ Pandoc meta bs+-- for this case, see #10459:+headerShift n (Pandoc meta (Div attr@(_,"section":_,_) (Header m _ ils : as) : bs))+  | n < 0+  , m + n == 0 = headerShift n $+                 B.setTitle (B.fromList ils) $ Pandoc meta (Div attr as : bs)+headerShift n (Pandoc meta bs) = Pandoc meta (walk shift bs)++ where+   shift :: Block -> Block+   shift (Header level attr inner)+     | level + n > 0  = Header (level + n) attr inner+     | otherwise      = Para inner+   shift x            = x
src/Text/Pandoc/Translations.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE OverloadedStrings          #-} {- |    Module      : Text.Pandoc.Translations-   Copyright   : Copyright (C) 2017-2023 John MacFarlane+   Copyright   : Copyright (C) 2017-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -20,9 +20,10 @@                          ) where import Text.Pandoc.Translations.Types-import Text.Pandoc.Class (PandocMonad(..), CommonState(..), toTextM, report)+import Text.Pandoc.Class (PandocMonad(..), toTextM, report)+import Text.Pandoc.Class.CommonState (CommonState(..)) import Text.Pandoc.Data (readDataFile)-import Text.Pandoc.Error (PandocError(..))+import Data.Containers.ListUtils (nubOrd) import Text.Pandoc.Logging (LogMessage(..)) import Control.Monad.Except (catchError) import qualified Data.Text as T@@ -55,34 +56,29 @@        Nothing -> return mempty  -- no language defined        Just (_, Just t) -> return t        Just (lang, Nothing) -> do  -- read from file-         let translationFile = "translations/" <> renderLang lang <> ".yaml"-         let fallbackFile = "translations/" <> langLanguage lang <> ".yaml"-         let getTrans fp = do-               txt <- readDataFile fp >>= toTextM fp-               case readTranslations txt of-                    Left e   -> do+         let translationFiles = map (\x -> "translations/" <> T.unpack x <> ".yaml")+               (nubOrd [renderLang lang,+                      langLanguage lang <> maybe "" ("-" <>) (langScript lang),+                      langLanguage lang])+         let getTrans [] = return mempty+             getTrans (fp:fps) = do+               result <- catchError (Right <$> (readDataFile fp >>= toTextM fp))+                             (\_ -> pure (Left ""))+               case result >>= readTranslations of+                  Left e+                    | null fps -> do                       report $ CouldNotLoadTranslations (renderLang lang)-                        (T.pack fp <> ": " <> e)+                                  (T.pack fp <> ": " <> e)                       -- make sure we don't try again...                       modifyCommonState $ \st ->                         st{ stTranslations = Nothing }                       return mempty-                    Right t -> do-                      modifyCommonState $ \st ->-                                  st{ stTranslations = Just (lang, Just t) }-                      return t-         catchError (getTrans $ T.unpack translationFile)-           (\_ ->-             catchError (getTrans $ T.unpack fallbackFile)-               (\e -> do-                 report $ CouldNotLoadTranslations (renderLang lang)-                          $ case e of-                               PandocCouldNotFindDataFileError _ ->-                                 "data file " <> fallbackFile <> " not found"-                               _ -> ""-                 -- make sure we don't try again...-                 modifyCommonState $ \st -> st{ stTranslations = Nothing }-                 return mempty))+                    | otherwise -> getTrans fps+                  Right t -> do+                    modifyCommonState $ \st ->+                        st{ stTranslations = Just (lang, Just t) }+                    return t+         getTrans translationFiles  -- | Get a translation from the current term map. -- Issue a warning if the term is not defined.
src/Text/Pandoc/Translations/Types.hs view
@@ -4,7 +4,7 @@ {-# LANGUAGE OverloadedStrings          #-} {- |    Module      : Text.Pandoc.Translations.Types-   Copyright   : Copyright (C) 2017-2023 John MacFarlane+   Copyright   : Copyright (C) 2017-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>
src/Text/Pandoc/URI.hs view
@@ -3,7 +3,7 @@ {-# LANGUAGE CPP #-} {- |    Module      : Text.Pandoc.URI-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -15,13 +15,21 @@                        , isURI                        , schemes                        , uriPathToPath+                       , pBase64DataURI                        ) where import qualified Network.HTTP.Types as HTTP+import Data.ByteString.Base64 (decodeLenient)+import Text.Pandoc.MIME (MimeType)+import qualified Data.ByteString as B import qualified Text.Pandoc.UTF8 as UTF8 import qualified Data.Text as T import qualified Data.Set as Set-import Data.Char (isSpace, isAscii)+import Data.Char (isSpace, isAscii, isHexDigit, chr)+import Safe (readMay) import Network.URI (URI (uriScheme), parseURI, escapeURIString)+import qualified Data.Attoparsec.Text as A+import Data.Text.Encoding (encodeUtf8)+import Control.Applicative (many, (<|>))  urlEncode :: T.Text -> T.Text urlEncode = UTF8.toText . HTTP.urlEncode True . UTF8.fromText@@ -84,18 +92,22 @@   , "xmlrpc.beep", "xmlrpc.beeps", "xmpp", "xri", "ymsgr", "z39.50", "z39.50r"   , "z39.50s"   -- Unofficial schemes-  , "doi", "isbn", "javascript", "pmid"+  , "doi", "gemini", "isbn", "javascript", "pmid"   ]  -- | Check if the string is a valid URL with a IANA or frequently used but -- unofficial scheme (see @schemes@). isURI :: T.Text -> Bool-isURI =-  -- we URI-escape non-ASCII characters because otherwise parseURI will choke:-  maybe False hasKnownScheme . parseURI . escapeURIString isAscii . T.unpack+isURI t =+  -- If it's a base 64 data: URI, avoid the expensive call to parseURI:+  case A.parseOnly (pBase64DataURI *> A.endOfInput) t of+    Right () -> True+    Left _ ->+      -- we URI-escape non-ASCII characters because otherwise parseURI will choke:+      maybe False hasKnownScheme . parseURI . escapeURIString isAscii . T.unpack $ t   where-    hasKnownScheme = (`Set.member` schemes) . T.toLower .-                     T.filter (/= ':') . T.pack . uriScheme+    hasKnownScheme =+      (`Set.member` schemes) . T.toLower . T.filter (/= ':') . T.pack . uriScheme  -- | Converts the path part of a file: URI to a regular path. -- On windows, @/c:/foo@ should be @c:/foo@.@@ -109,3 +121,39 @@ #else   path #endif++pBase64DataURI :: A.Parser (B.ByteString, MimeType)+pBase64DataURI = base64uri+ where+  base64uri = do+    A.string "data:"+    mime <- do+      n1 <- restrictedName+      A.char '/'+      n2 <- restrictedName+      mps <- many mediaParam+      pure $ n1 <> "/" <> n2 <> mconcat mps+    A.string ";base64,"+    b64 <- mconcat <$> many+              (A.takeWhile1 (A.inClass "A-Za-z0-9/+ \t\r\n") <|> percentOctet)+    A.skipWhile (== '=')+    -- this decode should be lazy:+    pure (decodeLenient (encodeUtf8 b64), mime)+  percentOctet = do+    A.char '%'+    x <- A.satisfy isHexDigit+    y <- A.satisfy isHexDigit+    case readMay ['0','x',x,y] of+      Nothing -> fail $ "Could not read percent encoded byte " <> [x,y]+      Just d -> pure $ T.singleton $ chr d+  restrictedName = do+    c <- A.satisfy (A.inClass "A-Za-z0-9")+    rest <- A.takeWhile (A.inClass "A-Za-z0-9!#$&^_.+-")+    pure $ T.singleton c <> rest+  mediaParam = do+    A.char ';'+    A.skipWhile isSpace+    k <- restrictedName+    A.char '='+    v <- A.takeWhile (/=';')+    pure $ ";" <> k <> "=" <> v
src/Text/Pandoc/UTF8.hs view
@@ -1,14 +1,14 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.UTF8-   Copyright   : Copyright (C) 2010-2023 John MacFarlane+   Copyright   : Copyright (C) 2010-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>    Stability   : alpha    Portability : portable -UTF-8 aware string IO functions that will work with GHC 6.10, 6.12, or 7.+UTF-8 aware string IO functions. -} module Text.Pandoc.UTF8 ( readFile                         , getContents
src/Text/Pandoc/UUID.hs view
@@ -1,6 +1,6 @@ {- |    Module      : Text.Pandoc.UUID-   Copyright   : Copyright (C) 2010-2023 John MacFarlane+   Copyright   : Copyright (C) 2010-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>
src/Text/Pandoc/Version.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE CPP                   #-} {- |    Module      : Text.Pandoc.Version-   Copyright   : Copyright (C) 2022-2023 John MacFarlane+   Copyright   : Copyright (C) 2022-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>
src/Text/Pandoc/Writers.hs view
@@ -5,7 +5,7 @@ {-# LANGUAGE TupleSections       #-} {- |    Module      : Text.Pandoc-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -19,6 +19,7 @@     -- * Writers: converting /from/ Pandoc format       Writer(..)     , writers+    , writeANSI     , writeAsciiDoc     , writeAsciiDocLegacy     , writeAsciiDoctor@@ -75,8 +76,16 @@     , writeTexinfo     , writeTextile     , writeTypst+    , writeXML     , writeXWiki     , writeZimWiki+    , writeVimdoc+    , writeBBCode+    , writeBBCodeSteam+    , writeBBCodeFluxBB+    , writeBBCodePhpBB+    , writeBBCodeHubzilla+    , writeBBCodeXenforo     , getWriter     ) where @@ -90,6 +99,7 @@ import Text.Pandoc.Options import qualified Text.Pandoc.UTF8 as UTF8 import Text.Pandoc.Error+import Text.Pandoc.Writers.ANSI import Text.Pandoc.Writers.AsciiDoc import Text.Pandoc.Writers.BibTeX import Text.Pandoc.Writers.ChunkedHTML@@ -126,8 +136,18 @@ import Text.Pandoc.Writers.Texinfo import Text.Pandoc.Writers.Textile import Text.Pandoc.Writers.Typst+import Text.Pandoc.Writers.XML import Text.Pandoc.Writers.XWiki import Text.Pandoc.Writers.ZimWiki+import Text.Pandoc.Writers.Vimdoc+import Text.Pandoc.Writers.BBCode (+  writeBBCode,+  writeBBCodeFluxBB,+  writeBBCodeHubzilla,+  writeBBCodePhpBB,+  writeBBCodeSteam,+  writeBBCodeXenforo,+ )  data Writer m = TextWriter (WriterOptions -> Pandoc -> m Text)               | ByteStringWriter (WriterOptions -> Pandoc -> m BL.ByteString)@@ -200,6 +220,15 @@   ,("markua"       , TextWriter writeMarkua)   ,("chunkedhtml"  , ByteStringWriter writeChunkedHTML)   ,("djot"         , TextWriter writeDjot)+  ,("ansi"         , TextWriter writeANSI)+  ,("xml"          , TextWriter writeXML)+  ,("vimdoc"       , TextWriter writeVimdoc)+  ,("bbcode"       , TextWriter writeBBCode)+  ,("bbcode_steam" , TextWriter writeBBCodeSteam)+  ,("bbcode_phpbb" , TextWriter writeBBCodePhpBB)+  ,("bbcode_fluxbb", TextWriter writeBBCodeFluxBB)+  ,("bbcode_hubzilla" , TextWriter writeBBCodeHubzilla)+  ,("bbcode_xenforo" , TextWriter writeBBCodeXenforo)   ]  -- | Retrieve writer, extensions based on formatSpec (format+extensions).
+ src/Text/Pandoc/Writers/ANSI.hs view
@@ -0,0 +1,394 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+   Module      : Text.Pandoc.Writers.ANSI+   Copyright   : © 2024 Evan Silberman+                 © 2025 Pandoc contributors+   License     : GNU GPL, version 2 or above++   Maintainer  : John MacFarlane <jgm@berkeley.edu>+   Stability   : alpha+   Portability : portable++Conversion of 'Pandoc' documents to Ansi terminal output.+-}+module Text.Pandoc.Writers.ANSI ( writeANSI ) where+import Control.Monad.State.Strict ( StateT, gets, modify, evalStateT )+import Control.Monad (foldM)+import Data.List (intersperse)+import qualified Data.Map as M+import Data.Maybe (fromMaybe)+import Data.Text (Text)+import Text.DocLayout ((<+>), ($$), ($+$))+import Text.DocTemplates (Context(..))+import Text.Pandoc.Class.PandocMonad (PandocMonad, report)+import Text.Pandoc.Definition+import Text.Pandoc.Highlighting (highlight, formatANSI)+import Text.Pandoc.Logging+import Text.Pandoc.Options+import Text.Pandoc.Shared+import Text.Pandoc.Templates (renderTemplate)+import Text.Pandoc.Writers.Math(texMathToInlines)+import Text.Pandoc.Writers.Shared+import qualified Data.Text as T+import Data.Text.Lazy (toStrict)+import qualified Text.DocLayout as D+import qualified Text.Pandoc.Highlighting as HL++hr :: D.HasChars a => D.Doc a+hr = rule 20++rule :: D.HasChars a => Int -> D.Doc a+rule n = D.literal $ D.replicateChar n '─'++data WriterState = WriterState {+    stNotes     :: [D.Doc Text]        -- Footnotes+  , stColumns   :: Int         -- Width of the rendered text block+  , stInner     :: Bool    -- Are we at the document's top-level or in a nested construct?+  , stNextFigureNum :: Int+  , stInFigure :: Bool+  , stInTable :: Bool+  }++type TW = StateT WriterState++withFewerColumns :: PandocMonad m => Int -> TW m a -> TW m a+withFewerColumns n a = do+  cols <- gets stColumns+  inner <- gets stInner+  modify $ \s -> s{stColumns = max (cols - n) 4, stInner = True}+  result <- a+  modify $ \s -> s{stColumns = cols, stInner = inner}+  return result++-- | Convert Pandoc to ANSI+writeANSI :: PandocMonad m => WriterOptions -> Pandoc -> m Text+writeANSI opts document =+  evalStateT (pandocToANSI opts document)+            WriterState { stNotes = [],+                          stColumns = (writerColumns opts),+                          stInner = False,+                          stNextFigureNum = 1,+                          stInFigure = False,+                          stInTable = False+                        }++-- | Return ANSI-styled version of document+pandocToANSI :: PandocMonad m+                => WriterOptions -> Pandoc -> TW m Text+pandocToANSI opts (Pandoc meta blocks) = do+  metadata <- metaToContext opts+                 (blockListToANSI opts)+                 (inlineListToANSI opts) meta+  let colwidth = if writerWrapText opts == WrapAuto+                    then Just $ writerColumns opts+                    else Nothing+  let title = titleBlock colwidth metadata+  let blocks' = makeSections (writerNumberSections opts) Nothing blocks+  body <- blockListToANSI opts blocks'+  notes <- gets $ reverse . stNotes+  let notemark x = D.literal (tshow (x :: Int) <> ".") <+> D.space+  let marks = map notemark [1..length notes]+  let hangWidth = foldr (max . D.offset) 0 marks+  let notepretty+       | not (null notes) =+          (case colwidth of+            Nothing -> hr+            Just w  -> D.cblock w hr)+          $+$ hangMarks hangWidth marks notes+       | otherwise = D.empty+  let main = body $+$ notepretty+  let context = defField "body" main+              $ defField "titleblock" title metadata+  return $+    case writerTemplate opts of+         Nothing  -> toStrict $ D.renderANSI colwidth main+         Just tpl -> toStrict $ D.renderANSI colwidth+                              $ renderTemplate tpl context++titleBlock :: Maybe Int -> Context Text -> D.Doc Text+titleBlock width meta =+  if null most+     then D.empty+     else (maybe id D.cblock width) $ most $+$ hr+  where+    title = D.bold (fromMaybe D.empty $ getField "title" meta)+    subtitle = fromMaybe D.empty $ getField "subtitle" meta+    author =  D.vcat $ fromMaybe [] $ getField "author" meta+    date = D.italic (fromMaybe D.empty $ getField "date" meta)+    most = (title $$ subtitle) $+$ author $+$ date++hangMarks :: Int -> [D.Doc Text] -> [D.Doc Text] -> D.Doc Text+hangMarks width markers contents =+  D.vsep (zipWith hangMark markers contents) where+    hangMark m d = D.rblock width m <+> D.nest (width + 1) d++stackMarks :: [D.Doc Text] -> [D.Doc Text] -> D.Doc Text+stackMarks markers contents = D.vsep (zipWith stack markers contents)+  where stack m d = m $$ D.nest 4 d++-- | Convert Pandoc block element to ANSI+blockToANSI :: PandocMonad m+               => WriterOptions -- ^ Options+               -> Block         -- ^ Block element+               -> TW m (D.Doc Text)++blockToANSI opts (Div _ bs) = blockListToANSI opts bs++blockToANSI opts (Plain inlines) = inlineListToANSI opts inlines++blockToANSI opts (Para inlines) = inlineListToANSI opts inlines++blockToANSI opts (LineBlock lns) = do+  let go [] = return D.blankline+      go xs = inlineListToANSI opts xs+  lns' <- mapM go lns+  return $ D.vcat lns'++blockToANSI _ b@(RawBlock _ _) = do+    report $ BlockNotRendered b+    return D.empty++blockToANSI _ HorizontalRule = return $ D.blankline $$ hr $$ D.blankline++blockToANSI opts (Header level (_, classes, kvs) inlines) = do+  contents <- inlineListToANSI opts inlines+  let secnum = fromMaybe mempty $ lookup "number" kvs+  let doNumber = writerNumberSections opts && not (T.null secnum) && "unnumbered" `notElem` classes+  let number | doNumber = D.hang (D.realLength secnum + 1) (header level (D.literal secnum) <> D.space)+             | otherwise = id+  return $ number (header level contents) $$ D.blankline where+    header 1 = (fmap T.toUpper) . D.bold+    header 2 = D.bold+    header _ = D.italic++-- The approach to code blocks and highlighting here is a best-effort with+-- existing tools. The Skylighting formatANSI function produces fully-rendered+-- results, and its line numbers are followed by a tab character, which can+-- produce less-than-ideal results depending on your terminal's tab stops. (See+-- tabs(1)). A more ambitious approach here could process SourceLines into a+-- Doc Text.+blockToANSI opts (CodeBlock attr str) = do+  table <- gets stInTable+  let highlightWithStyle s = do+        let fmt o = formatANSI o s+            result = highlight (writerSyntaxMap opts) fmt attr str+        return $ case result of+          Left _ -> defaultStyle str+          Right f -> D.literal f+  inner <- case (table, writerHighlightMethod opts) of+    (_, NoHighlighting) -> return $ defaultStyle str+    (True, _) -> return $ defaultStyle str+    (False, Skylighting s) -> highlightWithStyle s+    (False, DefaultHighlighting) -> highlightWithStyle HL.defaultStyle+    (False, IdiomaticHighlighting) -> do+      report $ CouldNotHighlight "no idiomatic highlighting in ANSI"+      return $ defaultStyle str+  return $ nest table inner+  where defaultStyle = (D.fg D.red) . D.literal+        nest False = D.nest 4+        nest True = id++blockToANSI opts (BlockQuote blocks) = do+  contents <- withFewerColumns 2 $ blockListToANSI opts blocks+  return ( D.prefixed "│ " contents $$ D.blankline)++blockToANSI opts (Table _ (Caption _ caption) colSpecs (TableHead _ thead) tbody (TableFoot _ tfoot)) = do+  let captionInlines = blocksToInlines caption+  captionMarkup <-+    if null captionInlines+       then return mempty+       else D.nest 2 <$> inlineListToANSI opts (blocksToInlines caption)+  wasTable <- gets stInTable+  modify $ \s -> s{stInTable = True}+  let tw = writerColumns opts+  let ncol = length colSpecs+  let inWidths = map snd colSpecs+  let spaceForColumns = tw - ncol + 1  -- reserve a 1-char gutter between tcols+  let claimWidth ColWidthDefault = 0+      claimWidth (ColWidth n) = floor (n * fromIntegral spaceForColumns)+  let usedSpace = sum (map claimWidth inWidths)+  let remaining = spaceForColumns - usedSpace+  let defWidth = remaining `div` length (filter (== ColWidthDefault) inWidths)+  let maxWidth ColWidthDefault = defWidth+      maxWidth k = claimWidth k+  let widths = map maxWidth inWidths+  let decor = [D.hsep $ map rule widths]+  head' <- (makeRows widths . map unRow) thead+  body' <- (makeRows widths . map unRow) (tableBodiesToRows tbody)+  foot' <- (makeRows widths . map unRow) tfoot+  modify $ \s -> s{stInTable = wasTable}+  return $ D.vcat (head' <> decor <> body' <> decor <> foot') $+$ captionMarkup+  where+    unRow (Row _ cs) = cs+    makeRows ws rows = do+      (docs, _) <- foldM (goRow ws) ([], M.empty) rows+      return $ reverse docs+    goRow _ (r, spans) [] =+      -- Empty rows are not displayed but previous row spans still apply for them.+      let spans' = M.map decrementPreviousRowSpans spans+      in  return (r, spans')+    goRow ws (r, spans) cs = do+      (d, (nextPos, spans'), _) <- foldM goCell ([], (0, spans), ws) cs+      let spans'' = decrementTrailingRowSpans nextPos spans' -- Handle previous row spans next to the end of the current row+      return (D.hcat (intersperse (D.vfill " ") $ reverse d):r, spans'')+    goCell (r, (colPos, spans), ws) cell@(Cell _ aln (RowSpan rspan) (ColSpan cspan) inner)+      | Just (ColSpan previousColSpan, spans') <- takePreviousSpansAtColumn colPos spans = do+          (r', nextPos, ws') <- makeCell r colPos ws AlignDefault previousColSpan []+          goCell (r', (nextPos, spans'), ws') cell+      | otherwise = do+          (r', nextPos, ws') <- makeCell r colPos ws aln cspan inner+          let spans' = insertCurrentSpansAtColumn colPos spans (RowSpan rspan) (ColSpan cspan)+          return (r', (nextPos, spans'), ws')+    decrementPreviousRowSpans spans@(RowSpan rspan, cspan) =+      if rspan >= 1+        then (RowSpan rspan - 1, cspan)+        else spans+    makeCell r colPos ws aln cspan inner = do+      let (ws', render) = next ws aln cspan+      innerDoc <- blockListToANSI opts inner+      return ((render innerDoc):r, colPos + cspan, ws')+    tcell AlignLeft    = D.lblock+    tcell AlignRight   = D.rblock+    tcell AlignCenter  = D.cblock+    tcell AlignDefault = D.lblock+    next ws aln cspan =+      let (this, ws') = splitAt cspan ws+          w = sum this + cspan - 1+          cell = (tcell aln) w+       in (ws', cell)++blockToANSI opts (BulletList items) = do+  contents <- withFewerColumns 2 $ mapM (blockListToANSI opts) items+  return $ D.vsep (fmap hangMark contents) where+    hangMark d = D.hang 2 (D.literal "• ") d++blockToANSI opts (OrderedList attribs items) = do+  let markers = fmap D.literal $ take (length items) $ orderedListMarkers attribs+  let hangWidth = foldr (max . D.offset) 0 markers+  contents <- withFewerColumns hangWidth $ mapM (blockListToANSI opts) items+  return $ hangMarks hangWidth markers contents <> D.cr++blockToANSI opts (DefinitionList items) = do+  labels <- mapM (inlineListToANSI opts . fst) items+  columns <- gets stColumns+  let hangWidth = foldr (max . D.offset) 0 labels+  if hangWidth > floor (toRational columns / 10 * 3)+     then do+       contents <- withFewerColumns 4 $ mapM ((mapM (blockListToANSI opts)) . snd) items+       return $ stackMarks (D.bold <$> labels) (D.vsep <$> contents) <> D.cr+     else do+       contents <- withFewerColumns hangWidth $ mapM ((mapM (blockListToANSI opts)) . snd) items+       return $ hangMarks hangWidth (D.bold <$> labels) (D.vsep <$> contents) <> D.cr++blockToANSI opts (Figure _ (Caption _ caption)  body) = do+  let captionInlines = blocksToInlines caption+  figState <- gets stInFigure+  captionMarkup <-+    if null captionInlines+       then return mempty+       else D.nest 2 <$> inlineListToANSI opts (blocksToInlines caption)+  modify $ \s -> s{stInFigure = True}+  contents <- blockListToANSI opts body+  modify $ \s -> s{stInFigure = figState}+  return $ contents $+$ captionMarkup++-- Auxiliary functions for lists:++-- | Convert list of Pandoc block elements to ANSI+blockListToANSI :: PandocMonad m+                   => WriterOptions -- ^ Options+                   -> [Block]       -- ^ List of block elements+                   -> TW m (D.Doc Text)+blockListToANSI opts blocks =+  D.vsep <$> mapM (blockToANSI opts) blocks++-- | Convert list of Pandoc inline elements to ANSI+inlineListToANSI :: PandocMonad m+                    => WriterOptions -> [Inline] -> TW m (D.Doc Text)+inlineListToANSI opts lst =+  D.hcat <$> mapM (inlineToANSI opts) lst++-- | Convert Pandoc inline element to ANSI+inlineToANSI :: PandocMonad m => WriterOptions -> Inline -> TW m (D.Doc Text)++inlineToANSI opts (Span _ lst) =+  inlineListToANSI opts lst++inlineToANSI opts (Emph lst) = do+  contents <- inlineListToANSI opts lst+  return $ D.italic contents++inlineToANSI opts (Underline lst) = do+  contents <- inlineListToANSI opts lst+  return $ D.underlined contents++inlineToANSI opts (Strong lst) = do+  contents <- inlineListToANSI opts lst+  return $ D.bold contents++inlineToANSI opts (Strikeout lst) = do+  contents <- inlineListToANSI opts lst+  return $ D.strikeout contents++inlineToANSI opts (Superscript lst) = do+  case traverse toSuperscriptInline lst of+    Just xs -> inlineListToANSI opts xs+    Nothing -> D.parens <$> inlineListToANSI opts lst++inlineToANSI opts (Subscript lst) = do+  case traverse toSubscriptInline lst of+    Just xs -> inlineListToANSI opts xs+    Nothing -> D.parens <$> inlineListToANSI opts lst++inlineToANSI opts (SmallCaps lst) = inlineListToANSI opts lst++inlineToANSI opts (Quoted SingleQuote lst) = do+  contents <- inlineListToANSI opts lst+  return $ "‘" <> contents <> "’"++inlineToANSI opts (Quoted DoubleQuote lst) = do+  contents <- inlineListToANSI opts lst+  return $ "“" <> contents <> "”"++inlineToANSI opts (Cite _  lst) = inlineListToANSI opts lst++-- Making a judgment call here that for ANSI-formatted output+-- intended for reading, we want to reflow inline Code on spaces+inlineToANSI _ (Code _ str) =+  return $ D.bg D.white $ D.fg D.red $ " " <> D.hcat flow <> " "+    where flow = intersperse D.space (D.literal <$> T.words str)++inlineToANSI _ (Str str) = return $ D.literal str++inlineToANSI opts (Math t str) = texMathToInlines t str >>= inlineListToANSI opts++inlineToANSI _ il@RawInline{} = do+  report $ InlineNotRendered il+  return ""++inlineToANSI _ LineBreak = return D.cr++inlineToANSI _ SoftBreak = return D.space++inlineToANSI _ Space = return D.space++inlineToANSI opts (Link (_, _, _) txt (src, _)) = do+  label <- inlineListToANSI opts txt+  return $ D.underlined $ D.fg D.cyan $ D.link src label++inlineToANSI opts (Image _ alt _) = do+  infig <- gets stInFigure+  if not infig then do+    alt' <- inlineListToANSI opts alt+    return $ D.brackets $ "image: " <> alt'+  else return $ D.brackets "image"++-- by construction, we should never be lacking in superscript characters+-- for the footnote number, but we'll fall back to square brackets anyway+inlineToANSI opts (Note contents) = do+  curNotes <- gets stNotes+  let newnum = tshow $ length curNotes + 1+  contents' <- blockListToANSI opts contents+  modify $ \s -> s { stNotes = contents' : curNotes }+  let super = T.pack <$> (traverse toSuperscript (T.unpack newnum))+  return $ D.literal $ fromMaybe ("[" <> newnum <> "]") super
src/Text/Pandoc/Writers/AsciiDoc.hs view
@@ -1,8 +1,9 @@+{-# LANGUAGE CPP  #-} {-# LANGUAGE LambdaCase        #-} {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Writers.AsciiDoc-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -28,12 +29,19 @@ import Control.Monad.State.Strict     ( StateT, MonadState(get), gets, modify, evalStateT ) import Data.Char (isPunctuation, isSpace)-import Data.List (delete, intercalate, intersperse)-import Data.List.NonEmpty (NonEmpty(..))-import Data.Maybe (fromMaybe, isJust)+#if MIN_VERSION_base(4,19,0)+import Data.List (delete, intercalate, intersperse, mapAccumL, uncons, sortOn, unsnoc)+#else+import Data.List (delete, intercalate, intersperse, mapAccumL, uncons, sortOn)+#endif+import Data.List.NonEmpty (NonEmpty((:|)), (<|))+import qualified Data.List.NonEmpty as NonEmpty+import Data.Maybe (fromMaybe, isJust, catMaybes)+import qualified Data.Map as M import qualified Data.Set as Set import qualified Data.Text as T import Data.Text (Text)+import Network.URI (parseURI, URI(uriScheme)) import System.FilePath (dropExtension) import Text.Pandoc.Class.PandocMonad (PandocMonad, report) import Text.Pandoc.Definition@@ -42,12 +50,18 @@ import Text.Pandoc.Options import Text.Pandoc.Parsing hiding (blankline, space) import Text.DocLayout+import Text.Pandoc.Builder (emptyCell) import Text.Pandoc.Shared import Text.Pandoc.URI import Text.Pandoc.Templates (renderTemplate) import Text.Pandoc.Writers.Shared import Text.Pandoc.Walk (walk) +#if !MIN_VERSION_base(4,19,0)+unsnoc :: [a] -> Maybe ([a], a)+unsnoc = foldr (\x -> Just . maybe ([], x) (\(~(a, b)) -> (x : a, b))) Nothing+#endif+ data WriterState = WriterState { defListMarker       :: Text                                , orderedListLevel    :: Int                                , bulletListLevel     :: Int@@ -104,7 +118,7 @@               (blockListToAsciiDoc opts)               (fmap chomp . inlineListToAsciiDoc opts)               meta-  main <- blockListToAsciiDoc opts $ makeSections False (Just 1) blocks+  main <- blockListToAsciiDoc opts $ makeSections False Nothing blocks   st <- get   let context  = defField "body" main                $ defField "toc"@@ -117,19 +131,47 @@        Nothing  -> main        Just tpl -> renderTemplate tpl context +data EscContext = Normal | InTable+  deriving (Show, Eq)+ -- | Escape special characters for AsciiDoc.-escapeString :: PandocMonad m => Text -> ADW m (Doc Text)-escapeString t = do-  parentTableLevel <- gets tableNestingLevel-  let needsEscape '{' = True-      needsEscape '|' = parentTableLevel > 0-      needsEscape _   = False-  let escChar c | needsEscape c = "\\" <> T.singleton c-                | otherwise     = T.singleton c-  if T.any needsEscape t-     then return $ literal $ T.concatMap escChar t-     else return $ literal t+escapeString :: EscContext -> Text -> Doc Text+escapeString context t+  | T.any needsEscape t+  = literal $+      case T.foldl' go (False, mempty) t of+        (True, x) -> x <> "++" -- close passthrough context+        (False, x) -> x+  | otherwise = literal t+ where+  -- Bool is True when we are in a ++ passthrough context+  go :: (Bool, Text) -> Char -> (Bool, Text)+  go (True, x) '+' = (False, x <> "++" <> "{plus}") -- close context+  go (False, x) '+' = (False, x <> "{plus}")+  go (True, x) '|'+    | context == InTable = (False, x <> "++" <> "{vbar}") -- close context+  go (False, x) '|'+    | context == InTable = (False, x <> "{vbar}")+  go (True, x) c+    | needsEscape c = (True, T.snoc x c)+    | otherwise = (False, T.snoc (x <> "++") c)+  go (False, x) c+    | needsEscape c = (True, x <> "++" <> T.singleton c)+    | otherwise = (False, T.snoc x c) +  needsEscape '{' = True+  needsEscape '+' = True+  needsEscape '`' = True+  needsEscape '*' = True+  needsEscape '#' = True+  needsEscape '_' = True+  needsEscape '<' = True+  needsEscape '>' = True+  needsEscape '[' = True+  needsEscape ']' = True+  needsEscape '\\' = True+  needsEscape '|' = True+  needsEscape _ = False  -- | Ordered list start parser for use in Para below. olMarker :: Parsec Text ParserState Char@@ -204,7 +246,10 @@ blockToAsciiDoc opts (Figure attr (Caption _ longcapt) body) = do   -- Images in figures all get rendered as individual block-level images   -- with the given caption. Non-image elements are rendered unchanged.-  capt <- inlineListToAsciiDoc opts (blocksToInlines longcapt)+  capt <- if null longcapt+             then pure mempty+             else ("." <>) . nowrap <$>+                   inlineListToAsciiDoc opts (blocksToInlines longcapt)   let renderFigElement = \case         Plain [Image imgAttr alternate (src, tit)] -> do           args <- imageArguments opts imgAttr alternate src tit@@ -213,7 +258,8 @@                 (ident, _, _) -> literal $ "[#" <> ident <> "]"           -- .Figure caption           -- image::images/logo.png[Company logo, title="blah"]-          return $ "." <> nowrap capt $$+          return $+            capt $$             figAttributes $$             "image::" <> args <> blankline         blk -> blockToAsciiDoc opts blk@@ -237,9 +283,12 @@                      else contents   let bar = text "____"   return $ bar $$ chomp contents' $$ bar <> blankline-blockToAsciiDoc opts block@(Table _ blkCapt specs thead tbody tfoot) = do-  let (caption, aligns, widths, headers, rows) =-        toLegacyTable blkCapt specs thead tbody tfoot+blockToAsciiDoc opts block@(Table _ blkCapt specs thead@(TableHead _ originalHeaders) originalTbody tfoot@(TableFoot _ originalFooters)) = do+  let (caption, aligns, widths, _, _) =+        toLegacyTable blkCapt specs thead originalTbody tfoot+  let headers = adjustEmptyRows originalHeaders+  let rows = adjustEmptyRows $ tableBodiesToRows originalTbody+  let footers = adjustEmptyRows originalFooters   caption' <- inlineListToAsciiDoc opts caption   let caption'' = if null caption                      then empty@@ -258,15 +307,19 @@                      ws        -> ws   let totalwidth :: Integer       totalwidth = floor $ sum widths * 100-  let colspec al wi = (case al of-                         AlignLeft    -> "<"-                         AlignCenter  -> "^"-                         AlignRight   -> ">"-                         AlignDefault -> "") +++  let alignmentOperator AlignLeft     = "<"+      alignmentOperator AlignCenter   = "^"+      alignmentOperator AlignRight    = ">"+      alignmentOperator AlignDefault  = ""+  let colspec al wi = (alignmentOperator al) ++                       if wi == 0 then "" else show wi ++ "%"-  let headerspec = if all null headers+  let optionSpecForRows rowList spec = if allRowsEmpty rowList then Nothing else Just spec+  let headerspec = optionSpecForRows headers "header"+  let footerspec = optionSpecForRows footers "footer"+  let optionsList = catMaybes [headerspec, footerspec]+  let optionsspec = if null optionsList                       then empty-                      else text "options=\"header\","+                      else text "options=\"" <> text (intercalate "," optionsList) <> text "\","   let widthspec = if totalwidth == 0                      then empty                      else text "width="@@ -278,7 +331,7 @@          <> doubleQuotes (text $ intercalate ","              $ zipWith colspec aligns widths')          <> text ","-         <> headerspec <> text "]"+         <> optionsspec <> text "]"    -- construct cells and recurse in case of nested tables   parentTableLevel <- gets tableNestingLevel@@ -303,19 +356,48 @@                                d <- blockListToAsciiDoc opts bs                                return $ (text "a" <> separator) $$ d -  let makeRow cells = hsep `fmap` mapM makeCell cells-  rows' <- mapM makeRow rows-  head' <- makeRow headers+  let colSpanFactor (ColSpan colSpan) = if colSpan > 1+                                          then text $ show colSpan+                                          else empty+  let rowSpanFactor (RowSpan rowSpan) = if rowSpan > 1+                                          then text $ "." ++ show rowSpan+                                          else empty++  let makeCellWithSpansAndAlignment (Cell _ alignment rowSpan colSpan blocks) = do+        let spanFactor = colSpanFactor colSpan <> rowSpanFactor rowSpan+        cell <- makeCell blocks+        let alignedCell = alignmentOperator alignment <> cell++        return $ if null spanFactor+          then alignedCell+          else spanFactor <> text "+" <> alignedCell++  let makeRow (Row attr []) = makeRow $ Row attr $ replicate (length widths') emptyCell+      makeRow (Row _ cells) = hsep `fmap` mapM makeCellWithSpansAndAlignment cells++  -- AsciiDoc only supports 1 header row and 1 footer row.+  let headerRow = Data.List.uncons $ adjustHeaders headers+  let footerRow = unsnoc $ adjustFooters footers+  let tailHeaderRows = if allRowsEmpty headers then [] else maybe [] snd headerRow+  let initFooterRows = if allRowsEmpty footers then [] else maybe [] fst footerRow+  rows' <- mapM makeRow $ tailHeaderRows ++ rows ++ initFooterRows+  head' <- case headerRow of+            Nothing -> return empty+            Just (headerRow', _) -> makeRow headerRow'+  foot <- case footerRow of+            Nothing -> return empty+            Just (_, footerRow') -> makeRow footerRow'   modify $ \st -> st{ tableNestingLevel = parentTableLevel }-  let head'' = if all null headers then empty else head'+  let head'' = if allRowsEmpty headers then empty else head'+  let foot' = if allRowsEmpty footers then empty else foot   let colwidth = if writerWrapText opts == WrapAuto                     then writerColumns opts                     else 100000-  let maxwidth = maximum $ fmap offset (head' :| rows')+  let maxwidth = maximum $ fmap offset (foot <| (head' :| rows'))   let body = if maxwidth > colwidth then vsep rows' else vcat rows'   let border = separator <> text "==="   return $-    caption'' $$ tablespec $$ border $$ head'' $$ body $$ border $$ blankline+    caption'' $$ tablespec $$ border $$ head'' $$ body $$ foot' $$ border $$ blankline blockToAsciiDoc opts (BulletList items) = do   inlist <- gets inList   modify $ \st -> st{ inList = True }@@ -343,29 +425,34 @@   contents <- mapM (definitionListItemToAsciiDoc opts) items   modify $ \st -> st{ inList = inlist }   return $ mconcat contents <> blankline++-- convert admonition and sidebar divs to asicidoc blockToAsciiDoc opts (Div (ident,classes,_) bs) = do   let identifier = if T.null ident then empty else "[[" <> literal ident <> "]]"-  let admonitions = ["attention","caution","danger","error","hint",+  let admonition_classes = ["attention","caution","danger","error","hint",                      "important","note","tip","warning"]+  let sidebar_class = "sidebar"+   contents <-        case classes of-         (l:_) | l `elem` admonitions -> do+         (l:_) | l `elem` admonition_classes || T.toLower l == sidebar_class -> do              let (titleBs, bodyBs) =                      case bs of                        (Div (_,["title"],_) ts : rest) -> (ts, rest)                        _ -> ([], bs)-             admonitionTitle <- if null titleBs ||+             let fence = if l == "sidebar" then "****" else "===="+             elemTitle <- if null titleBs ||                                    -- If title matches class, omit                                    (T.toLower (T.strip (stringify titleBs))) == l                                    then return mempty                                    else ("." <>) <$>                                          blockListToAsciiDoc opts titleBs-             admonitionBody <- blockListToAsciiDoc opts bodyBs+             elemBody <- blockListToAsciiDoc opts bodyBs              return $ "[" <> literal (T.toUpper l) <> "]" $$-                      chomp admonitionTitle $$-                      "====" $$-                      chomp admonitionBody $$-                      "===="+                      chomp elemTitle $$+                      fence $$+                      chomp elemBody $$+                      fence          _ -> blockListToAsciiDoc opts bs   return $ identifier $$ contents $$ blankline @@ -379,7 +466,7 @@   let blocksWithTasks = if isLegacy                           then blocks                           else (taskListItemToAsciiDoc blocks)-  contents <- foldM (addBlock opts) empty blocksWithTasks+  contents <- snd <$> foldM (addBlock opts) (False, empty) blocksWithTasks   modify $ \s -> s{ bulletListLevel = lev }   let marker = text (replicate (lev + 1) '*')   return $ marker <> text " " <> listBegin blocksWithTasks <>@@ -388,26 +475,32 @@ -- | Convert a list item containing text starting with @U+2610 BALLOT BOX@ -- or @U+2612 BALLOT BOX WITH X@ to asciidoctor checkbox syntax (e.g. @[x]@). taskListItemToAsciiDoc :: [Block] -> [Block]-taskListItemToAsciiDoc = handleTaskListItem toOrg listExt+taskListItemToAsciiDoc = handleTaskListItem toAd listExt   where-    toOrg (Str "☐" : Space : is) = Str "[ ]" : Space : is-    toOrg (Str "☒" : Space : is) = Str "[x]" : Space : is-    toOrg is = is+    toAd (Str "☐" : Space : is) = RawInline (Format "asciidoc") "[ ]" : Space : is+    toAd (Str "☒" : Space : is) = RawInline (Format "asciidoc") "[x]" : Space : is+    toAd is = is     listExt = extensionsFromList [Ext_task_lists]  addBlock :: PandocMonad m-         => WriterOptions -> Doc Text -> Block -> ADW m (Doc Text)-addBlock opts d b = do+         => WriterOptions -> (Bool, Doc Text) -> Block -> ADW m (Bool, Doc Text)+addBlock opts (containsContinuation, d) b = do   x <- chomp <$> blockToAsciiDoc opts b   return $     case b of-        BulletList{} -> d <> cr <> x-        OrderedList{} -> d <> cr <> x-        Para (Math DisplayMath _:_) -> d <> cr <> x-        Plain (Math DisplayMath _:_) -> d <> cr <> x-        Para{} | isEmpty d -> x-        Plain{} | isEmpty d -> x-        _ -> d <> cr <> text "+" <> cr <> x+        BulletList{}+          | containsContinuation -> (False, d <> blankline <> x)  -- see #11006+          | otherwise -> (False, d <> cr <> x)+        OrderedList (start, sty, _) _+          | containsContinuation+          , start == 1+          , sty == DefaultStyle -> (False, d <> blankline <> x)  -- see #11006+          | otherwise -> (False, d <> cr <> x)+        Para (Math DisplayMath _:_) -> (containsContinuation, d <> cr <> x)+        Plain (Math DisplayMath _:_) -> (containsContinuation, d <> cr <> x)+        Para{} | isEmpty d -> (containsContinuation, x)+        Plain{} | isEmpty d -> (containsContinuation, x)+        _ -> (True, d <> cr <> text "+" <> cr <> x)  listBegin :: [Block] -> Doc Text listBegin blocks =@@ -427,7 +520,7 @@ orderedListItemToAsciiDoc opts blocks = do   lev <- gets orderedListLevel   modify $ \s -> s{ orderedListLevel = lev + 1 }-  contents <- foldM (addBlock opts) empty blocks+  contents <- snd <$> foldM (addBlock opts) (False, empty) blocks   modify $ \s -> s{ orderedListLevel = lev }   let marker = text (replicate (lev + 1) '.')   return $ marker <> text " " <> listBegin blocks <> contents <> cr@@ -501,7 +594,9 @@                                    _           -> False        isSpacy Start (Str xs)          | Just (c, _) <- T.uncons xs = isPunctuation c || isSpace c-       isSpacy _ _ = True+       isSpacy End (Link{}) = True+       isSpacy End (Image{}) = True+       isSpacy _ _ = False  setIntraword :: PandocMonad m => Bool -> ADW m () setIntraword b = modify $ \st -> st{ intraword = b }@@ -517,45 +612,50 @@   contents <- inlineListToAsciiDoc opts lst   isIntraword <- gets intraword   let marker = if isIntraword then "__" else "_"-  return $ marker <> contents <> marker+  return $ delimited marker marker contents inlineToAsciiDoc opts (Underline lst) = do   contents <- inlineListToAsciiDoc opts lst-  return $ "[.underline]#" <> contents <> "#"+  return $ delimited "[.underline]#" "#" contents inlineToAsciiDoc opts (Strong lst) = do   contents <- inlineListToAsciiDoc opts lst   isIntraword <- gets intraword   let marker = if isIntraword then "**" else "*"-  return $ marker <> contents <> marker+  return $ delimited marker marker contents inlineToAsciiDoc opts (Strikeout lst) = do   contents <- inlineListToAsciiDoc opts lst-  return $ "[line-through]#" <> contents <> "#"+  return $ delimited "[line-through]#" "#" contents inlineToAsciiDoc opts (Superscript lst) = do   contents <- inlineListToAsciiDoc opts lst-  return $ "^" <> contents <> "^"+  return $ delimited "^" "^" contents inlineToAsciiDoc opts (Subscript lst) = do   contents <- inlineListToAsciiDoc opts lst-  return $ "~" <> contents <> "~"-inlineToAsciiDoc opts (SmallCaps lst) = inlineListToAsciiDoc opts lst+  return $ delimited "~" "~" contents+inlineToAsciiDoc opts (SmallCaps lst) = do+  contents <- inlineListToAsciiDoc opts lst+  return $ delimited "[smallcaps]#" "#" contents inlineToAsciiDoc opts (Quoted qt lst) = do   isLegacy <- gets legacy-  inlineListToAsciiDoc opts $-    case qt of-      SingleQuote-        | isLegacy     -> [Str "`"] ++ lst ++ [Str "'"]-        | otherwise    -> [Str "'`"] ++ lst ++ [Str "`'"]-      DoubleQuote-        | isLegacy     -> [Str "``"] ++ lst ++ [Str "''"]-        | otherwise    -> [Str "\"`"] ++ lst ++ [Str "`\""]+  contents <- inlineListToAsciiDoc opts lst+  pure $ case qt of+    SingleQuote+      | isLegacy     -> "`" <> contents <> "'"+      | otherwise    -> "'`" <> contents <> "`'"+    DoubleQuote+      | isLegacy     -> "``" <> contents <> "''"+      | otherwise    -> "\"`" <> contents <> "`\"" inlineToAsciiDoc _ (Code _ str) = do   isLegacy <- gets legacy   let escChar '`' = "\\'"       escChar c   = T.singleton c-  let contents = literal (T.concatMap escChar str)-  return $-    if isLegacy-       then text "`"  <> contents <> "`"-       else text "`+" <> contents <> "+`"-inlineToAsciiDoc _ (Str str) = escapeString str+  parentTableLevel <- gets tableNestingLevel+  let content+       | isLegacy = literal (T.concatMap escChar str)+       | otherwise = escapeString+                       (if parentTableLevel > 0 then InTable else Normal) str+  return $ text "`" <> content <> "`"+inlineToAsciiDoc _ (Str str) = do+  parentTableLevel <- gets tableNestingLevel+  pure $ escapeString (if parentTableLevel > 0 then InTable else Normal) str inlineToAsciiDoc _ (Math InlineMath str) = do   isLegacy <- gets legacy   modify $ \st -> st{ hasMath = True }@@ -599,9 +699,13 @@       fixCommas x = [x]    linktext <- inlineListToAsciiDoc opts $ walk (concatMap fixCommas) txt-  let isRelative = T.all (/= ':') src+  let needsLinkPrefix = case parseURI (T.unpack src) of+                          Just u -> uriScheme u `notElem` ["http:","https:",+                                                           "ftp:", "irc:",+                                                            "mailto:"]+                          _ -> True   let needsPassthrough = "--" `T.isInfixOf` src-  let prefix = if isRelative+  let prefix = if needsLinkPrefix                   then text "link:"                   else empty   let srcSuffix = fromMaybe src (T.stripPrefix "mailto:" src)@@ -631,9 +735,10 @@   contents <- inlineListToAsciiDoc opts ils   isIntraword <- gets intraword   let marker = if isIntraword then "##" else "#"-  if T.null ident && null classes-     then return contents-     else do+  case classes of+    [] | T.null ident -> return contents+    ["mark"] | T.null ident -> return $ marker <> contents <> marker+    _ -> do        let modifier = brackets $ literal $ T.unwords $             [ "#" <> ident | not (T.null ident)] ++ map ("." <>) classes        return $ modifier <> marker <> contents <> marker@@ -664,3 +769,144 @@                 then empty                 else "," <> mconcat (intersperse "," dimList)   return $ literal src <> "[" <> linktext <> linktitle <> dims <> "]"++-- | Adjust header rows for the fact that AsciiDoc only supports a single header row.+--+-- The first header row will become the single header row in AsciiDoc with the+-- other rows becoming the top body rows.+-- All cells of the first header row with a RowSpan > 1 will be mapped to+-- RowSpan 1 and the remaining RowSpans of those cells wll be added as empty+-- columns into the second row beneath them to preserve the original layout.+adjustHeaders :: [Row] -> [Row]+adjustHeaders [] = []+adjustHeaders [row] = [row]+adjustHeaders (Row attr firstHeaderCells:secondRow:remainingRows) =+  let ((_, emptyHeaderCells), headerRow) = mapAccumL adjustHeaderRowCell (0, []) firstHeaderCells+      secondRow' = applyEmptyCells secondRow emptyHeaderCells+  in  Row attr headerRow:secondRow':remainingRows+ where+  adjustHeaderRowCell (columnPosition, emptyCells) cell@(Cell cellAttr alignment (RowSpan rowSpan) (ColSpan colSpan) blocks) =+    let nextColumnPosition = columnPosition + colSpan+        adjustedHeaderCell = Cell cellAttr alignment (RowSpan 1) (ColSpan colSpan) blocks+        emptyHeaderRowCell = Cell nullAttr AlignDefault (RowSpan rowSpan - 1) (ColSpan colSpan) []+        emptyCellPosition = (columnPosition, emptyHeaderRowCell)+    in  if rowSpan > 1+          then ((nextColumnPosition, emptyCellPosition:emptyCells), adjustedHeaderCell)+          else ((nextColumnPosition, emptyCells), cell)++-- | Adjust footer rows for the fact that AsciiDoc only supports a single footer row.+--+-- The last footer row will become the single footer row in AsciiDoc with the+-- previous footer rows becoming the bottom body rows.+-- All column indices of cells whose RowSpans would reach that last footer row+-- are collected and subtracted by 1. Those collected column indices will then+-- be applied as empty columns into the last footer row to preserve the original+-- layout.+adjustFooters :: [Row] -> [Row]+adjustFooters [] = []+adjustFooters [row] = [row]+adjustFooters rows = adjustFooters' [] (0, length rows) M.empty rows+ where+  adjustFooters' _ _ _ [] = []+  adjustFooters' columnIndices _ _ [row] = [applyEmptyCells row columnIndices]+  adjustFooters' columnIndices rowInfo@(rowIndex, footerLength) previousRowSpans (row:rest) =+    -- Need to keep track of RowSpans from previous rows and how they occupy+    -- space in rows beneath them to be able to apply the correct column+    -- position of RowSpans that would reach the last footer row.+    let (previousRowSpans', row', columnIndices') = adjustFooterRow rowInfo previousRowSpans row+        rows' = adjustFooters' (columnIndices ++ columnIndices') (rowIndex + 1, footerLength) previousRowSpans' rest+    in  row':rows'++  adjustFooterRow rowInfo previousRowSpans (Row attr cells) =+    let ((nextColumnPosition, previousRowSpans'), cells') = mapAccumL (adjustFooterCell rowInfo) (0, previousRowSpans) cells+        (cells'', columnIndices) = unzip cells'++        -- Apply row spans from a previous row that are next to the end of the+        -- current row's cells to keep track of the correct column position.+        previousRowSpans'' = decrementTrailingRowSpans nextColumnPosition previousRowSpans'+    in  (previousRowSpans'', Row attr cells'', catMaybes columnIndices)++-- | Adjust footer cell for the fact that AsciiDoc only supports a single footer row.+--+-- Collects cells whose RowSpan would reach to the last footer row and applies+-- them as empty cells to that last footer row.+adjustFooterCell :: (Int, Int) -> (Int, M.Map Int (RowSpan, ColSpan)) -> Cell -> ((Int, M.Map Int (RowSpan, ColSpan)), (Cell, Maybe (Int, Cell)))+adjustFooterCell rowInfo@(rowIndex, footerLength) (columnPosition, previousSpans) cell@(Cell _ _ (RowSpan rowSpan) (ColSpan colSpan) _)+  | Just (ColSpan previousColSpan, previousSpans') <- takePreviousSpansAtColumn columnPosition previousSpans =+      -- Apply row span from a previous row that occupies this column to keep+      -- track of the correct column position.+      adjustFooterCell rowInfo (columnPosition + previousColSpan, previousSpans') cell+  | rowSpan > 1 && rowIndex + rowSpan >= footerLength =+      -- Adjust row span that would reach all the way to the last footer row and+      -- keep track of that to apply it to the last footer row.+      ((nextColumnPosition, previousRowSpans'), (decrementRowSpanInCell cell, Just (columnPosition, emptyCellWithColSpan)))+  | otherwise = ((nextColumnPosition, previousRowSpans'), (cell, Nothing))+ where+  -- Keep track of this cell's RowSpan for the rows following it.+  previousRowSpans' = insertCurrentSpansAtColumn columnPosition previousSpans (RowSpan rowSpan) (ColSpan colSpan)+  nextColumnPosition = columnPosition + colSpan+  emptyCellWithColSpan = Cell nullAttr AlignDefault (RowSpan 1) (ColSpan colSpan) []++-- | Adjust empty rows for AsciiDoc.+--+-- An empty row without any cells decrements RowSpans that cover it and is+-- removed by them to adjust for being unable to express empty rows with no+-- cells in AsciiDoc.+adjustEmptyRows :: [Row] -> [Row]+adjustEmptyRows = adjustEmptyRows' . map applyInitialRowsLeft+ where+  adjustEmptyRows' [] = []+  adjustEmptyRows' (row:rest)+    | maxRowSpan' <- maxRowSpan row+    , maxRowSpan' > 1 =+        -- Consume empty rows within the row's span.+        let followingRows = take (maxRowSpan' - 1) rest+            rows = consumeEmptyRows (row :| []) followingRows+            rest' = drop (length followingRows) rest+        in  rowFromCellsWithRowsLeft (NonEmpty.head rows) : adjustEmptyRows' (NonEmpty.tail rows ++ rest')+    | otherwise = rowFromCellsWithRowsLeft row : adjustEmptyRows' rest++  rowFromCellsWithRowsLeft (attr, cellsWithRowsLeft) = Row attr $ map fst cellsWithRowsLeft+  cellRowSpan (Cell _ _ (RowSpan rowSpan) _ _) = rowSpan++  consumeEmptyRows rows [] = NonEmpty.reverse rows+  consumeEmptyRows rows (followingRow:restRows) =+    if null (snd followingRow) && any rowHasRowSpanAndRowsLeft rows+      then consumeEmptyRows (fmap (subtractRowsLeft decrementRowSpanInCell) rows) restRows -- Consume empty row for RowSpan and remove it+      else consumeEmptyRows (followingRow <| fmap (subtractRowsLeft id) rows) restRows++  rowHasRowSpanAndRowsLeft (_, cells) = any cellHasRowSpanAndRowsLeft cells+  cellHasRowSpanAndRowsLeft (cell, rowsLeft) = cellRowSpan cell > 1 && rowsLeft >= 1++  subtractRowsLeft changeCell (attr, cells) = (attr, map (subtractRowsLeftCell changeCell) cells)++  subtractRowsLeftCell changeCell cellPair@(cell, rowsLeft)+    | rowsLeft >= 1 = (changeCell cell, rowsLeft - 1)+    | otherwise = cellPair++  applyInitialRowsLeft (Row attr cells) = (attr, map applyInitialRowsLeftCell cells)++  applyInitialRowsLeftCell cell+    | rowSpan <- cellRowSpan cell, rowSpan > 1 = (cell, rowSpan - 1) -- Minus its own row+    | otherwise = (cell, 0)++  maxRowSpan (_, []) = 0+  maxRowSpan (_, cells) = maximum $ map (cellRowSpan . fst) cells++-- | Decrement the RowSpan of a Cell if that RowSpan > 1.+decrementRowSpanInCell :: Cell -> Cell+decrementRowSpanInCell cell@(Cell attr alignment (RowSpan rowSpan) colSpan blocks) =+  if rowSpan > 1+    then Cell attr alignment (RowSpan rowSpan - 1) colSpan blocks+    else cell++-- | Apply empty table cells at the given positions inside a Row.+applyEmptyCells :: Row -> [(Int, Cell)] -> Row+applyEmptyCells (Row attr cells) = Row attr . applyEmptyCells' 0 cells . sortOn fst+ where+  applyEmptyCells' _  cells' [] = cells'+  applyEmptyCells' currentPosition cells' ((columnPosition, columnEmptyCell@(Cell _ _ _ (ColSpan colSpan) _)):rest)+    | columnPosition == currentPosition = columnEmptyCell : applyEmptyCells' (currentPosition + colSpan) cells' rest+  applyEmptyCells' _ [] _ = []+  applyEmptyCells' currentPosition (cell@(Cell _ _ _ (ColSpan currentCellColSpan) _):restCells) emptyCellList =+    cell : applyEmptyCells' (currentPosition + currentCellColSpan) restCells emptyCellList
+ src/Text/Pandoc/Writers/BBCode.hs view
@@ -0,0 +1,1089 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE Strict #-}+{-# LANGUAGE TypeApplications #-}+{- |+   Module      : Text.Pandoc.Writers.BBCode+   Copyright   : © 2025 Aleksey Myshko <git@crii.xyz>+   License     : GNU GPL, version 2 or above++   Maintainer  : Aleksey Myshko <git@crii.xyz>+   Stability   : alpha+   Portability : portable++Conversion of 'Pandoc' documents to various BBCode flavors.+-}++module Text.Pandoc.Writers.BBCode (+  -- * Predefined writers+  -- Writers for different flavors of BBCode. 'writeBBCode' is a synonym for+  -- 'writeBBCode_official'+  writeBBCode,+  writeBBCodeOfficial,+  writeBBCodeSteam,+  writeBBCodePhpBB,+  writeBBCodeFluxBB,+  writeBBCodeHubzilla,+  writeBBCodeXenforo,++  -- * Extending the writer+  -- $extending+  FlavorSpec (..),+  WriterState (..),+  RR,+  writeBBCodeCustom,+  inlineToBBCode,+  inlineListToBBCode,+  blockToBBCode,+  blockListToBBCode,++  -- ** Handling attributes+  -- $wrapping_spans_divs+  attrToMap,++  -- * Predefined flavor specifications+  officialSpec,+  steamSpec,+  phpbbSpec,+  fluxbbSpec,+  hubzillaSpec,+  xenforoSpec,+) where++import Control.Applicative (some)+import Control.Monad (forM)+import Control.Monad.Reader (MonadReader (..), ReaderT (..), asks)+import Control.Monad.State (MonadState (..), StateT, evalStateT, gets, modify)+import Data.Default (Default (..))+import Data.Either (isRight)+import Data.Foldable (toList)+import Data.Map.Strict (Map)+import qualified Data.Map.Strict as Map+import Data.Maybe (fromMaybe, isJust)+import Data.Sequence (Seq, (|>))+import qualified Data.Sequence as Seq+import Data.Text (Text)+import qualified Data.Text as T+import Text.DocLayout hiding (char, link, text)+import Text.Pandoc.Class.PandocMonad (PandocMonad, report)+import Text.Pandoc.Definition+import Text.Pandoc.Logging (LogMessage (..))+import Text.Pandoc.Options (WriterOptions (..))+import Text.Pandoc.Parsing (char, digit, eof, readWith)+import Text.Pandoc.Shared (inquotes, onlySimpleTableCells, removeFormatting, trim, tshow)+import Text.Pandoc.Templates (renderTemplate)+import Text.Pandoc.URI (escapeURI)+import Text.Pandoc.Writers.Shared (defField, metaToContext, toLegacyTable, unsmartify)+import Text.Read (readMaybe)++-- Type synonym to prevent haddock-generated HTML from overflowing+type PandocTable =+  (Attr, Caption, [ColSpec], TableHead, [TableBody], TableFoot)++-- $extending+-- If you want to support more Pandoc elements (or render some of them+-- differently) you can do so by creating your own 'FlavorSpec'+--+-- The module exports the @'FlavorSpec'@s underlying @writeBBCode_*@ functions,+-- namely 'officialSpec', 'steamSpec', 'phpbbSpec', 'fluxbbSpec',+-- 'hubzillaSpec'.+--+-- You can create and use your own renderers, for instance here we define a+-- renderer for 'CodeBlock' and use it to create a derivative format:+--+-- > renderCodeBlockCustom :: (PandocMonad m) => Attr -> Text -> RR m (Doc Text)+-- > renderCodeBlockCustom (_, cls, _) code = do+-- >   let opening = case cls of+-- >         (lang : _) -> "[code=" <> lang <> "]"+-- >         ("c++" : _) -> "[code=cpp]"+-- >         _ -> "[code]"+-- >   pure $ mconcat [literal opening, literal code, cr, "[/code]"]+-- >+-- > specCustom = officialSpec{renderCodeBlock = renderCodeBlockCustom}+--+-- Then we can use it to render 'Pandoc' document via 'writeBBCode_custom'++{- | Data type that is a collection of renderers for most elements in a Pandoc+AST (see 'Block' and 'Inline')++The intention here is to allow inheritance between formats, for instance if+format A and format @B@ differ only in rendering tables, @B@ can be implemented+as @A{'renderTable' = renderTableB}@+-}+data FlavorSpec = FlavorSpec+  { renderBlockQuote ::+      forall m.+      (PandocMonad m) =>+      [Block] ->+      RR m (Doc Text)+  -- ^ Render 'BlockQuote'+  , renderBulletList ::+      forall m.+      (PandocMonad m) =>+      [[Block]] ->+      RR m (Doc Text)+  -- ^ Render 'BulletList'+  , renderCodeBlock ::+      forall m.+      (PandocMonad m) =>+      Attr ->+      Text ->+      RR m (Doc Text)+  -- ^ Render 'CodeBlock'+  , renderDefinitionList ::+      forall m.+      (PandocMonad m) =>+      [([Inline], [[Block]])] ->+      RR m (Doc Text)+  -- ^ Render 'DefinitionList'+  , renderHeader ::+      forall m.+      (PandocMonad m) =>+      Int ->+      Attr ->+      [Inline] ->+      RR m (Doc Text)+  -- ^ Render 'Header'+  , renderInlineCode ::+      forall m.+      (PandocMonad m) =>+      Attr ->+      Text ->+      RR m (Doc Text)+  -- ^ Render 'Code'+  , renderLink ::+      forall m.+      (PandocMonad m) =>+      Attr ->+      [Inline] ->+      Target ->+      RR m (Doc Text)+  -- ^ Render 'Link'+  , renderOrderedList ::+      forall m.+      (PandocMonad m) =>+      ListAttributes ->+      [[Block]] ->+      RR m (Doc Text)+  -- ^ Render 'OrderedList'+  , renderStrikeout ::+      forall m.+      (PandocMonad m) =>+      [Inline] ->+      RR m (Doc Text)+  -- ^ Render 'Strikeout'+  , renderTable :: forall m. (PandocMonad m) => PandocTable -> RR m (Doc Text)+  -- ^ Render 'Table'+  , renderHorizontalRule ::+      forall m.+      (PandocMonad m) =>+      RR m (Doc Text)+  -- ^ Render 'HorizontalRule'+  , renderLineBlock ::+      forall m.+      (PandocMonad m) =>+      [[Inline]] ->+      RR m (Doc Text)+  -- ^ Render 'LineBlock'+  , renderPara ::+      forall m.+      (PandocMonad m) =>+      [Inline] ->+      RR m (Doc Text)+  -- ^ Render 'Para'+  , renderSuperscript ::+      forall m.+      (PandocMonad m) =>+      [Inline] ->+      RR m (Doc Text)+  -- ^ Render 'Superscript'+  , renderSubscript :: forall m. (PandocMonad m) => [Inline] -> RR m (Doc Text)+  -- ^ Render 'Subscript'+  , renderSmallCaps :: forall m. (PandocMonad m) => [Inline] -> RR m (Doc Text)+  -- ^ Render 'SmallCaps'+  , renderCite ::+      forall m.+      (PandocMonad m) =>+      [Citation] ->+      [Inline] ->+      RR m (Doc Text)+  -- ^ Render 'Cite'+  , renderNote :: forall m. (PandocMonad m) => [Block] -> RR m (Doc Text)+  -- ^ Render 'Note'+  , renderFigure ::+      forall m.+      (PandocMonad m) =>+      Attr ->+      Caption ->+      [Block] ->+      RR m (Doc Text)+  -- ^ Render 'Figure'+  , renderQuoted ::+      forall m.+      (PandocMonad m) =>+      QuoteType ->+      [Inline] ->+      RR m (Doc Text)+  -- ^ Render 'Quoted'+  , renderMath ::+      forall m.+      (PandocMonad m) =>+      MathType ->+      Text ->+      RR m (Doc Text)+  -- ^ Render 'Math'+  , renderImage ::+      forall m.+      (PandocMonad m) =>+      Attr ->+      [Inline] ->+      Target ->+      RR m (Doc Text)+  -- ^ Render 'Image'+  , wrapSpanDiv :: Bool -> Map Text (Maybe Text) -> Doc Text -> Doc Text+  -- ^ Wrap document in bbcode tags based on attributes/classes. Boolean flag+  -- indicates whether passed argument is a Div or a Span (True means Div)+  }++data WriterState = WriterState+  { writerOptions :: WriterOptions+  , flavorSpec :: FlavorSpec+  , inList :: Bool+  }++instance Default WriterState where+  def =+    WriterState+      { writerOptions = def+      , flavorSpec = officialSpec+      , inList = False+      }++-- | The base of a renderer monad.+type RR m a = StateT (Seq (Doc Text)) (ReaderT WriterState m) a++pandocToBBCode :: (PandocMonad m) => Pandoc -> RR m Text+pandocToBBCode (Pandoc meta body) = do+  opts <- asks writerOptions+  -- Run the rendering that mutates the state by producing footnotes+  bodyContents <- blockListToBBCode body+  -- Get the footnotes+  footnotes <- get+  -- Separate footnotes (if any) with a horizontal rule+  footnotesSep <-+    if null footnotes+      then pure empty+      else+        (\hr -> blankline <> hr <> blankline)+          <$> blockToBBCode HorizontalRule+  -- Put footnotes after the main text+  let docText = bodyContents <> footnotesSep <> vsep (toList footnotes)+  metadata <- metaToContext opts blockListToBBCode inlineListToBBCode meta+  let context = defField "body" docText metadata+  case writerTemplate opts of+    Just tpl -> pure $ render Nothing (renderTemplate tpl context)+    Nothing -> pure $ render Nothing docText++writeBBCode+  , writeBBCodeOfficial+  , writeBBCodeSteam+  , writeBBCodePhpBB+  , writeBBCodeFluxBB+  , writeBBCodeHubzilla+  , writeBBCodeXenforo ::+    (PandocMonad m) => WriterOptions -> Pandoc -> m Text+writeBBCode = writeBBCodeOfficial+writeBBCodeOfficial = writeBBCodeCustom officialSpec+writeBBCodeSteam = writeBBCodeCustom steamSpec+writeBBCodePhpBB = writeBBCodeCustom phpbbSpec+writeBBCodeFluxBB = writeBBCodeCustom fluxbbSpec+writeBBCodeHubzilla = writeBBCodeCustom hubzillaSpec+writeBBCodeXenforo = writeBBCodeCustom xenforoSpec++{- | Convert a 'Pandoc' document to BBCode using the given 'FlavorSpec' and+'WriterOptions'.+-}+writeBBCodeCustom ::+  (PandocMonad m) => FlavorSpec -> WriterOptions -> Pandoc -> m Text+writeBBCodeCustom spec opts document =+  runRR mempty def{writerOptions = opts, flavorSpec = spec} $+    pandocToBBCode document+ where+  runRR :: (Monad m) => Seq (Doc Text) -> WriterState -> RR m a -> m a+  runRR footnotes writerState action =+    runReaderT (evalStateT action footnotes) writerState++blockListToBBCode :: (PandocMonad m) => [Block] -> RR m (Doc Text)+blockListToBBCode blocks =+  chomp . vsep . filter (not . null)+    <$> mapM blockToBBCode blocks++blockToBBCode :: (PandocMonad m) => Block -> RR m (Doc Text)+blockToBBCode block = do+  spec <- asks flavorSpec+  case block of+    Plain inlines -> inlineListToBBCode inlines+    Para inlines -> renderPara spec inlines+    LineBlock inliness -> renderLineBlock spec inliness+    CodeBlock attr code -> renderCodeBlock spec attr code+    RawBlock format raw -> case format of+      "bbcode" -> pure $ literal raw+      _ -> "" <$ report (BlockNotRendered block)+    BlockQuote blocks -> renderBlockQuote spec blocks+    OrderedList attr items -> renderOrderedList spec attr items+    BulletList items -> renderBulletList spec items+    DefinitionList items -> renderDefinitionList spec items+    Header level attr inlines -> renderHeader spec level attr inlines+    HorizontalRule -> renderHorizontalRule spec+    Table attr blkCapt specs thead tbody tfoot ->+      renderTable spec (attr, blkCapt, specs, thead, tbody, tfoot)+    Figure attr caption blocks -> renderFigure spec attr caption blocks+    Div attr blocks -> do+      contents <- blockListToBBCode blocks+      let kvcMap = attrToMap attr+      -- whether passed contents is a Div (Block) element+      --                      vvvv+      pure $ wrapSpanDiv spec True kvcMap contents++inlineToBBCode :: (PandocMonad m) => Inline -> RR m (Doc Text)+inlineToBBCode inline = do+  spec <- asks flavorSpec+  case inline of+    Str str -> do+      opts <- asks writerOptions+      pure . literal $ unsmartify opts str+    Emph inlines -> do+      contents <- inlineListToBBCode inlines+      pure $ mconcat ["[i]", contents, "[/i]"]+    Underline inlines -> do+      contents <- inlineListToBBCode inlines+      pure $ mconcat ["[u]", contents, "[/u]"]+    Strong inlines -> do+      contents <- inlineListToBBCode inlines+      pure $ mconcat ["[b]", contents, "[/b]"]+    Strikeout inlines -> renderStrikeout spec inlines+    Superscript inlines -> renderSuperscript spec inlines+    Subscript inlines -> renderSubscript spec inlines+    SmallCaps inlines -> renderSmallCaps spec inlines+    Quoted typ inlines -> renderQuoted spec typ inlines+    Cite cits inlines -> renderCite spec cits inlines+    Code attr code -> renderInlineCode spec attr code+    Space -> pure space+    SoftBreak -> pure space+    LineBreak -> pure cr+    Math typ math -> renderMath spec typ math+    RawInline (Format format) text -> case format of+      "bbcode" -> pure $ literal text+      _ -> "" <$ report (InlineNotRendered inline)+    Link attr txt target -> renderLink spec attr txt target+    Image attr alt target -> renderImage spec attr alt target+    Note blocks -> renderNote spec blocks+    Span attr inlines -> do+      contents <- inlineListToBBCode inlines+      let kvcMap = attrToMap attr+      -- whether passed contents is a Div (Block element)+      --                      vvvvv+      pure $ wrapSpanDiv spec False kvcMap contents++renderImageDefault ::+  (PandocMonad m) => Attr -> [Inline] -> Target -> RR m (Doc Text)+renderImageDefault (_, _, kvList) alt (source, title) = do+  altText <-+    trim . render Nothing+      <$> inlineListToBBCode (removeFormatting alt)+  let kvMap = Map.fromList kvList+  -- No BBCode flavor supported by the Writer has local images support, but we+  -- still allow source to be plain path or anything else+  pure . literal $+    mconcat+      [ "[img"+      , if T.null altText+          then ""+          else " alt=" <> inquotes altText+      , if T.null title+          then ""+          else " title=" <> inquotes title+      , case Map.lookup "width" kvMap of+          Just w+            | isJust (readMaybe @Int $ T.unpack w) ->+                " width=" <> inquotes w+          _ -> ""+      , case Map.lookup "height" kvMap of+          Just h+            | isJust (readMaybe @Int $ T.unpack h) ->+                " height=" <> inquotes h+          _ -> ""+      , "]"+      , source+      , "[/img]"+      ]++renderImageOmit ::+  (PandocMonad m) => Attr -> [Inline] -> Target -> RR m (Doc Text)+renderImageOmit _ _ _ = pure ""++{- | Basic phpBB doesn't support any attributes, although+@[img src=https://example.com]whatever[/img]@ is supported, but text in tag has+no effect+-}+renderImagePhpBB ::+  (PandocMonad m) => Attr -> [Inline] -> Target -> RR m (Doc Text)+renderImagePhpBB _ _ (source, _) =+  pure . literal $ mconcat ["[img]", source, "[/img]"]++renderImageXenforo ::+  (PandocMonad m) => Attr -> [Inline] -> Target -> RR m (Doc Text)+renderImageXenforo (_, _, kvList) alt (source, title) = do+  altText <-+    trim . render Nothing+      <$> inlineListToBBCode (removeFormatting alt)+  let kvMap = Map.fromList kvList+  -- No BBCode flavor supported by the Writer has local images support, but we+  -- still allow source to be plain path or anything else+  pure . literal $+    mconcat+      [ "[img"+      , if T.null altText+          then ""+          else " alt=" <> inquotes altText+      , if T.null title+          then ""+          else " title=" <> inquotes title+      , case Map.lookup "width" kvMap of+          Just w+            | isRight (readWith sizeP Nothing w) ->+                " width=" <> w+          _ -> ""+      , "]"+      , source+      , "[/img]"+      ]+ where+  sizeP = some digit >> char '%' >> eof++{- | Check whether character is a bracket++>>> T.filter notBracket "[a]b[[ó]qü]]n®"+"ab\243q\252n\174"+-}+notBracket :: Char -> Bool+notBracket = \case+  '[' -> False+  ']' -> False+  _ -> True++-- FluxBB uses [img=alt text] instead of [img alt="alt text"]+renderImageFluxBB ::+  (PandocMonad m) => Attr -> [Inline] -> Target -> RR m (Doc Text)+renderImageFluxBB _ alt (source, _) = do+  alt' <- T.filter notBracket . render Nothing <$> inlineListToBBCode alt+  pure . literal $+    mconcat+      [ "[img"+      , if T.null alt'+          then ""+          else "=" <> alt'+      , "]"+      , source+      , "[/img]"+      ]++inlineListToBBCode :: (PandocMonad m) => [Inline] -> RR m (Doc Text)+inlineListToBBCode inlines = mconcat <$> mapM inlineToBBCode inlines++-- Taken from Data.Ord+clamp :: (Ord a) => (a, a) -> a -> a+clamp (low, high) a = min high (max a low)++renderHeaderDefault ::+  (PandocMonad m) => Int -> Attr -> [Inline] -> RR m (Doc Text)+renderHeaderDefault level _attr inlines =+  case clamp (1, 4) level of+    1 -> inlineToBBCode $ Underline [Strong inlines]+    2 -> inlineToBBCode $ Strong inlines+    3 -> inlineToBBCode $ Underline inlines+    _ -> inlineListToBBCode inlines++-- Adapted from Text.Pandoc.Writers.Org+renderLinkDefault ::+  (PandocMonad m) => Attr -> [Inline] -> Target -> RR m (Doc Text)+renderLinkDefault _ txt (src, _) =+  case txt of+    [Str x]+      | escapeURI x == src ->+          pure $ "[url]" <> literal x <> "[/url]"+    _ -> do+      contents <- inlineListToBBCode txt+      let suffix = if T.null src then "" else "=" <> src+      pure $ "[url" <> literal suffix <> "]" <> contents <> "[/url]"++renderCodeBlockDefault :: (PandocMonad m) => Attr -> Text -> RR m (Doc Text)+renderCodeBlockDefault (_, cls, _) code = do+  let opening = case cls of+        (lang : _) -> "[code=" <> lang <> "]"+        _ -> "[code]"+  pure $ mconcat [literal opening, literal code, cr, "[/code]"]++renderCodeBlockSimple :: (PandocMonad m) => Attr -> Text -> RR m (Doc Text)+renderCodeBlockSimple _ code = do+  pure $ mconcat [literal "[code]", literal code, cr, "[/code]"]++renderInlineCodeLiteral :: (PandocMonad m) => Attr -> Text -> RR m (Doc Text)+renderInlineCodeLiteral _ code = pure $ literal code++renderInlineCodeNoParse :: (PandocMonad m) => Attr -> Text -> RR m (Doc Text)+renderInlineCodeNoParse _ code =+  pure $ mconcat [literal "[noparse]", literal code, "[/noparse]"]++renderInlineCodeHubzilla :: (PandocMonad m) => Attr -> Text -> RR m (Doc Text)+renderInlineCodeHubzilla _ code =+  pure $ mconcat [literal "[code]", literal code, "[/code]"]++renderInlineCodeXenforo :: (PandocMonad m) => Attr -> Text -> RR m (Doc Text)+renderInlineCodeXenforo _ code =+  pure $ mconcat [literal "[icode]", literal code, "[/icode]"]++renderStrikeoutDefault :: (PandocMonad m) => [Inline] -> RR m (Doc Text)+renderStrikeoutDefault inlines = do+  contents <- inlineListToBBCode inlines+  pure $ mconcat ["[s]", contents, "[/s]"]++renderStrikeoutSteam :: (PandocMonad m) => [Inline] -> RR m (Doc Text)+renderStrikeoutSteam inlines = do+  contents <- inlineListToBBCode inlines+  pure $ mconcat ["[strike]", contents, "[/strike]"]++renderDefinitionListDefault ::+  (PandocMonad m) => [([Inline], [[Block]])] -> RR m (Doc Text)+renderDefinitionListDefault items = do+  items' <- forM items $ \(term, definitions) -> do+    term' <- inlineListToBBCode term+    definitions' <- blockToBBCode (BulletList definitions)+    pure $ term' $$ definitions'+  pure $ vcat items'++renderDefinitionListHubzilla ::+  (PandocMonad m) => [([Inline], [[Block]])] -> RR m (Doc Text)+renderDefinitionListHubzilla items = do+  items' <- forM items $ \(term, definitions) -> do+    term' <- inlineListToBBCode term+    let term'' = "[*= " <> term' <> "]"+    definitions' <- forM definitions blockListToBBCode+    pure $ vcat (term'' : definitions')+  pure $ vcat (literal "[dl terms=\"b\"]" : items' ++ [literal "[/dl]"])++listWithTags ::+  (PandocMonad m) =>+  Text ->+  Text ->+  ([[Block]] -> RR m [Doc Text]) ->+  [[Block]] ->+  RR m (Doc Text)+listWithTags open close renderItems items = do+  contents <- local (\s -> s{inList = True}) (renderItems items)+  pure $ vcat $ literal open : contents ++ [literal close]++starListItems :: (PandocMonad m) => [[Block]] -> RR m [Doc Text]+starListItems items = forM items $ \item -> do+  item' <- blockListToBBCode item+  pure $ literal "[*]" <> item'++listStyleCode :: ListNumberStyle -> Maybe Text+listStyleCode = \case+  Decimal -> Just "1"+  DefaultStyle -> Just "1"+  LowerAlpha -> Just "a"+  UpperAlpha -> Just "A"+  LowerRoman -> Just "i"+  UpperRoman -> Just "I"+  Example -> Nothing++renderBulletListOfficial :: (PandocMonad m) => [[Block]] -> RR m (Doc Text)+renderBulletListOfficial = listWithTags "[list]" "[/list]" starListItems++renderBulletListHubzilla :: (PandocMonad m) => [[Block]] -> RR m (Doc Text)+renderBulletListHubzilla = listWithTags "[ul]" "[/ul]" starListItems++renderOrderedListHubzilla ::+  (PandocMonad m) => ListAttributes -> [[Block]] -> RR m (Doc Text)+renderOrderedListHubzilla (_, style, _) = case style of+  DefaultStyle -> listWithTags "[ol]" "[/ol]" starListItems+  Example -> listWithTags "[ol]" "[/ol]" starListItems+  _ -> listWithTags ("[list=" <> suffix <> "]") "[/list]" starListItems+ where+  suffix = fromMaybe "1" $ listStyleCode style++renderOrderedListOfficial ::+  (PandocMonad m) => ListAttributes -> [[Block]] -> RR m (Doc Text)+renderOrderedListOfficial (_, style, _) = do+  let suffix = maybe "" ("=" <>) (listStyleCode style)+  listWithTags ("[list" <> suffix <> "]") "[/list]" starListItems++renderOrderedListSteam ::+  (PandocMonad m) => ListAttributes -> [[Block]] -> RR m (Doc Text)+renderOrderedListSteam _ =+  listWithTags "[olist]" "[/olist]" starListItems++renderHeaderSteam ::+  (PandocMonad m) => Int -> Attr -> [Inline] -> RR m (Doc Text)+renderHeaderSteam level _ inlines = do+  body <- inlineListToBBCode inlines+  let capped = clamp (1, 3) level+      open = "[h" <> tshow capped <> "]"+      close = "[/h" <> tshow capped <> "]"+  pure $ literal open <> body <> literal close++renderHeaderHubzilla ::+  (PandocMonad m) => Int -> Attr -> [Inline] -> RR m (Doc Text)+renderHeaderHubzilla level _ inlines = do+  body <- inlineListToBBCode inlines+  let capped = clamp (1, 6) level+      open = "[h" <> tshow capped <> "]"+      close = "[/h" <> tshow capped <> "]"+  pure $ literal open <> body <> literal close++-- xenForo supports levels 1--3, but levels other than 1--3 become div with+-- .bbHeading class which can be linked to.+renderHeaderXenforo ::+  (PandocMonad m) => Int -> Attr -> [Inline] -> RR m (Doc Text)+renderHeaderXenforo level _ inlines = do+  body <- inlineListToBBCode inlines+  let capped = max 1 level+      open = "[heading=" <> tshow capped <> "]"+      close = "[/heading]"+  pure $ literal open <> body <> literal close++renderTableGeneric ::+  (PandocMonad m) =>+  Text ->+  Text ->+  Text ->+  (Attr, Caption, [ColSpec], TableHead, [TableBody], TableFoot) ->+  RR m (Doc Text)+renderTableGeneric tableTag headerCellTag bodyCellTag table = do+  caption' <- inlineListToBBCode caption+  table' <-+    if not simpleCells+      then "" <$ report (BlockNotRendered tableBlock)+      else do+        headerDocs <-+          if null headers+            then pure []+            else pure <$> renderTableRow headerCellTag headers+        rowDocs <- mapM (renderTableRow bodyCellTag) rows+        pure $ renderTable' headerDocs rowDocs+  pure $ caption' $$ table'+ where+  (attr, blkCapt, specs, thead, tbody, tfoot) = table+  (caption, _, _, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot+  tableBlock = Table attr blkCapt specs thead tbody tfoot+  simpleCells = onlySimpleTableCells (headers : rows)+  renderTable' headerDocs rowDocs =+    vcat+      [ literal ("[" <> tableTag <> "]")+      , vcat headerDocs+      , vcat rowDocs+      , literal ("[/" <> tableTag <> "]")+      ]+  renderCell cellTag cellDoc =+    mconcat+      [ literal ("[" <> cellTag <> "]")+      , cellDoc+      , literal ("[/" <> cellTag <> "]")+      ]+  renderTableRow cellTag cells = do+    renderedCells <- mapM blockListToBBCode cells+    let cellsDoc = mconcat $ map (renderCell cellTag) renderedCells+    pure $ literal "[tr]" <> cellsDoc <> literal "[/tr]"++renderTableDefault ::+  (PandocMonad m) =>+  ( Attr+  , Caption+  , [ColSpec]+  , TableHead+  , [TableBody]+  , TableFoot+  ) ->+  RR m (Doc Text)+renderTableDefault = renderTableGeneric "table" "th" "td"++renderTableOmit ::+  (PandocMonad m) =>+  ( Attr+  , Caption+  , [ColSpec]+  , TableHead+  , [TableBody]+  , TableFoot+  ) ->+  RR m (Doc Text)+renderTableOmit (_, blkCapt, specs, thead, tbody, tfoot) = do+  let (caption, _, _, _, _) = toLegacyTable blkCapt specs thead tbody tfoot+  caption' <- inlineListToBBCode caption+  pure $ caption' $$ "(TABLE)"++-- $wrapping_spans_divs+-- Consider attribute a key-value pair with a Just value, and respectively+-- class is key-value pair with Nothing value.+-- For instance, given @("", ["cl1"], [("k", "v")]) :: 'Attr'@, respective Map+-- should look like @'Map.fromList' [("cl1", 'Nothing'), ("k", 'Just' "v")]@+--+-- This transformation is handled by 'attrToMap'+--+-- Example definition of a wrapSpanDiv:+--+-- > {-# LANGUAGE OverloadedStrings #-}+-- > import Data.Map (Map)+-- > import qualified Data.Map as Map+-- > import Text.DocLayout+-- > import Data.Text (Text)+-- > import qualified Data.Text as T+-- >+-- > wrapSpanDivSteam :: Bool -> Map Text (Maybe Text) -> Doc Text -> Doc Text+-- > wrapSpanDivSteam isDiv kvc doc = Map.foldrWithKey wrap doc kvc+-- >  where+-- >   wrap "spoiler" (Just _) acc | isDiv = "[spoiler]" <> acc <> "[/spoiler]"+-- >   wrap "spoiler" Nothing acc | isDiv = "[spoiler]" <> acc <> "[/spoiler]"+-- >   wrap _ _ acc = acc+--+-- To verify it works, wrap some text in unnamed spoiler+--+-- >>> render Nothing $ wrapSpanDivSteam True (attrToMap ("", ["spoiler"], [])) "I am text"+-- "[spoiler]I am text[/spoiler]"++{- | The goal of the transformation is to treat classes and key-value pairs+uniformly.++Class list becomes Map where all values are Nothing, and list of key-value+pairs is converted to Map via 'Map.toList'. Both Maps are then merged.+-}+attrToMap :: Attr -> Map Text (Maybe Text)+attrToMap (_, classes, kvList) =+  Map.fromList kvList' `Map.union` Map.fromList classes'+ where+  kvList' = map (\(k, v) -> (k, Just v)) kvList+  classes' = map (\k -> (k, Nothing)) classes++wrapSpanDivOfficial :: Bool -> Map Text (Maybe Text) -> Doc Text -> Doc Text+wrapSpanDivOfficial isDiv kvc doc = Map.foldrWithKey wrap doc kvc+ where+  wrap "left" Nothing acc | isDiv = "[left]" <> acc <> "[/left]"+  wrap "center" Nothing acc | isDiv = "[center]" <> acc <> "[/center]"+  wrap "right" Nothing acc | isDiv = "[right]" <> acc <> "[/right]"+  wrap "spoiler" Nothing acc | isDiv = "[spoiler]" <> acc <> "[/spoiler]"+  wrap "spoiler" (Just v) acc+    | isDiv =+        literal ("[spoiler=" <> T.filter notBracket v <> "]")+          <> acc+          <> "[/spoiler]"+  wrap "size" (Just v) acc+    | Just v' <- readMaybe @Int (T.unpack v)+    , v' > 0 =+        literal ("[size=" <> v <> "]") <> acc <> "[/size]"+  wrap "color" (Just v) acc =+    literal ("[color=" <> v <> "]") <> acc <> "[/color]"+  wrap _ _ acc = acc++wrapSpanDivSteam :: Bool -> Map Text (Maybe Text) -> Doc Text -> Doc Text+wrapSpanDivSteam isDiv kvc doc = Map.foldrWithKey wrap doc kvc+ where+  wrap "spoiler" (Just _) acc | isDiv = "[spoiler]" <> acc <> "[/spoiler]"+  wrap "spoiler" Nothing acc | isDiv = "[spoiler]" <> acc <> "[/spoiler]"+  wrap _ _ acc = acc++wrapSpanDivPhpBB :: Bool -> Map Text (Maybe Text) -> Doc Text -> Doc Text+wrapSpanDivPhpBB _ kvc doc = Map.foldrWithKey wrap doc kvc+ where+  wrap "color" (Just v) acc =+    literal ("[color=" <> v <> "]") <> acc <> "[/color]"+  wrap _ _ acc = acc++wrapSpanDivFluxBB :: Bool -> Map Text (Maybe Text) -> Doc Text -> Doc Text+wrapSpanDivFluxBB _ kvc doc = Map.foldrWithKey wrap doc kvc+ where+  wrap "color" (Just v) acc =+    literal ("[color=" <> v <> "]") <> acc <> "[/color]"+  wrap _ _ acc = acc++wrapSpanDivHubzilla :: Bool -> Map Text (Maybe Text) -> Doc Text -> Doc Text+wrapSpanDivHubzilla isDiv kvc doc = Map.foldrWithKey wrap doc kvc+ where+  wrap "center" Nothing acc | isDiv = "[center]" <> acc <> "[/center]"+  wrap "spoiler" Nothing acc | isDiv = "[spoiler]" <> acc <> "[/spoiler]"+  wrap "spoiler" (Just v) acc+    | isDiv =+        literal ("[spoiler=" <> T.filter notBracket v <> "]")+          <> acc+          <> "[/spoiler]"+  wrap "size" (Just v) acc+    | Just v' <- readMaybe @Int (T.unpack v)+    , v' > 0 =+        literal ("[size=" <> v <> "]") <> acc <> "[/size]"+  wrap "color" (Just v) acc =+    literal ("[color=" <> v <> "]") <> acc <> "[/color]"+  wrap "font" (Just v) acc = literal ("[font=" <> v <> "]") <> acc <> "[/font]"+  wrap _ _ acc = acc++wrapSpanDivXenforo :: Bool -> Map Text (Maybe Text) -> Doc Text -> Doc Text+wrapSpanDivXenforo isDiv kvc doc = Map.foldrWithKey wrap doc kvc+ where+  wrap "left" Nothing acc | isDiv = "[left]" <> acc <> "[/left]"+  wrap "center" Nothing acc | isDiv = "[center]" <> acc <> "[/center]"+  wrap "right" Nothing acc | isDiv = "[right]" <> acc <> "[/right]"+  wrap "spoiler" _ acc | not isDiv = "[ispoiler]" <> acc <> "[/ispoiler]"+  wrap "spoiler" Nothing acc | isDiv = "[spoiler]" <> acc <> "[/spoiler]"+  wrap "spoiler" (Just v) acc+    | isDiv =+        literal ("[spoiler=" <> T.filter notBracket v <> "]")+          <> acc+          <> "[/spoiler]"+  wrap "size" (Just v) acc+    | Just v' <- readMaybe @Int (T.unpack v)+    , v' > 0 =+        literal ("[size=" <> v <> "]") <> acc <> "[/size]"+  wrap "color" (Just v) acc =+    literal ("[color=" <> v <> "]") <> acc <> "[/color]"+  wrap "font" (Just v) acc = literal ("[font=" <> v <> "]") <> acc <> "[/font]"+  wrap _ _ acc = acc++renderOrderedListFluxbb ::+  (PandocMonad m) =>+  ListAttributes ->+  [[Block]] ->+  RR m (Doc Text)+renderOrderedListFluxbb (_, style, _) =+  let suffix = case style of+        LowerAlpha -> "=a"+        UpperAlpha -> "=a"+        _ -> "=1"+   in listWithTags ("[list" <> suffix <> "]") "[/list]" starListItems++renderOrderedListXenforo ::+  (PandocMonad m) =>+  ListAttributes ->+  [[Block]] ->+  RR m (Doc Text)+renderOrderedListXenforo _ =+  listWithTags "[list=1]" "[/list]" starListItems++renderLinkEmailAware ::+  (PandocMonad m) =>+  Attr ->+  [Inline] ->+  Target ->+  RR m (Doc Text)+renderLinkEmailAware attr txt target@(src, _) = do+  case T.stripPrefix "mailto:" src of+    Just address -> do+      linkText <- inlineListToBBCode txt+      let isAutoEmail = case txt of+            [Str x] -> x == address+            _ -> False+      pure $+        if isAutoEmail+          then literal "[email]" <> literal address <> "[/email]"+          else literal ("[email=" <> address <> "]") <> linkText <> "[/email]"+    Nothing -> renderLinkDefault attr txt target++renderBlockQuoteDefault :: (PandocMonad m) => [Block] -> RR m (Doc Text)+renderBlockQuoteDefault blocks = do+  contents <- blockListToBBCode blocks+  pure $ vcat ["[quote]", contents, "[/quote]"]++renderBlockQuoteFluxBB :: (PandocMonad m) => [Block] -> RR m (Doc Text)+renderBlockQuoteFluxBB blocks = do+  contents <- blockListToBBCode blocks+  isInList <- asks inList+  if isInList+    then "" <$ report (BlockNotRendered $ BlockQuote blocks)+    else pure $ vcat ["[quote]", contents, "[/quote]"]++renderHorizontalRuleDefault :: (PandocMonad m) => RR m (Doc Text)+renderHorizontalRuleDefault = pure "* * *"++renderHorizontalRuleHR :: (PandocMonad m) => RR m (Doc Text)+renderHorizontalRuleHR = pure "[hr]"++renderLineBlockDefault :: (PandocMonad m) => [[Inline]] -> RR m (Doc Text)+renderLineBlockDefault inliness = vcat <$> mapM inlineListToBBCode inliness++renderParaDefault :: (PandocMonad m) => [Inline] -> RR m (Doc Text)+renderParaDefault inlines = inlineListToBBCode inlines++renderSuperscriptDefault :: (PandocMonad m) => [Inline] -> RR m (Doc Text)+renderSuperscriptDefault = inlineListToBBCode++renderSubscriptDefault :: (PandocMonad m) => [Inline] -> RR m (Doc Text)+renderSubscriptDefault = inlineListToBBCode++renderSmallCapsDefault :: (PandocMonad m) => [Inline] -> RR m (Doc Text)+renderSmallCapsDefault = inlineListToBBCode++renderCiteDefault ::+  (PandocMonad m) => [Citation] -> [Inline] -> RR m (Doc Text)+renderCiteDefault _ = inlineListToBBCode++renderNoteDefault :: (PandocMonad m) => [Block] -> RR m (Doc Text)+renderNoteDefault blocks = do+  -- NOTE: no BBCode flavor has native syntax for footnotes.+  newN <- gets (succ . Seq.length)+  contents <- blockListToBBCode blocks+  let pointer = "(" <> tshow newN <> ")"+  let contents' = literal pointer <> space <> contents+  modify (|> contents')+  pure $ literal pointer++renderFigureDefault ::+  (PandocMonad m) => Attr -> Caption -> [Block] -> RR m (Doc Text)+renderFigureDefault _ (Caption _ caption) blocks = do+  caption' <- blockListToBBCode caption+  contents <- blockListToBBCode blocks+  pure $ contents $$ caption'++renderQuotedDefault ::+  (PandocMonad m) => QuoteType -> [Inline] -> RR m (Doc Text)+renderQuotedDefault typ inlines = do+  let quote = case typ of SingleQuote -> "'"; DoubleQuote -> "\""+  contents <- inlineListToBBCode inlines+  pure $ mconcat [quote, contents, quote]++renderMathDefault :: (PandocMonad m) => MathType -> Text -> RR m (Doc Text)+renderMathDefault typ math = case typ of+  InlineMath ->+    inlineToBBCode $+      Code ("", ["latex"], []) ("$" <> math <> "$")+  DisplayMath ->+    blockToBBCode $+      CodeBlock ("", ["latex"], []) ("$$" <> math <> "$$")++{- | Format documentation: <https://www.bbcode.org/reference.php>++There is no such thing as «Official» bbcode format, nonetheless this spec+implements what is described on bbcode.org, which is a reasonable base that can+be extended/contracted as needed.+-}+officialSpec :: FlavorSpec+officialSpec =+  FlavorSpec+    { renderOrderedList = renderOrderedListOfficial+    , renderBulletList = renderBulletListOfficial+    , renderDefinitionList = renderDefinitionListDefault+    , renderHeader = renderHeaderDefault+    , renderTable = renderTableDefault+    , renderLink = renderLinkEmailAware+    , renderCodeBlock = renderCodeBlockDefault+    , renderInlineCode = renderInlineCodeLiteral+    , renderStrikeout = renderStrikeoutDefault+    , renderBlockQuote = renderBlockQuoteDefault+    , renderHorizontalRule = renderHorizontalRuleDefault+    , renderLineBlock = renderLineBlockDefault+    , renderPara = renderParaDefault+    , renderSuperscript = renderSuperscriptDefault+    , renderSubscript = renderSubscriptDefault+    , renderSmallCaps = renderSmallCapsDefault+    , renderCite = renderCiteDefault+    , renderNote = renderNoteDefault+    , renderFigure = renderFigureDefault+    , renderMath = renderMathDefault+    , renderQuoted = renderQuotedDefault+    , renderImage = renderImageDefault+    , wrapSpanDiv = wrapSpanDivOfficial+    }++{- | Format documentation: <https://steamcommunity.com/comment/ForumTopic/formattinghelp>++Used at: <https://steamcommunity.com/discussions/forum>++Quirks:++- There seems to be no way to show external images on steam.+  https://steamcommunity.com/sharedfiles/filedetails/?id=2807121939 shows [img]+  and [previewimg] can (could?) be used to show images, although it is likely+  reserved for steam urls only.+-}+steamSpec :: FlavorSpec+steamSpec =+  officialSpec+    { renderOrderedList = renderOrderedListSteam+    , renderHeader = renderHeaderSteam+    , renderLink = renderLinkDefault+    , renderInlineCode = renderInlineCodeNoParse+    , renderStrikeout = renderStrikeoutSteam+    , renderImage = renderImageOmit+    , wrapSpanDiv = wrapSpanDivSteam+    , renderHorizontalRule = renderHorizontalRuleHR+    }++{- | Format documentation: <https://www.phpbb.com/community/help/bbcode>++Used at: <https://www.phpbb.com/community>++Quirks:++- PhpBB docs don't mention strikeout support, but their+  [support forum](https://www.phpbb.com/community) does support it.+- Same for named code blocks.+- @[email=example\@example.com]the email[/url]@ is a valid use of [email]+  tag on the phpBB community forum despite not being in the docs.+-}+phpbbSpec :: FlavorSpec+phpbbSpec =+  officialSpec+    { renderTable = renderTableOmit+    , renderImage = renderImagePhpBB+    , wrapSpanDiv = wrapSpanDivPhpBB+    }++{- | Format documentation: <https://web.archive.org/web/20210623155046/https://fluxbb.org/forums/help.php#bbcode>++Used at: https://bbs.archlinux.org+-}+fluxbbSpec :: FlavorSpec+fluxbbSpec =+  officialSpec+    { renderOrderedList = renderOrderedListFluxbb+    , renderCodeBlock = renderCodeBlockSimple+    , renderTable = renderTableOmit+    , renderBlockQuote = renderBlockQuoteFluxBB+    , renderImage = renderImageFluxBB+    , wrapSpanDiv = wrapSpanDivFluxBB+    }++{- | Format documentation: <https://hubzilla.org/help/member/bbcode>++Used at: <https://hub.netzgemeinde.eu> (see [other hubs](https://hubzilla.org/pubsites))++Quirks:++- If link target is not a URI, it simply points to https://$BASEURL/ when+  rendered by a hub.+-}+hubzillaSpec :: FlavorSpec+hubzillaSpec =+  officialSpec+    { renderOrderedList = renderOrderedListHubzilla+    , renderBulletList = renderBulletListHubzilla+    , renderDefinitionList = renderDefinitionListHubzilla+    , renderHeader = renderHeaderHubzilla+    , renderInlineCode = renderInlineCodeHubzilla+    , renderLink = renderLinkDefault+    , wrapSpanDiv = wrapSpanDivHubzilla+    , renderHorizontalRule = renderHorizontalRuleHR+    }++{- | Format documentation: <https://www.xenfocus.com/community/help/bb-codes/>++Used at: see <https://xenforo.com/>+-}+xenforoSpec :: FlavorSpec+xenforoSpec =+  officialSpec+    { wrapSpanDiv = wrapSpanDivXenforo+    , renderHeader = renderHeaderXenforo+    , renderInlineCode = renderInlineCodeXenforo+    , renderHorizontalRule = renderHorizontalRuleHR+    , renderOrderedList = renderOrderedListXenforo+    , renderImage = renderImageXenforo+    }
src/Text/Pandoc/Writers/BibTeX.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Writers.BibTeX-   Copyright   : Copyright (C) 2021-2023 John MacFarlane+   Copyright   : Copyright (C) 2021-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>
src/Text/Pandoc/Writers/Blaze.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Writers.Blaze-   Copyright   : Copyright (C) 2021-2023 John MacFarlane+   Copyright   : Copyright (C) 2021-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>
src/Text/Pandoc/Writers/CommonMark.hs view
@@ -1,6 +1,6 @@ {- |    Module      : Text.Pandoc.Writers.CommonMark-   Copyright   : Copyright (C) 2015-2023 John MacFarlane+   Copyright   : Copyright (C) 2015-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>
src/Text/Pandoc/Writers/ConTeXt.hs view
@@ -4,7 +4,7 @@ {-# LANGUAGE ViewPatterns        #-} {- |    Module      : Text.Pandoc.Writers.ConTeXt-   Copyright   : Copyright (C) 2007-2023 John MacFarlane+   Copyright   : Copyright (C) 2007-2025 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -20,7 +20,7 @@ import Data.Char (ord, isDigit) import Data.List (intersperse) import Data.List.NonEmpty (NonEmpty ((:|)))-import Data.Maybe (isNothing, mapMaybe, catMaybes)+import Data.Maybe (mapMaybe, catMaybes) import Data.Monoid (Any (Any, getAny)) import Data.Text (Text) import qualified Data.Text as T@@ -104,6 +104,8 @@   mblang <- fromBCP47 (getLang options meta)   st <- get   let context =   defField "toc" (writerTableOfContents options)+                $ defField "lof" (writerListOfFigures options)+                $ defField "lot" (writerListOfTables options)                 $ defField "placelist"                    (mconcat . intersperse ("," :: Doc Text) $                      take (writerTOCDepth options +@@ -115,6 +117,7 @@                         "subsubsubsection","subsubsubsubsection"])                 $ defField "body" main                 $ defField "layout" layoutFromMargins+                $ defField "tagging" (isEnabled Ext_tagging options)                 $ defField "number-sections" (writerNumberSections options)                 $ defField "csl-refs" (stHasCslRefs st)                 $ defField "csl-hanging-indent" (stCslHangingIndent st)@@ -128,10 +131,10 @@                         _                     -> id)                 $ defField "emphasis-commands"                     (mconcat $ Map.elems (stEmphasisCommands st))-                $ (case writerHighlightStyle options of-                        Just sty | stHighlighting st ->-                          defField "highlighting-commands" (styleToConTeXt sty)-                        _ -> id)+                $ (case writerHighlightMethod options of+                      Skylighting sty | stHighlighting st ->+                        defField "highlighting-commands" (styleToConTeXt sty)+                      _ -> id)                 $ (case T.toLower $ lookupMetaString "pdfa" meta of                         "true" -> resetField "pdfa" (T.pack "1b:2005")                         _                     -> id) metadata@@ -230,9 +233,9 @@             return (literal h)   -- blankline because \stoptyping can't have anything after it, inc. '}'   ($$ blankline) . flush <$>-    if null classes || isNothing (writerHighlightStyle opts)-    then pure unhighlighted-    else highlighted+    case writerHighlightMethod opts of+      Skylighting _ | not (null classes) -> pure unhighlighted+      _ -> highlighted blockToConTeXt b@(RawBlock f str)   | f == Format "context" || f == Format "tex" = return $ literal str <> blankline   | otherwise = empty <$ report (BlockNotRendered b)@@ -587,7 +590,7 @@                 -> WM m (Doc Text) inlineToConTeXt (Emph lst)      = highlightInlines "emph"      "\\em" lst inlineToConTeXt (Strong lst)    = highlightInlines "strong"    "\\bf" lst-inlineToConTeXt (SmallCaps lst) = highlightInlines "smallcaps" "\\sc" lst+inlineToConTeXt (SmallCaps lst) = highlightInlines "smallcaps" "\\setsmallcaps" lst inlineToConTeXt (Underline lst) = do   contents <- inlineListToConTeXt lst   return $ "\\underbar" <> braces contents@@ -622,9 +625,9 @@           Right h -> do             modify (\st -> st{ stHighlighting = True })             return (text (T.unpack h))-  if isNothing (writerHighlightStyle opts) || null classes-    then rawCode-    else highlightCode+  case writerHighlightMethod opts of+    Skylighting _ | not (null classes) -> highlightCode+    _ -> rawCode inlineToConTeXt (Quoted SingleQuote lst) = do   contents <- inlineListToConTeXt lst   return $ "\\quote" <> braces contents@@ -696,9 +699,9 @@       dims = if null dimList                 then empty                 else brackets $ mconcat (intersperse "," dimList)-      clas = if null cls-                then empty-                else brackets $ literal $ toLabel $ head cls+      clas = case cls of+               [] -> empty+               (cl:_) -> brackets $ literal $ toLabel cl       -- Use / for path separators on Windows; see #4918       fixPathSeparators = T.map $ \c -> case c of                                           '\\' -> '/'@@ -829,7 +832,6 @@ fromBCP47' (Just (Lang "el" _ _ _ _ _))           = Just "gr" fromBCP47' (Just (Lang "eu" _ _ _ _ _))           = Just "ba" fromBCP47' (Just (Lang "he" _ _ _ _ _))           = Just "il"-fromBCP47' (Just (Lang "jp" _ _ _ _ _))           = Just "ja" fromBCP47' (Just (Lang "uk" _ _ _ _ _))           = Just "ua" fromBCP47' (Just (Lang "vi" _ _ _ _ _))           = Just "vn" fromBCP47' (Just (Lang "zh" _ _ _ _ _))           = Just "cn"
src/Text/Pandoc/Writers/CslJson.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Writers.CslJson-   Copyright   : Copyright (C) 2020-2023 John MacFarlane+   Copyright   : Copyright (C) 2020-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>
src/Text/Pandoc/Writers/Djot.hs view
@@ -100,7 +100,8 @@ blockToDjot (Header lev attr ils) =   fmap (D.addAttr (toDjotAttr attr)) . D.heading lev <$> inlinesToDjot ils blockToDjot HorizontalRule = pure D.thematicBreak-blockToDjot (Div (ident,"section":cls,kvs) bls@(Header _ _ ils : _)) = do+blockToDjot (Div (ident,"section":cls,kvs)+              (Header lev (_,hcls,hkvs) ils : bls)) = do   ilsBs <- D.inlinesToByteString <$> inlinesToDjot ils   let ident' = toIdentifier ilsBs   let label = D.normalizeLabel ilsBs@@ -112,8 +113,10 @@   fmap     (D.addAttr (toDjotAttr (if autoid then "" else ident,                          filter (/= "section") cls,-                         filter (\(k,_) -> k /= "wrapper") kvs))) . D.section-     <$> blocksToDjot bls+                         filter (\(k,_) -> k /= "wrapper") kvs) <>+                toDjotAttr ("", [c | c <- hcls, c `notElem` cls], hkvs)))+         . D.section+     <$> blocksToDjot (Header lev mempty ils : bls) blockToDjot (Div attr@(ident,cls,kvs) bls)   | Just "1" <- lookup "wrapper" kvs     = fmap (D.addAttr@@ -212,6 +215,7 @@ inlineToDjot (Strikeout ils) = D.delete <$> inlinesToDjot ils inlineToDjot (Subscript ils) = D.subscript <$> inlinesToDjot ils inlineToDjot (Superscript ils) = D.superscript <$> inlinesToDjot ils+inlineToDjot (Span ("",["mark"],[]) ils) = D.highlight <$> inlinesToDjot ils inlineToDjot (Span attr@(ident,cls,kvs) ils)   | Just "1" <- lookup "wrapper" kvs     = fmap (D.addAttr
src/Text/Pandoc/Writers/DocBook.hs view
@@ -3,7 +3,7 @@ {-# LANGUAGE PatternGuards     #-} {- |    Module      : Text.Pandoc.Writers.DocBook-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -17,7 +17,7 @@ import Data.Generics (everywhere, mkT) import Data.List (nub, partition) import Data.Maybe (isNothing)-import Data.Monoid (All (..), Any (..))+import Data.Monoid (All (..)) import Data.Text (Text) import qualified Data.Text as T import qualified Text.Pandoc.Builder as B@@ -174,7 +174,8 @@ blockToDocBook :: PandocMonad m => WriterOptions -> Block -> DB m (Doc Text) -- Add ids to paragraphs in divs with ids - this is needed for -- pandoc-citeproc to get link anchors in bibliographies:-blockToDocBook opts (Div (id',"section":_,_) (Header lvl (_,classes,attrs) ils : xs)) = do+blockToDocBook opts (Div (id',"section":_classes,divattrs)+                     (Header lvl (_,hclasses,_) ils : xs)) = do   version <- ask   -- DocBook doesn't allow sections with no content, so insert some if needed   let bs = if null xs@@ -198,7 +199,7 @@        -- Populate miscAttr with Header.Attr.attributes, filtering out non-valid DocBook section attributes, id, and xml:id       -- Also enrich the role attribute with certain class tokens-      miscAttr = enrichRole (filter (isSectionAttr version) attrs) classes+      miscAttr = enrichRole (filter (isSectionAttr version) divattrs) hclasses       attribs = nsAttr <> idAttr <> miscAttr   title' <- inlinesToDocBook opts ils   contents <- blocksToDocBook opts bs@@ -245,16 +246,15 @@                         <$> inlinesToDocBook opts lst   | otherwise         = inTagsIndented "para" <$> inlinesToDocBook opts lst blockToDocBook opts (LineBlock lns) =-  blockToDocBook opts $ linesToPara lns+  inTags False "literallayout" [] . vcat <$> mapM (inlinesToDocBook opts) lns blockToDocBook opts (BlockQuote blocks) =   inTagsIndented "blockquote" <$> blocksToDocBook opts blocks blockToDocBook opts (CodeBlock (_,classes,_) str) = return $   literal ("<programlisting" <> lang <> ">") <> cr <>      flush (literal (escapeStringForXML str) <> cr <> literal "</programlisting>")-    where lang  = if null langs-                     then ""-                     else " language=\"" <> escapeStringForXML (head langs) <>-                          "\""+    where lang  = case langs of+                     [] -> ""+                     (l:_) -> " language=\"" <> escapeStringForXML l <> "\""           syntaxMap = writerSyntaxMap opts           isLang l    = T.toLower l `elem` map T.toLower (languages syntaxMap)           langsFrom s = if isLang s@@ -265,7 +265,7 @@   let attribs = [("spacing", "compact") | isTightList lst]   inTags True "itemizedlist" attribs <$> listItemsToDocBook opts lst blockToDocBook _ (OrderedList _ []) = return empty-blockToDocBook opts (OrderedList (start, numstyle, _) (first:rest)) = do+blockToDocBook opts (OrderedList (start, numstyle, _) items) = do   let numeration = case numstyle of                        DefaultStyle -> []                        Decimal      -> [("numeration", "arabic")]@@ -274,17 +274,10 @@                        LowerAlpha   -> [("numeration", "loweralpha")]                        UpperRoman   -> [("numeration", "upperroman")]                        LowerRoman   -> [("numeration", "lowerroman")]-      spacing    = [("spacing", "compact") | isTightList (first:rest)]-      attribs    = numeration <> spacing-  items <- if start == 1-              then listItemsToDocBook opts (first:rest)-              else do-                first' <- blocksToDocBook opts (map plainToPara first)-                rest' <- listItemsToDocBook opts rest-                return $-                  inTags True "listitem" [("override",tshow start)] first' $$-                   rest'-  return $ inTags True "orderedlist" attribs items+      spacing    = [("spacing", "compact") | isTightList items]+      startnum   = [("startingnumber", tshow start) | start /= 1]+      attribs    = numeration <> spacing <> startnum+  inTags True "orderedlist" attribs <$> listItemsToDocBook opts items blockToDocBook opts (DefinitionList lst) = do   let attribs = [("spacing", "compact") | isTightList $ concatMap snd lst]   inTags True "variablelist" attribs <$> deflistItemsToDocBook opts lst@@ -350,16 +343,6 @@         else inTagsIndented "figure" $              inTagsSimple "title" title $$              mconcat mediaobjects--hasLineBreaks :: [Inline] -> Bool-hasLineBreaks = getAny . query isLineBreak . walk removeNote-  where-    removeNote :: Inline -> Inline-    removeNote (Note _) = Str ""-    removeNote x        = x-    isLineBreak :: Inline -> Any-    isLineBreak LineBreak = Any True-    isLineBreak _         = Any False  alignmentToString :: Alignment -> Text alignmentToString alignment = case alignment of
src/Text/Pandoc/Writers/Docx.hs view
@@ -3,1702 +3,853 @@ {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE ViewPatterns        #-} {-# LANGUAGE FlexibleContexts    #-}-{-# LANGUAGE LambdaCase          #-}-{-# LANGUAGE OverloadedStrings   #-}-{-# LANGUAGE TypeApplications    #-}-{- |-   Module      : Text.Pandoc.Writers.Docx-   Copyright   : Copyright (C) 2012-2023 John MacFarlane-   License     : GNU GPL, version 2 or above--   Maintainer  : John MacFarlane <jgm@berkeley.edu>-   Stability   : alpha-   Portability : portable--Conversion of 'Pandoc' documents to docx.--}-module Text.Pandoc.Writers.Docx ( writeDocx ) where-import Codec.Archive.Zip-    ( Archive(zEntries),-      addEntryToArchive,-      emptyArchive,-      findEntryByPath,-      fromArchive,-      toArchive,-      toEntry,-      Entry(eRelativePath) )-import Control.Applicative ((<|>))-import Control.Monad (MonadPlus(mplus), unless, when, foldM)-import Control.Monad.Except (catchError, throwError)-import Control.Monad.Reader-    ( asks, MonadReader(local), MonadTrans(lift), ReaderT(runReaderT) )-import Control.Monad.State.Strict ( StateT(runStateT), gets, modify )-import qualified Data.ByteString.Lazy as BL-import Data.Containers.ListUtils (nubOrd)-import Data.Char (isSpace, isLetter)-import Data.List (intercalate, isPrefixOf, isSuffixOf, sortBy)-import Data.Ord (comparing)-import Data.String (fromString)-import qualified Data.Map as M-import Data.Maybe (fromMaybe, isNothing, mapMaybe, maybeToList, isJust)-import qualified Data.Set as Set-import qualified Data.Text as T-import Data.Text (Text)-import qualified Data.Text.Lazy as TL-import Data.Time.Clock.POSIX-import Data.Digest.Pure.SHA (sha1, showDigest)-import Skylighting-import Text.Pandoc.Class (PandocMonad, report, toLang, getMediaBag)-import Text.Pandoc.Translations (Term(Abstract), translateTerm)-import Text.Pandoc.MediaBag (lookupMedia, MediaItem(..))-import qualified Text.Pandoc.Translations as Term-import qualified Text.Pandoc.Class.PandocMonad as P-import Text.Pandoc.Data (readDataFile, readDefaultDataFile)-import Data.Time-import Text.Pandoc.UTF8 (fromTextLazy)-import Text.Pandoc.Definition-import Text.Pandoc.Generic-import Text.Pandoc.Highlighting (highlight)-import Text.Pandoc.Error-import Text.Pandoc.ImageSize-import Text.Pandoc.Logging-import Text.Pandoc.MIME (extensionFromMimeType, getMimeType, getMimeTypeDef)-import Text.Pandoc.Options-import Text.Pandoc.Readers.Docx.Parse (extractTarget)-import Text.Pandoc.Writers.Docx.StyleMap-import Text.Pandoc.Writers.Docx.Table as Table-import Text.Pandoc.Writers.Docx.Types-import Text.Pandoc.Shared-import Text.Pandoc.Walk-import qualified Text.Pandoc.Writers.GridTable as Grid-import Text.Pandoc.Writers.Math-import Text.Pandoc.Writers.Shared-import Text.TeXMath-import Text.Pandoc.Writers.OOXML-import Text.Pandoc.XML.Light as XML-import Data.Generics (mkT, everywhere)-import Text.Collate.Lang (renderLang, Lang(..))---- from wml.xsd EG_RPrBase-rPrTagOrder :: M.Map Text Int-rPrTagOrder =-  M.fromList-  (zip [ "rStyle"-    , "rFonts"-    , "b"-    , "bCs"-    , "i"-    , "iCs"-    , "caps"-    , "smallCaps"-    , "strike"-    , "dstrike"-    , "outline"-    , "shadow"-    , "emboss"-    , "imprint"-    , "noProof"-    , "snapToGrid"-    , "vanish"-    , "webHidden"-    , "color"-    , "spacing"-    , "w"-    , "kern"-    , "position"-    , "sz"-    , "szCs"-    , "highlight"-    , "u"-    , "effect"-    , "bdr"-    , "shd"-    , "fitText"-    , "vertAlign"-    , "rtl"-    , "cs"-    , "em"-    , "lang"-    , "eastAsianLayout"-    , "specVanish"-    , "oMath"-    ] [0..])--sortSquashed :: [Element] -> [Element]-sortSquashed l =-  sortBy (comparing tagIndex) l-  where-    tagIndex :: Element -> Int-    tagIndex el =-      fromMaybe 0 (M.lookup tag rPrTagOrder)-      where tag = (qName . elName) el--squashProps :: EnvProps -> [Element]-squashProps (EnvProps Nothing es) = sortSquashed es-squashProps (EnvProps (Just e) es) = sortSquashed (e : es)--renumIdMap :: Int -> [Element] -> M.Map Text Text-renumIdMap _ [] = M.empty-renumIdMap n (e:es)-  | Just oldId <- findAttr (QName "Id" Nothing Nothing) e =-      M.insert oldId ("rId" <> tshow n) (renumIdMap (n+1) es)-  | otherwise = renumIdMap n es--replaceAttr :: (QName -> Bool) -> Text -> [XML.Attr] -> [XML.Attr]-replaceAttr f val = map $-    \a -> if f (attrKey a) then XML.Attr (attrKey a) val else a--renumId :: (QName -> Bool) -> M.Map Text Text -> Element -> Element-renumId f renumMap e-  | Just oldId <- findAttrBy f e-  , Just newId <- M.lookup oldId renumMap =-    let attrs' = replaceAttr f newId (elAttribs e)-    in-     e { elAttribs = attrs' }-  | otherwise = e--renumIds :: (QName -> Bool) -> M.Map Text Text -> [Element] -> [Element]-renumIds f renumMap = map (renumId f renumMap)---- | Certain characters are invalid in XML even if escaped.--- See #1992-stripInvalidChars :: Text -> Text-stripInvalidChars = T.filter isValidChar---- | See XML reference-isValidChar :: Char -> Bool-isValidChar '\t' = True-isValidChar '\n' = True-isValidChar '\r' = True-isValidChar '\xFFFE' = False-isValidChar '\xFFFF' = False-isValidChar c = (' ' <= c && c <= '\xD7FF') || ('\xE000' <= c)--writeDocx :: (PandocMonad m)-          => WriterOptions  -- ^ Writer options-          -> Pandoc         -- ^ Document to convert-          -> m BL.ByteString-writeDocx opts doc = do-  let Pandoc meta blocks = walk fixDisplayMath doc-  setupTranslations meta-  let blocks' = makeSections True Nothing blocks-  let doc' = Pandoc meta blocks'--  username <- P.lookupEnv "USERNAME"-  utctime <- P.getTimestamp-  oldUserDataDir <- P.getUserDataDir-  P.setUserDataDir Nothing-  res <- readDefaultDataFile "reference.docx"-  P.setUserDataDir oldUserDataDir-  let distArchive = toArchive $ BL.fromStrict res-  refArchive <- case writerReferenceDoc opts of-                     Just f  -> toArchive . BL.fromStrict . fst-                                   <$> P.fetchItem (T.pack f)-                     Nothing -> toArchive . BL.fromStrict <$>-                          readDataFile "reference.docx"--  parsedDoc <- parseXml refArchive distArchive "word/document.xml"-  let wname f qn = qPrefix qn == Just "w" && f (qName qn)-  let mbsectpr = filterElementName (wname (=="sectPr")) parsedDoc--  -- Gets the template size-  let mbpgsz = mbsectpr >>= filterElementName (wname (=="pgSz"))-  let mbAttrSzWidth = mbpgsz >>= lookupAttrBy ((=="w") . qName) . elAttribs--  let mbpgmar = mbsectpr >>= filterElementName (wname (=="pgMar"))-  let mbAttrMarLeft = mbpgmar >>= lookupAttrBy ((=="left") . qName) . elAttribs-  let mbAttrMarRight = mbpgmar >>= lookupAttrBy ((=="right") . qName) . elAttribs--  -- Get the available area (converting the size and the margins to int and-  -- doing the difference-  let pgContentWidth = do-                         w <- mbAttrSzWidth >>= safeRead-                         r <- mbAttrMarRight >>= safeRead-                         l <- mbAttrMarLeft >>= safeRead-                         pure $ w - r - l--  -- styles-  mblang <- toLang $ getLang opts meta-  -- TODO FIXME avoid this generic traversal!-  -- lang is in w:docDefaults /  w:rPr  /  w:lang-  let addLang :: Element -> Element-      addLang = case mblang of-                  Nothing -> id-                  Just l  -> everywhere (mkT (go l))-        where-          go :: Lang -> Element -> Element-          go lang e'-           | qName (elName e') == "lang"-             = if isEastAsianLang lang-                  then e'{ elAttribs =-                             map (setattr "eastAsia" (renderLang lang)) $-                             elAttribs e' }-                  else-                    if isBidiLang lang-                       then e'{ elAttribs =-                                 map (setattr "bidi" (renderLang lang)) $-                                 elAttribs e' }-                       else e'{ elAttribs =-                                 map (setattr "val" (renderLang lang)) $-                                 elAttribs e' }-           | otherwise = e'--          setattr attrname l (XML.Attr qn@(QName s _ _) _)-            | s == attrname  = XML.Attr qn l-          setattr _ _ x      = x--          isEastAsianLang Lang{ langLanguage = lang } =-             lang == "zh" || lang == "jp" || lang == "ko"-          isBidiLang Lang{ langLanguage = lang } =-             lang == "he" || lang == "ar"--  let stylepath = "word/styles.xml"-  styledoc <- addLang <$> parseXml refArchive distArchive stylepath--  -- parse styledoc for heading styles-  let styleMaps = getStyleMaps refArchive--  let tocTitle = case lookupMetaInlines "toc-title" meta of-                   [] -> stTocTitle defaultWriterState-                   ls -> ls--  let initialSt = defaultWriterState {-          stStyleMaps  = styleMaps-        , stTocTitle   = tocTitle-        , stCurId      = 20-        }--  let isRTLmeta = case lookupMeta "dir" meta of-        Just (MetaString "rtl")        -> True-        Just (MetaInlines [Str "rtl"]) -> True-        _                              -> False--  let env = defaultWriterEnv {-          envRTL = isRTLmeta-        , envChangesAuthor = fromMaybe "unknown" username-        , envChangesDate   = T.pack $ formatTime defaultTimeLocale "%FT%XZ" utctime-        , envPrintWidth = maybe 420 (`quot` 20) pgContentWidth-        }---  ((contents, footnotes, comments), st) <- runStateT-                         (runReaderT-                          (writeOpenXML opts{writerWrapText = WrapNone} doc')-                          env)-                         initialSt-  let epochtime = floor $ utcTimeToPOSIXSeconds utctime-  let imgs = M.elems $ stImages st--  -- create entries for images in word/media/...-  let toImageEntry (_,path,_,img) = toEntry ("word/" ++ path) epochtime $ toLazy img-  let imageEntries = map toImageEntry imgs--  let stdAttributes =-            [("xmlns:w","http://schemas.openxmlformats.org/wordprocessingml/2006/main")-            ,("xmlns:m","http://schemas.openxmlformats.org/officeDocument/2006/math")-            ,("xmlns:r","http://schemas.openxmlformats.org/officeDocument/2006/relationships")-            ,("xmlns:o","urn:schemas-microsoft-com:office:office")-            ,("xmlns:v","urn:schemas-microsoft-com:vml")-            ,("xmlns:w10","urn:schemas-microsoft-com:office:word")-            ,("xmlns:a","http://schemas.openxmlformats.org/drawingml/2006/main")-            ,("xmlns:pic","http://schemas.openxmlformats.org/drawingml/2006/picture")-            ,("xmlns:wp","http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing")]---  parsedRels <- parseXml refArchive distArchive "word/_rels/document.xml.rels"-  let isHeaderNode e = findAttr (QName "Type" Nothing Nothing) e == Just "http://schemas.openxmlformats.org/officeDocument/2006/relationships/header"-  let isFooterNode e = findAttr (QName "Type" Nothing Nothing) e == Just "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer"-  let headers = filterElements isHeaderNode parsedRels-  let footers = filterElements isFooterNode parsedRels--  -- we create [Content_Types].xml and word/_rels/document.xml.rels-  -- from scratch rather than reading from reference.docx,-  -- because Word sometimes changes these files when a reference.docx is modified,-  -- e.g. deleting the reference to footnotes.xml or removing default entries-  -- for image content types.--  -- [Content_Types].xml-  let mkOverrideNode (part', contentType') = mknode "Override"-               [("PartName", T.pack part')-               ,("ContentType", contentType')] ()-  let mkImageOverride (_, imgpath, mbMimeType, _) =-          mkOverrideNode ("/word/" <> imgpath,-                          fromMaybe "application/octet-stream" mbMimeType)-  let mkMediaOverride imgpath =-          mkOverrideNode ("/" <> imgpath, getMimeTypeDef imgpath)-  let overrides = map mkOverrideNode (-                  [("/word/webSettings.xml",-                    "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml")-                  ,("/word/numbering.xml",-                    "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml")-                  ,("/word/settings.xml",-                    "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml")-                  ,("/word/theme/theme1.xml",-                    "application/vnd.openxmlformats-officedocument.theme+xml")-                  ,("/word/fontTable.xml",-                    "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml")-                  ,("/docProps/app.xml",-                    "application/vnd.openxmlformats-officedocument.extended-properties+xml")-                  ,("/docProps/core.xml",-                    "application/vnd.openxmlformats-package.core-properties+xml")-                  ,("/docProps/custom.xml",-                    "application/vnd.openxmlformats-officedocument.custom-properties+xml")-                  ,("/word/styles.xml",-                    "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml")-                  ,("/word/document.xml",-                    "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml")-                  ,("/word/comments.xml",-                    "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml")-                  ,("/word/footnotes.xml",-                    "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml")-                  ] ++-                  map (\x -> (maybe "" (T.unpack . ("/word/" <>)) (extractTarget x),-                       "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml")) headers ++-                  map (\x -> (maybe "" (T.unpack . ("/word/" <>)) (extractTarget x),-                       "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml")) footers) ++-                    map mkImageOverride imgs ++-                    [ mkMediaOverride (eRelativePath e)-                        | e <- zEntries refArchive-                        , "word/media/" `isPrefixOf` eRelativePath e ]--  let mkDefaultNode (ext, mt) =-        mknode "Default" [("Extension",ext),("ContentType",mt)] ()-  let defaultnodes = map mkDefaultNode-        [("xml", "application/xml"),-         ("rels", "application/vnd.openxmlformats-package.relationships+xml"),-         ("odttf",-           "application/vnd.openxmlformats-officedocument.obfuscatedFont")]-  let contentTypesDoc = mknode "Types" [("xmlns","http://schemas.openxmlformats.org/package/2006/content-types")] $ defaultnodes ++ overrides-  let contentTypesEntry = toEntry "[Content_Types].xml" epochtime-        $ renderXml contentTypesDoc--  -- word/_rels/document.xml.rels-  let toBaseRel (url', id', target') = mknode "Relationship"-                                          [("Type",url')-                                          ,("Id",id')-                                          ,("Target",target')] ()-  let baserels' = map toBaseRel-                    [("http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering",-                      "rId1",-                      "numbering.xml")-                    ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles",-                      "rId2",-                      "styles.xml")-                    ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings",-                      "rId3",-                      "settings.xml")-                    ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings",-                      "rId4",-                      "webSettings.xml")-                    ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable",-                      "rId5",-                      "fontTable.xml")-                    ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme",-                      "rId6",-                      "theme/theme1.xml")-                    ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes",-                      "rId7",-                      "footnotes.xml")-                    ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments",-                      "rId8",-                      "comments.xml")-                    ]--  let idMap = renumIdMap (length baserels' + 1) (headers ++ footers)-  let renumHeaders = renumIds (\q -> qName q == "Id") idMap headers-  let renumFooters = renumIds (\q -> qName q == "Id") idMap footers-  let baserels = baserels' ++ renumHeaders ++ renumFooters-  let toImgRel (ident,path,_,_) =  mknode "Relationship" [("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"),("Id",T.pack ident),("Target",T.pack path)] ()-  let imgrels = map toImgRel imgs-  let toLinkRel (src,ident) =  mknode "Relationship" [("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"),("Id",ident),("Target",src),("TargetMode","External") ] ()-  let linkrels = map toLinkRel $ M.toList $ stExternalLinks st-  let reldoc = mknode "Relationships" [("xmlns","http://schemas.openxmlformats.org/package/2006/relationships")] $ baserels ++ imgrels ++ linkrels-  let relEntry = toEntry "word/_rels/document.xml.rels" epochtime-        $ renderXml reldoc---  -- adjust contents to add sectPr from reference.docx-  let sectpr = case mbsectpr of-        Just sectpr' -> let cs = renumIds-                                 (\q -> qName q == "id" && qPrefix q == Just "r")-                                 idMap-                                 (elChildren sectpr')-                        in-                         add_attrs (elAttribs sectpr') $ mknode "w:sectPr" [] cs-        Nothing      -> mknode "w:sectPr" [] ()--  -- let sectpr = fromMaybe (mknode "w:sectPr" [] ()) mbsectpr'-  let contents' = contents ++ [Elem sectpr]-  let docContents = mknode "w:document" stdAttributes-                    $ mknode "w:body" [] contents'----  -- word/document.xml-  let contentEntry = toEntry "word/document.xml" epochtime-                     $ renderXml docContents--  -- footnotes-  let notes = mknode "w:footnotes" stdAttributes footnotes-  let footnotesEntry = toEntry "word/footnotes.xml" epochtime $ renderXml notes--  -- footnote rels-  let footnoteRelEntry = toEntry "word/_rels/footnotes.xml.rels" epochtime-        $ renderXml $ mknode "Relationships" [("xmlns","http://schemas.openxmlformats.org/package/2006/relationships")]-        linkrels--  -- comments-  let commentsEntry = toEntry "word/comments.xml" epochtime-        $ renderXml $ mknode "w:comments" stdAttributes comments--  -- styles--  -- We only want to inject paragraph and text properties that-  -- are not already in the style map. Note that keys in the stylemap-  -- are normalized as lowercase.-  let newDynamicParaProps = filter-        (\sty -> not $ hasStyleName sty $ smParaStyle styleMaps)-        (Set.toList $ stDynamicParaProps st)--      newDynamicTextProps = filter-        (\sty -> not $ hasStyleName sty $ smCharStyle styleMaps)-        (Set.toList $ stDynamicTextProps st)--  let newstyles = map newParaPropToOpenXml newDynamicParaProps ++-                  map newTextPropToOpenXml newDynamicTextProps ++-                  maybe [] (styleToOpenXml styleMaps) (writerHighlightStyle opts)-  let styledoc' = styledoc{ elContent = elContent styledoc ++-                                           map Elem newstyles }-  let styleEntry = toEntry stylepath epochtime $ renderXml styledoc'--  -- construct word/numbering.xml-  let numpath = "word/numbering.xml"-  numbering <- parseXml refArchive distArchive numpath-  let newNumElts = mkNumbering (stLists st)-  let pandocAdded e =-       case findAttrBy ((== "abstractNumId") . qName) e >>= safeRead of-         Just numid -> numid >= (990 :: Int)-         Nothing    ->-           case findAttrBy ((== "numId") . qName) e >>= safeRead of-             Just numid -> numid >= (1000 :: Int)-             Nothing    -> False-  let oldElts = filter (not . pandocAdded) $ onlyElems (elContent numbering)-  let allElts = oldElts ++ newNumElts-  let numEntry = toEntry numpath epochtime $ renderXml numbering{ elContent =-                       -- we want all the abstractNums first, then the nums,-                       -- otherwise things break:-                       [Elem e | e <- allElts-                               , qName (elName e) == "abstractNum" ] ++-                       [Elem e | e <- allElts-                               , qName (elName e) == "num" ] }--  let keywords = case lookupMeta "keywords" meta of-                       Just (MetaList xs) -> map stringify xs-                       _                  -> []--  -- docProps/core.xml-  let docPropsPath = "docProps/core.xml"-  let extraCoreProps = ["subject","lang","category","description"]-  let extraCorePropsMap = M.fromList $ zip extraCoreProps-                       ["dc:subject","dc:language","cp:category","dc:description"]-  let lookupMetaString' :: Text -> Meta -> Text-      lookupMetaString' key' meta' =-        case key' of-             "description"    -> T.intercalate "_x000d_\n" (map stringify $ lookupMetaBlocks "description" meta')-             key''            -> lookupMetaString key'' meta'--  let docProps = mknode "cp:coreProperties"-          [("xmlns:cp","http://schemas.openxmlformats.org/package/2006/metadata/core-properties")-          ,("xmlns:dc","http://purl.org/dc/elements/1.1/")-          ,("xmlns:dcterms","http://purl.org/dc/terms/")-          ,("xmlns:dcmitype","http://purl.org/dc/dcmitype/")-          ,("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance")]-          $ mktnode "dc:title" [] (stringify $ docTitle meta)-          : mktnode "dc:creator" [] (T.intercalate "; " (map stringify $ docAuthors meta))-          : [ mktnode (M.findWithDefault "" k extraCorePropsMap) [] (lookupMetaString' k meta)-            | k <- M.keys (unMeta meta), k `elem` extraCoreProps]-          ++ mknode "cp:keywords" [] (T.intercalate ", " keywords)-          : (\x -> [ mknode "dcterms:created" [("xsi:type","dcterms:W3CDTF")] x-                   , mknode "dcterms:modified" [("xsi:type","dcterms:W3CDTF")] x-                   ]) (T.pack $ formatTime defaultTimeLocale "%FT%XZ" utctime)-  let docPropsEntry = toEntry docPropsPath epochtime $ renderXml docProps--  -- docProps/custom.xml-  let customProperties :: [(Text, Text)]-      customProperties = [ (k, lookupMetaString k meta)-                         | k <- M.keys (unMeta meta)-                         , k `notElem` (["title", "author", "keywords"]-                                       ++ extraCoreProps)]-  let mkCustomProp (k, v) pid = mknode "property"-         [("fmtid","{D5CDD505-2E9C-101B-9397-08002B2CF9AE}")-         ,("pid", tshow pid)-         ,("name", k)] $ mknode "vt:lpwstr" [] v-  let customPropsPath = "docProps/custom.xml"-  let customProps = mknode "Properties"-          [("xmlns","http://schemas.openxmlformats.org/officeDocument/2006/custom-properties")-          ,("xmlns:vt","http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes")-          ] $ zipWith mkCustomProp customProperties [(2 :: Int)..]-  let customPropsEntry = toEntry customPropsPath epochtime $ renderXml customProps--  let relsPath = "_rels/.rels"-  let rels = mknode "Relationships" [("xmlns", "http://schemas.openxmlformats.org/package/2006/relationships")]-        $ map (\attrs -> mknode "Relationship" attrs ())-        [ [("Id","rId1")-          ,("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument")-          ,("Target","word/document.xml")]-        , [("Id","rId4")-          ,("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties")-          ,("Target","docProps/app.xml")]-        , [("Id","rId3")-          ,("Type","http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties")-          ,("Target","docProps/core.xml")]-        , [("Id","rId5")-          ,("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties")-          ,("Target","docProps/custom.xml")]-        ]-  let relsEntry = toEntry relsPath epochtime $ renderXml rels--  -- we use dist archive for settings.xml, because Word sometimes-  -- adds references to footnotes or endnotes we don't have...-  -- we do, however, copy some settings over from reference-  let settingsPath = "word/settings.xml"--  settingsEntry <- copyChildren refArchive distArchive settingsPath epochtime-                      -- note: these must go in the following order:-                     [ "writeProtection"-                     , "view"-                     , "zoom"-                     , "removePersonalInformation"-                     , "removeDateAndTime"-                     , "doNotDisplayPageBoundaries"-                     , "displayBackgroundShape"-                     , "printPostScriptOverText"-                     , "printFractionalCharacterWidth"-                     , "printFormsData"-                     , "embedTrueTypeFonts"-                     , "embedSystemFonts"-                     , "saveSubsetFonts"-                     , "saveFormsData"-                     , "mirrorMargins"-                     , "alignBordersAndEdges"-                     , "bordersDoNotSurroundHeader"-                     , "bordersDoNotSurroundFooter"-                     , "gutterAtTop"-                     , "hideSpellingErrors"-                     , "hideGrammaticalErrors"-                     , "activeWritingStyle"-                     , "proofState"-                     , "formsDesign"-                     , "attachedTemplate"-                     , "linkStyles"-                     , "stylePaneFormatFilter"-                     , "stylePaneSortMethod"-                     , "documentType"-                     , "mailMerge"-                     , "revisionView"-                     , "trackRevisions"-                     , "doNotTrackMoves"-                     , "doNotTrackFormatting"-                     , "documentProtection"-                     , "autoFormatOverride"-                     , "styleLockTheme"-                     , "styleLockQFSet"-                     , "defaultTabStop"-                     , "autoHyphenation"-                     , "consecutiveHyphenLimit"-                     , "hyphenationZone"-                     , "doNotHyphenateCaps"-                     , "showEnvelope"-                     , "summaryLength"-                     , "clickAndTypeStyle"-                     , "defaultTableStyle"-                     , "evenAndOddHeaders"-                     , "bookFoldRevPrinting"-                     , "bookFoldPrinting"-                     , "bookFoldPrintingSheets"-                     , "drawingGridHorizontalSpacing"-                     , "drawingGridVerticalSpacing"-                     , "displayHorizontalDrawingGridEvery"-                     , "displayVerticalDrawingGridEvery"-                     , "doNotUseMarginsForDrawingGridOrigin"-                     , "drawingGridHorizontalOrigin"-                     , "drawingGridVerticalOrigin"-                     , "doNotShadeFormData"-                     , "noPunctuationKerning"-                     , "characterSpacingControl"-                     , "printTwoOnOne"-                     , "strictFirstAndLastChars"-                     , "noLineBreaksAfter"-                     , "noLineBreaksBefore"-                     , "savePreviewPicture"-                     , "doNotValidateAgainstSchema"-                     , "saveInvalidXml"-                     , "ignoreMixedContent"-                     , "alwaysShowPlaceholderText"-                     , "doNotDemarcateInvalidXml"-                     , "saveXmlDataOnly"-                     , "useXSLTWhenSaving"-                     , "saveThroughXslt"-                     , "showXMLTags"-                     , "alwaysMergeEmptyNamespace"-                     , "updateFields"-                     , "hdrShapeDefaults"-                     -- , "footnotePr" -- this can cause problems, see #9522-                     -- , "endnotePr"-                     , "compat"-                     , "docVars"-                     , "rsids"-                     , "attachedSchema"-                     , "themeFontLang"-                     , "clrSchemeMapping"-                     , "doNotIncludeSubdocsInStats"-                     , "doNotAutoCompressPictures"-                     , "forceUpgrade"-                     , "captions"-                     , "readModeInkLockDown"-                     , "smartTagType"-                     , "shapeDefaults"-                     , "doNotEmbedSmartTags"-                     , "decimalSymbol"-                     , "listSeparator" ]--  let entryFromArchive arch path =-         maybe (throwError $ PandocSomeError-                           $ T.pack $ path ++ " missing in reference docx")-               return-               (findEntryByPath path arch `mplus` findEntryByPath path distArchive)-  docPropsAppEntry <- entryFromArchive refArchive "docProps/app.xml"-  themeEntry <- entryFromArchive refArchive "word/theme/theme1.xml"-  fontTableEntry <- entryFromArchive refArchive "word/fontTable.xml"-  let fontTableRelsEntries = maybeToList $-       findEntryByPath "word/_rels/fontTable.xml.rels" refArchive-  let fontEntries = [entry | entry <- zEntries refArchive-                           , "word/fonts/" `isPrefixOf` (eRelativePath entry)]-                        -- or parse fontTable.xml.rels?-  webSettingsEntry <- entryFromArchive refArchive "word/webSettings.xml"-  headerFooterEntries <- mapM (entryFromArchive refArchive . ("word/" ++)) $-                         mapMaybe (fmap T.unpack . extractTarget)-                         (headers ++ footers)-  let miscRelEntries = [ e | e <- zEntries refArchive-                       , "word/_rels/" `isPrefixOf` eRelativePath e-                       , ".xml.rels" `isSuffixOf` eRelativePath e-                       , eRelativePath e /= "word/_rels/document.xml.rels"-                       , eRelativePath e /= "word/_rels/footnotes.xml.rels" ]-  let otherMediaEntries = [ e | e <- zEntries refArchive-                          , "word/media/" `isPrefixOf` eRelativePath e ]--  -- Create archive-  let archive = foldr addEntryToArchive emptyArchive $-                  contentTypesEntry : relsEntry : contentEntry : relEntry :-                  footnoteRelEntry : numEntry : styleEntry : footnotesEntry :-                  commentsEntry :-                  docPropsEntry : docPropsAppEntry : customPropsEntry :-                  themeEntry :-                  settingsEntry : webSettingsEntry :-                  fontTableEntry :-                  fontTableRelsEntries ++ fontEntries ++-                  imageEntries ++ headerFooterEntries ++-                  miscRelEntries ++ otherMediaEntries-  return $ fromArchive archive--newParaPropToOpenXml :: ParaStyleName -> Element-newParaPropToOpenXml (fromStyleName -> s) =-  let styleId = T.filter (not . isSpace) s-  in mknode "w:style" [ ("w:type", "paragraph")-                      , ("w:customStyle", "1")-                      , ("w:styleId", styleId)]-     [ mknode "w:name" [("w:val", s)] ()-     , mknode "w:basedOn" [("w:val","BodyText")] ()-     , mknode "w:qFormat" [] ()-     ]--newTextPropToOpenXml :: CharStyleName -> Element-newTextPropToOpenXml (fromStyleName -> s) =-  let styleId = T.filter (not . isSpace) s-  in mknode "w:style" [ ("w:type", "character")-                      , ("w:customStyle", "1")-                      , ("w:styleId", styleId)]-     [ mknode "w:name" [("w:val", s)] ()-     , mknode "w:basedOn" [("w:val","BodyTextChar")] ()-     ]--styleToOpenXml :: StyleMaps -> Style -> [Element]-styleToOpenXml sm style =-  maybeToList parStyle ++ mapMaybe toStyle alltoktypes-  where alltoktypes = enumFromTo KeywordTok NormalTok-        toStyle toktype | hasStyleName (fromString $ show toktype) (smCharStyle sm) = Nothing-                        | otherwise = Just $-                          mknode "w:style" [("w:type","character"),-                           ("w:customStyle","1"),("w:styleId", tshow toktype)]-                             [ mknode "w:name" [("w:val", tshow toktype)] ()-                             , mknode "w:basedOn" [("w:val","VerbatimChar")] ()-                             , mknode "w:rPr" [] $-                               [ mknode "w:b" [] () | tokFeature tokenBold toktype ] ++-                               [ mknode "w:i" [] () | tokFeature tokenItalic toktype ] ++-                               [ mknode "w:color" [("w:val", tokCol toktype)] ()-                                 | tokCol toktype /= "auto" ] ++-                               [ mknode "w:u" [] () | tokFeature tokenUnderline toktype ] ++-                               [ mknode "w:shd" [("w:val","clear")-                                                ,("w:fill",tokBg toktype)] ()-                                 | tokBg toktype /= "auto" ]-                             ]-        tokStyles = tokenStyles style-        tokFeature f toktype = maybe False f $ M.lookup toktype tokStyles-        tokCol toktype = maybe "auto" (T.pack . drop 1 . fromColor)-                         $ (tokenColor =<< M.lookup toktype tokStyles)-                           `mplus` defaultColor style-        tokBg toktype = maybe "auto" (T.pack . drop 1 . fromColor)-                         $ (tokenBackground =<< M.lookup toktype tokStyles)-                           `mplus` backgroundColor style-        parStyle | hasStyleName "Source Code" (smParaStyle sm) = Nothing-                 | otherwise = Just $-                   mknode "w:style" [("w:type","paragraph"),-                           ("w:customStyle","1"),("w:styleId","SourceCode")]-                             [ mknode "w:name" [("w:val","Source Code")] ()-                             , mknode "w:basedOn" [("w:val","Normal")] ()-                             , mknode "w:link" [("w:val","VerbatimChar")] ()-                             , mknode "w:pPr" []-                               $ mknode "w:wordWrap" [("w:val","off")] ()-                               :-                         maybe [] (\col -> [mknode "w:shd" [("w:val","clear"),("w:fill", T.pack $ drop 1 $ fromColor col)] ()]) (backgroundColor style)-                             ]--copyChildren :: (PandocMonad m)-             => Archive -> Archive -> String -> Integer -> [Text] -> m Entry-copyChildren refArchive distArchive path timestamp elNames = do-  ref  <- parseXml refArchive distArchive path-  dist <- parseXml distArchive distArchive path-  els <- foldM (addEl ref dist) [] (reverse elNames)-  return $ toEntry path timestamp-         $ renderXml dist{ elContent = map cleanElem els }-  where-    addEl ref dist els name =-      case filterChildName (hasName name) ref `mplus`-             filterChildName (hasName name) dist of-        Just el -> pure (el : els)-        Nothing -> pure els-    hasName name = (== name) . qName-    cleanElem el@Element{elName=name} = Elem el{elName=name{qURI=Nothing}}---- this is the lowest number used for a list numId-baseListId :: Int-baseListId = 1000--mkNumbering :: [ListMarker] -> [Element]-mkNumbering lists =-  elts ++ zipWith mkNum lists [baseListId..(baseListId + length lists - 1)]-    where elts = map mkAbstractNum (nubOrd lists)--maxListLevel :: Int-maxListLevel = 8--mkNum :: ListMarker -> Int -> Element-mkNum marker numid =-  mknode "w:num" [("w:numId",tshow numid)]-   $ mknode "w:abstractNumId" [("w:val",listMarkerToId marker)] ()-   : case marker of-       NoMarker     -> []-       BulletMarker -> []-       NumberMarker _ _ start ->-          map (\lvl -> mknode "w:lvlOverride" [("w:ilvl",tshow (lvl :: Int))]-              $ mknode "w:startOverride" [("w:val",tshow start)] ())-                [0..maxListLevel]--mkAbstractNum :: ListMarker -> Element-mkAbstractNum marker =-  mknode "w:abstractNum" [("w:abstractNumId",listMarkerToId marker)]-    $ mknode "w:nsid" [("w:val", T.justifyRight 8 '0' ("A" <> listMarkerToId marker))] ()-    : mknode "w:multiLevelType" [("w:val","multilevel")] ()-    : map (mkLvl marker)-      [0..maxListLevel]--mkLvl :: ListMarker -> Int -> Element-mkLvl marker lvl =-  mknode "w:lvl" [("w:ilvl",tshow lvl)] $-    [ mknode "w:start" [("w:val",start)] ()-      | marker /= NoMarker && marker /= BulletMarker ] ++-    [ mknode "w:numFmt" [("w:val",fmt)] ()-    , mknode "w:lvlText" [("w:val", lvltxt)] ()-    , mknode "w:lvlJc" [("w:val","left")] ()-    , mknode "w:pPr" []-      [ mknode "w:ind" [ ("w:left",tshow $ lvl * step + step)-                       , ("w:hanging",tshow (hang :: Int))-                       ] ()-      ]-    ]-    where (fmt, lvltxt, start) =-            case marker of-                 NoMarker             -> ("bullet"," ","1")-                 BulletMarker         -> ("bullet",bulletFor lvl,"1")-                 NumberMarker st de n -> (styleFor st lvl-                                         ,patternFor de ("%" <> tshow (lvl + 1))-                                         ,tshow n)-          step = 720-          hang = 480-          bulletFor 0 = "\x2022"  -- filled circle-          bulletFor 1 = "\x2013"  -- en dash-          bulletFor 2 = "\x2022"  -- hyphen bullet-          bulletFor 3 = "\x2013"-          bulletFor 4 = "\x2022"-          bulletFor 5 = "\x2013"-          bulletFor x = bulletFor (x `mod` 6)-          styleFor UpperAlpha _   = "upperLetter"-          styleFor LowerAlpha _   = "lowerLetter"-          styleFor UpperRoman _   = "upperRoman"-          styleFor LowerRoman _   = "lowerRoman"-          styleFor Decimal _      = "decimal"-          styleFor DefaultStyle 0 = "decimal"-          styleFor DefaultStyle 1 = "lowerLetter"-          styleFor DefaultStyle 2 = "lowerRoman"-          styleFor DefaultStyle 3 = "decimal"-          styleFor DefaultStyle 4 = "lowerLetter"-          styleFor DefaultStyle 5 = "lowerRoman"-          styleFor DefaultStyle x = styleFor DefaultStyle (x `mod` 6)-          styleFor _ _            = "decimal"-          patternFor OneParen s  = s <> ")"-          patternFor TwoParens s = "(" <> s <> ")"-          patternFor _ s         = s <> "."--getNumId :: (PandocMonad m) => WS m Int-getNumId = (((baseListId - 1) +) . length) `fmap` gets stLists---makeTOC :: (PandocMonad m) => WriterOptions -> WS m [Element]-makeTOC opts = do-  let depth = "1-" <> tshow (writerTOCDepth opts)-  let tocCmd = "TOC \\o \"" <> depth <> "\" \\h \\z \\u"-  tocTitle <- gets stTocTitle-  title <- withParaPropM (pStyleM "TOC Heading") (blocksToOpenXML opts [Para tocTitle])-  return-    [mknode "w:sdt" [] [-      mknode "w:sdtPr" [] (-        mknode "w:docPartObj" []-          [mknode "w:docPartGallery" [("w:val","Table of Contents")] (),-          mknode "w:docPartUnique" [] ()]-         -- w:docPartObj-      ), -- w:sdtPr-      mknode "w:sdtContent" [] (title ++ [ Elem $-        mknode "w:p" [] (-          mknode "w:r" [] [-            mknode "w:fldChar" [("w:fldCharType","begin"),("w:dirty","true")] (),-            mknode "w:instrText" [("xml:space","preserve")] tocCmd,-            mknode "w:fldChar" [("w:fldCharType","separate")] (),-            mknode "w:fldChar" [("w:fldCharType","end")] ()-          ] -- w:r-        ) -- w:p-      ])-    ]] -- w:sdt---- | Convert Pandoc document to two lists of--- OpenXML elements (the main document and footnotes).-writeOpenXML :: (PandocMonad m)-             => WriterOptions -> Pandoc-             -> WS m ([Content], [Element], [Element])-writeOpenXML opts (Pandoc meta blocks) = do-  let tit = docTitle meta-  let auths = docAuthors meta-  let dat = docDate meta-  let abstract' = lookupMetaBlocks "abstract" meta-  let subtitle' = lookupMetaInlines "subtitle" meta-  let includeTOC = writerTableOfContents opts || lookupMetaBool "toc" meta-  title <- withParaPropM (pStyleM "Title") $ blocksToOpenXML opts [Para tit | not (null tit)]-  subtitle <- withParaPropM (pStyleM "Subtitle") $ blocksToOpenXML opts [Para subtitle' | not (null subtitle')]-  authors <- withParaPropM (pStyleM "Author") $ blocksToOpenXML opts $-       map Para auths-  date <- withParaPropM (pStyleM "Date") $ blocksToOpenXML opts [Para dat | not (null dat)]-  abstract <- if null abstract'-                 then return []-                 else do-                   abstractTitle <- case lookupMeta "abstract-title" meta of-                       Just (MetaBlocks bs)   -> pure $ stringify bs-                       Just (MetaInlines ils) -> pure $ stringify ils-                       Just (MetaString s)    -> pure s-                       _                      -> translateTerm Abstract-                   abstractTit <- withParaPropM (pStyleM "AbstractTitle") $-                                   blocksToOpenXML opts-                                     [Para [Str abstractTitle]]-                   abstractContents <- withParaPropM (pStyleM "Abstract") $-                                         blocksToOpenXML opts abstract'-                   return $ abstractTit <> abstractContents--  let convertSpace (Str x : Space : Str y : xs) = Str (x <> " " <> y) : xs-      convertSpace (Str x : Str y : xs)         = Str (x <> y) : xs-      convertSpace xs                           = xs-  let blocks' = bottomUp convertSpace blocks-  doc' <- setFirstPara >> blocksToOpenXML opts blocks'-  notes' <- reverse <$> gets stFootnotes-  comments <- reverse <$> gets stComments-  let toComment (kvs, ils) = do-        annotation <- inlinesToOpenXML opts ils-        return $-          mknode "w:comment" [("w:" <> k, v) | (k,v) <- kvs]-            [ mknode "w:p" [] $-              map Elem-              [ mknode "w:pPr" []-                [ mknode "w:pStyle" [("w:val", "CommentText")] () ]-              , mknode "w:r" []-                [ mknode "w:rPr" []-                  [ mknode "w:rStyle" [("w:val", "CommentReference")] ()-                  ]-                  , mknode "w:annotationRef" [] ()-                ]-              ] ++ annotation-            ]-  comments' <- mapM toComment comments-  toc <- if includeTOC-            then makeTOC opts-            else return []-  let meta' = title ++ subtitle ++ authors ++ date ++ abstract ++ map Elem toc-  return (meta' ++ doc', notes', comments')---- | Convert a list of Pandoc blocks to OpenXML.-blocksToOpenXML :: (PandocMonad m) => WriterOptions -> [Block] -> WS m [Content]-blocksToOpenXML opts = fmap concat . mapM (blockToOpenXML opts) . separateTables . filter (not . isForeignRawBlock)--isForeignRawBlock :: Block -> Bool-isForeignRawBlock (RawBlock format _) = format /= "openxml"-isForeignRawBlock _                   = False---- Word combines adjacent tables unless you put an empty paragraph between--- them.  See #4315.-separateTables :: [Block] -> [Block]-separateTables [] = []-separateTables (x@Table{}:xs@(Table{}:_)) =-  x : RawBlock (Format "openxml") "<w:p />" : separateTables xs-separateTables (x:xs) = x : separateTables xs--rStyleM :: (PandocMonad m) => CharStyleName -> WS m XML.Element-rStyleM styleName = do-  cStyleMap <- gets (smCharStyle . stStyleMaps)-  let sty' = getStyleIdFromName styleName cStyleMap-  return $ mknode "w:rStyle" [("w:val", fromStyleId sty')] ()--getUniqueId :: (PandocMonad m) => WS m Text-getUniqueId = do-  n <- gets stCurId-  modify $ \st -> st{stCurId = n + 1}-  return $ tshow n---- | Key for specifying user-defined docx styles.-dynamicStyleKey :: Text-dynamicStyleKey = "custom-style"---- | Convert a Pandoc block element to OpenXML.-blockToOpenXML :: (PandocMonad m) => WriterOptions -> Block -> WS m [Content]-blockToOpenXML opts blk = withDirection $ blockToOpenXML' opts blk--blockToOpenXML' :: (PandocMonad m) => WriterOptions -> Block -> WS m [Content]-blockToOpenXML' opts (Div (ident,_classes,kvs) bs) = do-  stylemod <- case lookup dynamicStyleKey kvs of-                   Just (fromString . T.unpack -> sty) -> do-                      modify $ \s ->-                        s{stDynamicParaProps = Set.insert sty-                             (stDynamicParaProps s)}-                      return $ withParaPropM (pStyleM sty)-                   _ -> return id-  dirmod <- case lookup "dir" kvs of-                 Just "rtl" -> return $ local (\env -> env { envRTL = True })-                 Just "ltr" -> return $ local (\env -> env { envRTL = False })-                 _ -> return id-  let (hs, bs') = if ident == "refs"-                     then span isHeaderBlock bs-                     else ([], bs)-  let bibmod = if ident == "refs"-                  then withParaPropM (pStyleM "Bibliography")-                  else id-  let langmod = case lookup "lang" kvs of-                  Nothing -> id-                  Just lang -> local (\env -> env{envLang = Just lang})-  header <- dirmod $ stylemod $ blocksToOpenXML opts hs-  contents <- dirmod $ bibmod $ stylemod $ langmod $ blocksToOpenXML opts bs'-  wrapBookmark ident $ header <> contents-blockToOpenXML' opts (Header lev (ident,_,kvs) lst) = do-  setFirstPara-  paraProps <- withParaPropM (pStyleM (fromString $ "Heading "++show lev)) $-                    getParaProps False-  number <--        if writerNumberSections opts-           then-             case lookup "number" kvs of-                Just n -> do-                   num <- withTextPropM (rStyleM "SectionNumber")-                            (inlineToOpenXML opts (Str n))-                   return $ num ++ [Elem $ mknode "w:r" [] [mknode "w:tab" [] ()]]-                Nothing -> return []-           else return []-  contents <- (number ++) <$> inlinesToOpenXML opts lst-  if T.null ident-     then return [Elem $ mknode "w:p" [] (map Elem paraProps ++ contents)]-     else do-       let bookmarkName = ident-       modify $ \s -> s{ stSectionIds = Set.insert bookmarkName-                                      $ stSectionIds s }-       bookmarkedContents <- wrapBookmark bookmarkName contents-       return [Elem $ mknode "w:p" [] (map Elem paraProps ++ bookmarkedContents)]-blockToOpenXML' opts (Plain lst) = do-  isInTable <- gets stInTable-  isInList <- gets stInList-  let block = blockToOpenXML opts (Para lst)-  prop <- pStyleM "Compact"-  if isInTable || isInList-     then withParaProp prop block-     else block-blockToOpenXML' opts (Para lst)-  | null lst && not (isEnabled Ext_empty_paragraphs opts) = return []-  | otherwise = do-      isFirstPara <- gets stFirstPara-      let displayMathPara = case lst of-                                 [x] -> isDisplayMath x-                                 _   -> False-      paraProps <- getParaProps displayMathPara-      bodyTextStyle <- pStyleM $ if isFirstPara-                       then "First Paragraph"-                       else "Body Text"-      let paraProps' = case paraProps of-            []               -> [mknode "w:pPr" [] [bodyTextStyle]]-            ps               -> ps-      modify $ \s -> s { stFirstPara = False }-      contents <- inlinesToOpenXML opts lst-      return [Elem $ mknode "w:p" [] (map Elem paraProps' ++ contents)]-blockToOpenXML' opts (LineBlock lns) = blockToOpenXML opts $ linesToPara lns-blockToOpenXML' _ b@(RawBlock format str)-  | format == Format "openxml" = return [-        Text (CData CDataRaw str Nothing)-      ]-  | otherwise                  = do-      report $ BlockNotRendered b-      return []-blockToOpenXML' opts (BlockQuote blocks) = do-  inNote <- asks envInNote-  p <- withParaPropM (pStyleM-                       (if inNote-                           then "Footnote Block Text"-                           else "Block Text"))-       $ blocksToOpenXML opts blocks-  setFirstPara-  return p-blockToOpenXML' opts (CodeBlock attrs@(ident, _, _) str) = do-  p <- withParaPropM (pStyleM "Source Code") (blockToOpenXML opts $ Para [Code attrs str])-  setFirstPara-  wrapBookmark ident p-blockToOpenXML' _ HorizontalRule = do-  setFirstPara-  return [ Elem $-    mknode "w:p" [] $ mknode "w:r" [] $ mknode "w:pict" []-    $ mknode "v:rect" [("style","width:0;height:1.5pt"),-                       ("o:hralign","center"),-                       ("o:hrstd","t"),("o:hr","t")] () ]-blockToOpenXML' opts (Table attr caption colspecs thead tbodies tfoot) = do-  -- Remove extra paragraph indentation due to list items (#5947).-  -- This means that tables in lists will not be indented, but it-  -- avoids unwanted indentation in each cell.-  content <- tableToOpenXML opts-              (local (\env -> env{ envListLevel = -1 }) . blocksToOpenXML opts)-                 (Grid.toTable attr caption colspecs thead tbodies tfoot)-  let (tableId, _, _) = attr-  wrapBookmark tableId content-blockToOpenXML' opts el-  | BulletList lst <- el = addOpenXMLList BulletMarker lst-  | OrderedList (start, numstyle, numdelim) lst <- el-  = addOpenXMLList (NumberMarker numstyle numdelim start) lst-  where-    addOpenXMLList marker lst = do-      addList marker-      numid  <- getNumId-      exampleid <- case marker of-                        NumberMarker Example _ _ -> gets stExampleId-                        _ -> return Nothing-      l <- asList $ concat `fmap` mapM (listItemToOpenXML opts $ fromMaybe numid exampleid) lst-      setFirstPara-      return l-blockToOpenXML' opts (DefinitionList items) = do-  l <- concat `fmap` mapM (definitionListItemToOpenXML opts) items-  setFirstPara-  return l-blockToOpenXML' opts (Figure (ident, _, _) (Caption _ longcapt) body) = do-  setFirstPara-  fignum <- gets stNextFigureNum-  unless (null longcapt) $ modify $ \st -> st{ stNextFigureNum = fignum + 1 }-  let refid = if T.null ident-              then "ref_fig" <> tshow fignum-              else "ref_" <> ident-  figname <- translateTerm Term.Figure-  prop <- pStyleM $-    if null longcapt-    then "Figure"-    else "Captioned Figure"-  paraProps <- local-    (\env -> env { envParaProperties = EnvProps (Just prop) [] <>-                                       envParaProperties env })-    (getParaProps False)--  -- Figure contents-  let simpleImage x = do-        imgXML <- inlineToOpenXML opts x-        pure $ Elem (mknode "w:p" [] (map Elem paraProps ++ imgXML))-  contentsNode <- case body of-    [Plain [img@Image {}]] -> simpleImage img-    [Para  [img@Image {}]] -> simpleImage img-    _                      -> toFigureTable opts body-  -- Caption-  let imageCaption = withParaPropM (pStyleM "Image Caption")-                   . blocksToOpenXML opts-  let fstCaptionPara inlns = Para $-        if not $ isEnabled Ext_native_numbering opts-        then inlns-        else let rawfld = RawInline (Format "openxml") $ mconcat-                          [ "<w:fldSimple w:instr=\"SEQ Figure"-                          , " \\* ARABIC \"><w:r><w:t>"-                          , tshow fignum-                          , "</w:t></w:r></w:fldSimple>"-                          ]-             in Span (refid,[],[]) [Str (figname <> "\160") , rawfld]-                : Str ": " : inlns-  captionNode <- case longcapt of-    []              -> return []-    (Para xs  : bs) -> imageCaption (fstCaptionPara xs : bs)-    (Plain xs : bs) -> imageCaption (fstCaptionPara xs : bs)-    _               -> imageCaption longcapt-  return $ contentsNode : captionNode--toFigureTable :: PandocMonad m-              => WriterOptions -> [Block] -> WS m Content-toFigureTable opts blks = do-  modify $ \s -> s { stInTable = True }-  let ncols = length blks-  let textwidth = 7920  -- 5.5 in in twips       (1 twip == 1/20 pt)-  let cellfrac = 1 / fromIntegral ncols-  let colwidth = tshow @Integer $ floor (textwidth * cellfrac) -- twips-  let gridCols = replicate ncols $ mknode "w:gridCol" [("w:w", colwidth)] ()-  let scaleImage = \case-        Image attr@(ident, classes, attribs) alt tgt ->-          let dimWidth  = case dimension Width attr of-                            Nothing -> Percent (cellfrac * 100)-                            Just d  -> scaleDimension cellfrac d-              dimHeight = scaleDimension cellfrac <$> dimension Height attr-              attribs' = (tshow Width, tshow dimWidth) :-                         (case dimHeight of-                            Nothing -> id-                            Just h  -> ((tshow Height, tshow h) :))-                         [ (k, v) | (k, v) <- attribs-                                  , k `notElem` ["width", "height"]-                                  ]-          in Image (ident, classes, attribs') alt tgt-        x -> x-  let blockToCell = Table.OOXMLCell nullAttr AlignCenter 1 1 . (:[])-                  . walk scaleImage-  tblBody <- Table.rowToOpenXML (blocksToOpenXML opts) .-             Table.OOXMLRow Table.BodyRow nullAttr $-             map blockToCell blks-  let tbl = mknode "w:tbl" []-        ( mknode "w:tblPr" []-          [ mknode "w:tblStyle" [("w:val","FigureTable")] (),-            mknode "w:tblW" [ ("w:type", "auto"), ("w:w", "0") ] (),-            mknode "w:jc" [("w:val","center")] (),-            mknode "w:tblLook" [ ("w:firstRow", "0")-                               , ("w:lastRow", "0")-                               , ("w:firstColumn", "0")-                               , ("w:lastColumn", "0")-                               ] ()-          ]-          : mknode "w:tblGrid" [] gridCols-          : maybeToList tblBody-        )-  modify $ \s -> s { stInTable = False }-  return $ Elem tbl---definitionListItemToOpenXML  :: (PandocMonad m)-                             => WriterOptions -> ([Inline],[[Block]])-                             -> WS m [Content]-definitionListItemToOpenXML opts (term,defs) = do-  term' <- withParaPropM (pStyleM "Definition Term")-           $ blockToOpenXML opts (Para term)-  defs' <- withParaPropM (pStyleM "Definition")-           $ concat `fmap` mapM (blocksToOpenXML opts) defs-  return $ term' ++ defs'--addList :: (PandocMonad m) => ListMarker -> WS m ()-addList marker = do-  lists <- gets stLists-  lastExampleId <- gets stExampleId-  modify $ \st -> st{ stLists = lists ++ case marker of-                                         -- Use only first occurrence of Example for list declaration to avoid overhead-                                         NumberMarker Example _ _ | isJust lastExampleId -> []-                                         _ -> [marker]-                    , stExampleId = case marker of-                                         -- Reuse the same identifier for all other occurrences of Example-                                         NumberMarker Example _ _ -> lastExampleId <|> Just (baseListId + length lists)-                                         _ -> lastExampleId-                  }--listItemToOpenXML :: (PandocMonad m)-                  => WriterOptions-                  -> Int -> [Block]-                  -> WS m [Content]-listItemToOpenXML opts numid bs = do-  oldInList <- gets stInList-  modify $ \st -> st{ stInList = True }-  let isListBlock = \case-        BulletList{}  -> True-        OrderedList{} -> True-        _             -> False-  -- Prepend an empty string if the first entry is another-  -- list. Otherwise the outer bullet will disappear.-  let bs' = case bs of-                 [] -> []-                 first:rest -> if isListBlock first-                               then Plain [Str ""]:first:rest-                               else first:rest-  modify $ \st -> st{ stNumIdUsed = False }-  contents <- withNumId numid $ blocksToOpenXML opts bs'-  modify $ \st -> st{ stInList = oldInList }-  return contents---- | Convert a list of inline elements to OpenXML.-inlinesToOpenXML :: PandocMonad m => WriterOptions -> [Inline] -> WS m [Content]-inlinesToOpenXML opts lst = concat `fmap` mapM (inlineToOpenXML opts) lst--withNumId :: (PandocMonad m) => Int -> WS m a -> WS m a-withNumId numid = local $ \env -> env{ envListNumId = numid }--asList :: (PandocMonad m) => WS m a -> WS m a-asList = local $ \env -> env{ envListLevel = envListLevel env + 1 }--getTextProps :: (PandocMonad m) => WS m [Element]-getTextProps = do-  props <- asks envTextProperties-  mblang <- asks envLang-  let langnode = case mblang of-                   Nothing -> mempty-                   Just l  -> EnvProps Nothing-                               [mknode "w:lang" [("w:val", l)] ()]-  let squashed = squashProps (props <> langnode)-  return [mknode "w:rPr" [] squashed | (not . null) squashed]--withTextProp :: PandocMonad m => Element -> WS m a -> WS m a-withTextProp d p =-  local (\env -> env {envTextProperties = ep <> envTextProperties env}) p-  where ep = if isStyle d then EnvProps (Just d) [] else EnvProps Nothing [d]--withTextPropM :: PandocMonad m => WS m Element -> WS m a -> WS m a-withTextPropM md p = do-  d <- md-  withTextProp d p--getParaProps :: PandocMonad m => Bool -> WS m [Element]-getParaProps displayMathPara = do-  props <- asks envParaProperties-  listLevel <- asks envListLevel-  numid <- asks envListNumId-  numIdUsed <- gets stNumIdUsed-  -- clear numId after first use to support multiple paragraphs in the same bullet-  -- baseListId is the code for no list marker-  let numid' = if numIdUsed then baseListId else numid-  modify $ \st -> st{ stNumIdUsed = True }-  let listPr = [mknode "w:numPr" []-                [ mknode "w:ilvl" [("w:val",tshow listLevel)] ()-                , mknode "w:numId" [("w:val",tshow numid')] () ] | listLevel >= 0 && not displayMathPara]-  return $ case squashProps (EnvProps Nothing listPr <> props) of-                [] -> []-                ps -> [mknode "w:pPr" [] ps]--formattedString :: PandocMonad m => Text -> WS m [Element]-formattedString str =-  -- properly handle soft hyphens-  case splitTextBy (=='\173') str of-      [w] -> formattedString' w-      ws  -> do-         sh <- formattedRun [mknode "w:softHyphen" [] ()]-         intercalate sh <$> mapM formattedString' ws--formattedString' :: PandocMonad m => Text -> WS m [Element]-formattedString' str = do-  inDel <- asks envInDel-  formattedRun [ mktnode (if inDel then "w:delText" else "w:t")-                 [("xml:space","preserve")] (stripInvalidChars str) ]--formattedRun :: PandocMonad m => [Element] -> WS m [Element]-formattedRun els = do-  props <- getTextProps-  return [ mknode "w:r" [] $ props ++ els ]---- | Convert an inline element to OpenXML.-inlineToOpenXML :: PandocMonad m => WriterOptions -> Inline -> WS m [Content]-inlineToOpenXML opts il = withDirection $ inlineToOpenXML' opts il--inlineToOpenXML' :: PandocMonad m => WriterOptions -> Inline -> WS m [Content]-inlineToOpenXML' _ (Str str) =-  map Elem <$> formattedString str-inlineToOpenXML' opts Space = inlineToOpenXML opts (Str " ")-inlineToOpenXML' opts SoftBreak = inlineToOpenXML opts (Str " ")-inlineToOpenXML' opts (Span ("",["mark"],[]) ils) =-  withTextProp (mknode "w:highlight" [("w:val","yellow")] ()) $-    inlinesToOpenXML opts ils-inlineToOpenXML' opts (Span ("",["csl-block"],[]) ils) =-  inlinesToOpenXML opts ils-inlineToOpenXML' opts (Span ("",["csl-left-margin"],[]) ils) =-  inlinesToOpenXML opts ils-inlineToOpenXML' opts (Span ("",["csl-right-inline"],[]) ils) =-   ([Elem $-     mknode "w:r" []-     (mknode "w:t"-       [("xml:space","preserve")]-       ("\t" :: Text))] ++)-    <$> inlinesToOpenXML opts ils-inlineToOpenXML' opts (Span ("",["csl-indent"],[]) ils) =-  inlinesToOpenXML opts ils-inlineToOpenXML' _ (Span (ident,["comment-start"],kvs) ils) = do-  -- prefer the "id" in kvs, since that is the one produced by the docx-  -- reader.-  let ident' = fromMaybe ident (lookup "id" kvs)-      kvs' = filter (("id" /=) . fst) kvs-  modify $ \st -> st{ stComments = (("id",ident'):kvs', ils) : stComments st }-  return [ Elem $ mknode "w:commentRangeStart" [("w:id", ident')] () ]-inlineToOpenXML' _ (Span (ident,["comment-end"],kvs) _) =-  -- prefer the "id" in kvs, since that is the one produced by the docx-  -- reader.-  let ident' = fromMaybe ident (lookup "id" kvs)-  in return . map Elem $-     [ mknode "w:commentRangeEnd" [("w:id", ident')] ()-     , mknode "w:r" []-       [ mknode "w:rPr" []-         [ mknode "w:rStyle" [("w:val", "CommentReference")] () ]-       , mknode "w:commentReference" [("w:id", ident')] () ]-     ]-inlineToOpenXML' opts (Span (ident,classes,kvs) ils) = do-  stylemod <- case lookup dynamicStyleKey kvs of-                   Just (fromString . T.unpack -> sty) -> do-                      modify $ \s ->-                        s{stDynamicTextProps = Set.insert sty-                              (stDynamicTextProps s)}-                      return $ withTextPropM (rStyleM sty)-                   _ -> return id-  let dirmod = case lookup "dir" kvs of-                 Just "rtl" -> local (\env -> env { envRTL = True })-                 Just "ltr" -> local (\env -> env { envRTL = False })-                 _          -> id-      off x = withTextProp (mknode x [("w:val","0")] ())-      pmod =  (if "csl-no-emph" `elem` classes then off "w:i" else id) .-              (if "csl-no-strong" `elem` classes then off "w:b" else id) .-              (if "csl-no-smallcaps" `elem` classes-                  then off "w:smallCaps"-                  else id)-      getChangeAuthorDate = do-        defaultAuthor <- asks envChangesAuthor-        let author = fromMaybe defaultAuthor (lookup "author" kvs)-        let mdate = lookup "date" kvs-        return $ ("w:author", author) :-                   maybe [] (\date -> [("w:date", date)]) mdate-  insmod <- if "insertion" `elem` classes-               then do-                 changeAuthorDate <- getChangeAuthorDate-                 insId <- gets stInsId-                 modify $ \s -> s{stInsId = insId + 1}-                 return $ \f -> do-                   x <- f-                   return [Elem $-                           mknode "w:ins"-                             (("w:id", tshow insId) : changeAuthorDate) x]-               else return id-  delmod <- if "deletion" `elem` classes-               then do-                 changeAuthorDate <- getChangeAuthorDate-                 delId <- gets stDelId-                 modify $ \s -> s{stDelId = delId + 1}-                 return $ \f -> local (\env->env{envInDel=True}) $ do-                   x <- f-                   return [Elem $ mknode "w:del"-                             (("w:id", tshow delId) : changeAuthorDate) x]-               else return id-  let langmod = case lookup "lang" kvs of-                  Nothing -> id-                  Just lang -> local (\env -> env{envLang = Just lang})-  contents <- insmod $ delmod $ dirmod $ stylemod $ pmod $-              langmod $ inlinesToOpenXML opts ils-  wrapBookmark ident contents-inlineToOpenXML' opts (Strong lst) =-  withTextProp (mknode "w:bCs" [] ()) $ -- needed for LTR, #6911-  withTextProp (mknode "w:b" [] ()) $-  inlinesToOpenXML opts lst-inlineToOpenXML' opts (Emph lst) =-  withTextProp (mknode "w:iCs" [] ()) $  -- needed for LTR, #6911-  withTextProp (mknode "w:i" [] ()) $-  inlinesToOpenXML opts lst-inlineToOpenXML' opts (Underline lst) =-  withTextProp (mknode "w:u" [("w:val","single")] ()) $-    inlinesToOpenXML opts lst-inlineToOpenXML' opts (Subscript lst) =-  withTextProp (mknode "w:vertAlign" [("w:val","subscript")] ())-  $ inlinesToOpenXML opts lst-inlineToOpenXML' opts (Superscript lst) =-  withTextProp (mknode "w:vertAlign" [("w:val","superscript")] ())-  $ inlinesToOpenXML opts lst-inlineToOpenXML' opts (SmallCaps lst) =-  withTextProp (mknode "w:smallCaps" [] ())-  $ inlinesToOpenXML opts lst-inlineToOpenXML' opts (Strikeout lst) =-  withTextProp (mknode "w:strike" [] ())-  $ inlinesToOpenXML opts lst-inlineToOpenXML' _ LineBreak = return [Elem br]-inlineToOpenXML' _ il@(RawInline f str)-  | f == Format "openxml" = return-                            [Text (CData CDataRaw str Nothing)]-  | otherwise             = do-      report $ InlineNotRendered il-      return []-inlineToOpenXML' opts (Quoted quoteType lst) =-  inlinesToOpenXML opts $ [Str open] ++ lst ++ [Str close]-    where (open, close) = case quoteType of-                            SingleQuote -> ("\x2018", "\x2019")-                            DoubleQuote -> ("\x201C", "\x201D")-inlineToOpenXML' opts (Math mathType str) = do-  when (mathType == DisplayMath) setFirstPara-  res <- (lift . lift) (convertMath writeOMML mathType str)-  case res of-       Right r -> return [Elem $ fromXLElement r]-       Left il -> inlineToOpenXML' opts il-inlineToOpenXML' opts (Cite _ lst) = inlinesToOpenXML opts lst-inlineToOpenXML' opts (Code attrs str) = do-  let alltoktypes = [KeywordTok ..]-  tokTypesMap <- mapM (\tt -> (,) tt <$> rStyleM (fromString $ show tt)) alltoktypes-  let unhighlighted = (map Elem . intercalate [br]) `fmap`-                       mapM formattedString (T.lines str)-      formatOpenXML _fmtOpts = intercalate [br] . map (map toHlTok)-      toHlTok (toktype,tok) =-        mknode "w:r" []-          [ mknode "w:rPr" [] $-            maybeToList (lookup toktype tokTypesMap)-            , mknode "w:t" [("xml:space","preserve")] tok ]-  withTextPropM (rStyleM "Verbatim Char")-    $ if isNothing (writerHighlightStyle opts)-          then unhighlighted-          else case highlight (writerSyntaxMap opts)-                      formatOpenXML attrs str of-                    Right h  -> return (map Elem h)-                    Left msg -> do-                      unless (T.null msg) $ report $ CouldNotHighlight msg-                      unhighlighted-inlineToOpenXML' opts (Note bs) = do-  notes <- gets stFootnotes-  notenum <- getUniqueId-  footnoteStyle <- rStyleM "Footnote Reference"-  let notemarker = mknode "w:r" []-                   [ mknode "w:rPr" [] footnoteStyle-                   , mknode "w:footnoteRef" [] () ]-  let notemarkerXml = RawInline (Format "openxml") $ ppElement notemarker-  let insertNoteRef (Plain ils : xs) = Plain (notemarkerXml : Space : ils) : xs-      insertNoteRef (Para ils  : xs) = Para  (notemarkerXml : Space : ils) : xs-      insertNoteRef xs               = Para [notemarkerXml] : xs--  contents <- local (\env -> env{ envListLevel = -1-                                , envParaProperties = mempty-                                , envTextProperties = mempty-                                , envInNote = True })-              (withParaPropM (pStyleM "Footnote Text") $-               blocksToOpenXML opts $ insertNoteRef bs)-  let newnote = mknode "w:footnote" [("w:id", notenum)] contents-  modify $ \s -> s{ stFootnotes = newnote : notes }-  return [ Elem $ mknode "w:r" []-           [ mknode "w:rPr" [] footnoteStyle-           , mknode "w:footnoteReference" [("w:id", notenum)] () ] ]--- internal link:-inlineToOpenXML' opts (Link _ txt (T.uncons -> Just ('#', xs),_)) = do-  contents <- withTextPropM (rStyleM "Hyperlink") $ inlinesToOpenXML opts txt-  return-    [ Elem $ mknode "w:hyperlink" [("w:anchor", toBookmarkName xs)] contents ]--- external link:-inlineToOpenXML' opts (Link _ txt (src,_)) = do-  contents <- withTextPropM (rStyleM "Hyperlink") $ inlinesToOpenXML opts txt-  extlinks <- gets stExternalLinks-  id' <- case M.lookup src extlinks of-            Just i   -> return i-            Nothing  -> do-              i <- ("rId" <>) <$> getUniqueId-              modify $ \st -> st{ stExternalLinks =-                        M.insert src i extlinks }-              return i-  return [ Elem $ mknode "w:hyperlink" [("r:id",id')] contents ]-inlineToOpenXML' opts (Image attr@(imgident, _, _) alt (src, title)) = do-  pageWidth <- asks envPrintWidth-  imgs <- gets stImages-  let-    stImage = M.lookup (T.unpack src) imgs-    generateImgElt (ident, _fp, mt, img) = do-      docprid <- getUniqueId-      nvpicprid <- getUniqueId-      (blipAttrs, blipContents) <--        case T.takeWhile (/=';') <$> mt of-          Just "image/svg+xml" -> do-            -- get fallback png-            mediabag <- getMediaBag-            mbFallback <--              case lookupMedia (T.unpack (src <> ".png")) mediabag of-                Just item -> do-                  id' <- T.unpack . ("rId" <>) <$> getUniqueId-                  let fp' = "media/" <> id' <> ".png"-                  let imgdata = (id',-                                 fp',-                                 Just (mediaMimeType item),-                                 BL.toStrict $ mediaContents item)-                  modify $ \st -> st { stImages =-                            M.insert fp' imgdata $ stImages st }-                  return $ Just id'-                Nothing -> return Nothing-            let extLst = mknode "a:extLst" []-                            [ mknode "a:ext"-                              [("uri","{28A0092B-C50C-407E-A947-70E740481C1C}")]-                              [ mknode "a14:useLocalDpi"-                                [("xmlns:a14","http://schemas.microsoft.com/office/drawing/2010/main"),-                                 ("val","0")] () ]-                            , mknode "a:ext"-                              [("uri","{96DAC541-7B7A-43D3-8B79-37D633B846F1}")]-                              [ mknode "asvg:svgBlip"-                                [("xmlns:asvg", "http://schemas.microsoft.com/office/drawing/2016/SVG/main"),-                                 ("r:embed",T.pack ident)] () ]-                            ]-            return (maybe [] (\id'' -> [("r:embed", T.pack id'')]) mbFallback,-                    [extLst])-          _ -> return ([("r:embed", T.pack ident)], [])-      let-        (xpt,ypt) = desiredSizeInPoints opts attr-               (either (const def) id (imageSize opts img))-        -- 12700 emu = 1 pt-        pageWidthPt = case dimension Width attr of-                        Just (Percent a) -> pageWidth * (floor $ a * 127)-                        _                -> pageWidth * 12700-        (xemu,yemu) = fitToPage (xpt * 12700, ypt * 12700) pageWidthPt-        cNvPicPr = mknode "pic:cNvPicPr" [] $-                         mknode "a:picLocks" [("noChangeArrowheads","1")-                                             ,("noChangeAspect","1")] ()-        nvPicPr  = mknode "pic:nvPicPr" []-                        [ mknode "pic:cNvPr"-                            [("descr",src)-                            ,("id", nvpicprid)-                            ,("name","Picture")] ()-                        , cNvPicPr ]-        blipFill = mknode "pic:blipFill" []-          [ mknode "a:blip" blipAttrs blipContents-          , mknode "a:stretch" [] $-              mknode "a:fillRect" [] ()-          ]-        xfrm =    mknode "a:xfrm" []-                        [ mknode "a:off" [("x","0"),("y","0")] ()-                        , mknode "a:ext" [("cx",tshow xemu)-                                         ,("cy",tshow yemu)] () ]-        prstGeom = mknode "a:prstGeom" [("prst","rect")] $-                         mknode "a:avLst" [] ()-        ln =      mknode "a:ln" [("w","9525")]-                        [ mknode "a:noFill" [] ()-                        , mknode "a:headEnd" [] ()-                        , mknode "a:tailEnd" [] () ]-        spPr =    mknode "pic:spPr" [("bwMode","auto")]-                        [xfrm, prstGeom, mknode "a:noFill" [] (), ln]-        graphic = mknode "a:graphic" [] $-          mknode "a:graphicData"-            [("uri","http://schemas.openxmlformats.org/drawingml/2006/picture")]-            [ mknode "pic:pic" []-              [ nvPicPr-              , blipFill-              , spPr-              ]-            ]-        imgElt = mknode "w:r" [] $-          mknode "w:drawing" [] $-            mknode "wp:inline" []-              [ mknode "wp:extent" [("cx",tshow xemu),("cy",tshow yemu)] ()-              , mknode "wp:effectExtent"-                [("b","0"),("l","0"),("r","0"),("t","0")] ()-              , mknode "wp:docPr"-                [ ("descr", stringify alt)-                , ("title", title)-                , ("id", docprid)-                , ("name","Picture")-                ] ()-              , graphic-              ]-      return [Elem imgElt]--  wrapBookmark imgident =<< case stImage of-    Just imgData -> generateImgElt imgData-    Nothing -> ( do --try-      (img, mt) <- P.fetchItem src-      ident <- ("rId" <>) <$> getUniqueId--      let-        imgext = case mt >>= extensionFromMimeType of-          Just x    -> "." <> x-          Nothing   -> case imageType img of-            Just Png  -> ".png"-            Just Jpeg -> ".jpeg"-            Just Gif  -> ".gif"-            Just Pdf  -> ".pdf"-            Just Eps  -> ".eps"-            Just Svg  -> ".svg"-            Just Emf  -> ".emf"-            Just Tiff -> ".tiff"-            Nothing   -> ""-        imgpath = "media/" <> ident <> imgext-        mbMimeType = mt <|> getMimeType (T.unpack imgpath)--        imgData = (T.unpack ident, T.unpack imgpath, mbMimeType, img)--      if T.null imgext-         then -- without an extension there is no rule for content type-           inlinesToOpenXML opts alt -- return alt to avoid corrupted docx-         else do-           -- insert mime type to use in constructing [Content_Types].xml-           modify $ \st -> st { stImages = M.insert (T.unpack src) imgData $ stImages st }-           generateImgElt imgData-      )-      `catchError` ( \e -> do-        report $ CouldNotFetchResource src $ T.pack (show e)-        -- emit alt text-        inlinesToOpenXML opts alt-      )--br :: Element-br = mknode "w:r" [] [mknode "w:br" [] ()]---withDirection :: PandocMonad m => WS m a -> WS m a-withDirection x = do-  isRTL <- asks envRTL-  paraProps <- asks envParaProperties-  textProps <- asks envTextProperties-  -- We want to clean all bidirection (bidi) and right-to-left (rtl)-  -- properties from the props first. This is because we don't want-  -- them to stack up.-  let paraProps' = filter (\e -> (qName . elName) e /= "bidi") (otherElements paraProps)-      textProps' = filter (\e -> (qName . elName) e /= "rtl") (otherElements textProps)-      paraStyle = styleElement paraProps-      textStyle = styleElement textProps-  if isRTL-    -- if we are going right-to-left, we (re?)add the properties.-    then flip local x $-         \env -> env { envParaProperties = EnvProps paraStyle $ mknode "w:bidi" [] () : paraProps'-                     , envTextProperties = EnvProps textStyle $ mknode "w:rtl" [] () : textProps'-                     }-    else flip local x $ \env -> env { envParaProperties = EnvProps paraStyle paraProps'-                                    , envTextProperties = EnvProps textStyle textProps'-                                    }--wrapBookmark :: (PandocMonad m) => Text -> [Content] -> WS m [Content]-wrapBookmark "" contents = return contents-wrapBookmark ident contents = do-  id' <- getUniqueId-  let bookmarkStart = mknode "w:bookmarkStart"-                       [("w:id", id')-                       ,("w:name", toBookmarkName ident)] ()-      bookmarkEnd = mknode "w:bookmarkEnd" [("w:id", id')] ()-  return $ Elem bookmarkStart : contents ++ [Elem bookmarkEnd]---- Word imposes a 40 character limit on bookmark names and requires--- that they begin with a letter.  So we just use a hash of the--- identifier when otherwise we'd have an illegal bookmark name.-toBookmarkName :: Text -> Text-toBookmarkName s-  | Just (c, _) <- T.uncons s-  , isLetter c-  , T.length s <= 40 = s-  | otherwise = T.pack $ 'X' : drop 1 (showDigest (sha1 (fromTextLazy $ TL.fromStrict s)))+{-# LANGUAGE OverloadedStrings   #-}+{- |+   Module      : Text.Pandoc.Writers.Docx+   Copyright   : Copyright (C) 2012-2025 John MacFarlane+   License     : GNU GPL, version 2 or above++   Maintainer  : John MacFarlane <jgm@berkeley.edu>+   Stability   : alpha+   Portability : portable++Conversion of 'Pandoc' documents to docx.+-}+module Text.Pandoc.Writers.Docx ( writeDocx ) where+import Codec.Archive.Zip+    ( Archive(zEntries),+      addEntryToArchive,+      emptyArchive,+      findEntryByPath,+      fromArchive,+      toArchive,+      toEntry,+      Entry(eRelativePath) )+import Control.Monad (MonadPlus(mplus), foldM)+import Control.Monad.Except (throwError)+import Control.Monad.Reader ( ReaderT(runReaderT) )+import Control.Monad.State.Strict ( StateT(runStateT) )+import qualified Data.ByteString as B+import qualified Data.ByteString.Lazy as BL+import Data.Containers.ListUtils (nubOrd)+import Data.Char (isSpace)+import Data.List (isPrefixOf, isSuffixOf)+import Data.String (fromString)+import qualified Data.Map as M+import Data.Maybe (fromMaybe, mapMaybe, maybeToList)+import qualified Data.Set as Set+import qualified Data.Text as T+import Data.Text (Text)+import Data.Time.Clock.POSIX+import Skylighting+import Text.Pandoc.Class (PandocMonad, toLang)+import qualified Text.Pandoc.Class.PandocMonad as P+import Text.Pandoc.Data (readDataFile, readDefaultDataFile)+import Data.Time+import qualified Text.Pandoc.UTF8 as UTF8+import Text.Pandoc.Definition+import Text.Pandoc.Error+import Text.Pandoc.Highlighting (defaultStyle)+import Text.Pandoc.MIME (MimeType, getMimeTypeDef)+import Text.Pandoc.Options+import Text.Pandoc.Writers.Docx.StyleMap+import Text.Pandoc.Writers.Docx.Types+import Text.Pandoc.Writers.Docx.OpenXML (writeOpenXML, maxListLevel)+import Text.Pandoc.Shared+import Text.Pandoc.Walk+import Text.Pandoc.Writers.Shared+import Text.Pandoc.Writers.OOXML+import Text.Pandoc.XML.Light as XML+import Text.Collate.Lang (renderLang, Lang(..))++writeDocx :: (PandocMonad m)+          => WriterOptions  -- ^ Writer options+          -> Pandoc         -- ^ Document to convert+          -> m BL.ByteString+writeDocx opts doc = do+  -- Phase 1: Document preprocessing+  let Pandoc meta blocks = walk fixDisplayMath doc+  setupTranslations meta+  let blocks' = makeSectionsWithOffsets (writerNumberOffset opts)+                   True Nothing blocks+  let doc' = Pandoc meta blocks'++  -- Phase 2: Archive loading+  (refArchive, distArchive, username, utctime) <- loadArchives opts+  let epochtime = floor $ utcTimeToPOSIXSeconds utctime++  -- Phase 3: Page layout extraction+  (mbsectpr, pgContentWidth) <- extractPageLayout refArchive distArchive++  -- Phase 4: Language & style setup+  mblang <- toLang $ getLang opts meta+  let addLang = mkLangTransformer mblang+  styledoc <- addLang <$> parseXml refArchive distArchive "word/styles.xml"+  let styleMaps = getStyleMaps refArchive++  let tocTitle = case lookupMetaInlines "toc-title" meta of+                   [] -> stTocTitle defaultWriterState+                   ls -> ls++  let isRTLmeta = case lookupMeta "dir" meta of+        Just (MetaString "rtl")        -> True+        Just (MetaInlines [Str "rtl"]) -> True+        _                              -> False++  let env = defaultWriterEnv {+          envRTL = isRTLmeta+        , envChangesAuthor = fromMaybe "unknown" username+        , envChangesDate   = T.pack $ formatTime defaultTimeLocale "%FT%XZ" utctime+        , envPrintWidth = maybe 420 (`quot` 20) pgContentWidth+        }++  -- Phase 5: Relationship extraction+  (baserels, headers, footers, newMaxRelId) <- extractRelationships refArchive distArchive++  let initialSt = defaultWriterState {+          stStyleMaps  = styleMaps+        , stTocTitle   = tocTitle+        , stCurId      = newMaxRelId + 1+        }++  -- Phase 6: Core content generation+  -- adjust contents to add sectPr from reference.docx+  let sectpr = case mbsectpr of+        Just sectpr' -> add_attrs (elAttribs sectpr') $ mknode "w:sectPr" []+                             (elChildren sectpr')+        Nothing      -> mknode "w:sectPr" []+                          [ mknode "w:footnotePr" []+                            [ mknode "w:numRestart" [("w:val","eachSect")] () ]+                          ]++  ((contents, footnotes, comments), st) <- runStateT+                         (runReaderT+                          (writeOpenXML opts{ writerWrapText = WrapNone }+                                        doc')+                          env{ envSectPr = Just sectpr })+                         initialSt+  let imgs = M.elems $ stImages st++  -- Phase 7: XML document construction+  -- We create [Content_Types].xml and word/_rels/document.xml.rels+  -- from scratch rather than reading from reference.docx,+  -- because Word sometimes changes these files when a reference.docx is modified,+  -- e.g. deleting the reference to footnotes.xml or removing default entries+  -- for image content types.+  let contentTypesEntry = mkContentTypesEntry epochtime imgs headers footers refArchive+  let relEntry = mkDocumentRelsEntry epochtime baserels imgs (stExternalLinks st)+  let contentEntry = toEntry "word/document.xml" epochtime+                       (BL.fromStrict $ UTF8.fromText contents)+  let footnotesEntry = mkFootnotesEntry epochtime footnotes+  let footnoteRelEntry = mkFootnoteRelsEntry epochtime (stExternalLinks st)+  let commentsEntry = mkCommentsEntry epochtime comments+  let styleEntry = mkStylesEntry epochtime styledoc styleMaps st opts+  numEntry <- mkNumberingEntry refArchive distArchive epochtime (stLists st)+  let docPropsEntry = mkCorePropsEntry epochtime utctime meta+  let customPropsEntry = mkCustomPropsEntry epochtime meta+  let relsEntry = mkPackageRelsEntry epochtime++  -- we use dist archive for settings.xml, because Word sometimes+  -- adds references to footnotes or endnotes we don't have...+  -- we do, however, copy some settings over from reference+  settingsEntry <- copyChildren refArchive distArchive "word/settings.xml"+                     epochtime settingsElementNames++  -- Phase 8: Archive assembly+  let toImageEntry (_, path, _, img) = toEntry ("word/" ++ path) epochtime $ toLazy img+  let imageEntries = map toImageEntry imgs++  refEntries <- collectReferenceEntries refArchive distArchive headers footers++  let archive = foldr addEntryToArchive emptyArchive $+                  contentTypesEntry : relsEntry : contentEntry : relEntry :+                  footnoteRelEntry : numEntry : styleEntry : footnotesEntry :+                  commentsEntry :+                  docPropsEntry : customPropsEntry :+                  settingsEntry :+                  imageEntries ++ refEntries+  return $ fromArchive archive++newParaPropToOpenXml :: ParaStyleName -> Element+newParaPropToOpenXml (fromStyleName -> s) =+  let styleId = T.filter (not . isSpace) s+  in mknode "w:style" [ ("w:type", "paragraph")+                      , ("w:customStyle", "1")+                      , ("w:styleId", styleId)]+     [ mknode "w:name" [("w:val", s)] ()+     , mknode "w:basedOn" [("w:val","BodyText")] ()+     , mknode "w:qFormat" [] ()+     ]++newTextPropToOpenXml :: CharStyleName -> Element+newTextPropToOpenXml (fromStyleName -> s) =+  let styleId = T.filter (not . isSpace) s+  in mknode "w:style" [ ("w:type", "character")+                      , ("w:customStyle", "1")+                      , ("w:styleId", styleId)]+     [ mknode "w:name" [("w:val", s)] ()+     , mknode "w:basedOn" [("w:val","BodyTextChar")] ()+     ]++styleToOpenXml :: StyleMaps -> Style -> [Element]+styleToOpenXml sm style =+  maybeToList parStyle ++ mapMaybe toStyle alltoktypes+  where alltoktypes = enumFromTo KeywordTok NormalTok+        toStyle toktype | hasStyleName (fromString $ show toktype) (smCharStyle sm) = Nothing+                        | otherwise = Just $+                          mknode "w:style" [("w:type","character"),+                           ("w:customStyle","1"),("w:styleId", tshow toktype)]+                             [ mknode "w:name" [("w:val", tshow toktype)] ()+                             , mknode "w:basedOn" [("w:val","VerbatimChar")] ()+                             , mknode "w:rPr" [] $+                               [ mknode "w:b" [] () | tokFeature tokenBold toktype ] +++                               [ mknode "w:i" [] () | tokFeature tokenItalic toktype ] +++                               [ mknode "w:color" [("w:val", tokCol toktype)] ()+                                 | tokCol toktype /= "auto" ] +++                               [ mknode "w:u" [] () | tokFeature tokenUnderline toktype ] +++                               [ mknode "w:shd" [("w:val","clear")+                                                ,("w:fill",tokBg toktype)] ()+                                 | tokBg toktype /= "auto" ]+                             ]+        tokStyles = tokenStyles style+        tokFeature f toktype = maybe False f $ M.lookup toktype tokStyles+        tokCol toktype = maybe "auto" (T.pack . drop 1 . fromColor)+                         $ (tokenColor =<< M.lookup toktype tokStyles)+                           `mplus` defaultColor style+        tokBg toktype = maybe "auto" (T.pack . drop 1 . fromColor)+                         $ (tokenBackground =<< M.lookup toktype tokStyles)+                           `mplus` backgroundColor style+        parStyle | hasStyleName "Source Code" (smParaStyle sm) = Nothing+                 | otherwise = Just $+                   mknode "w:style" [("w:type","paragraph"),+                           ("w:customStyle","1"),("w:styleId","SourceCode")]+                             [ mknode "w:name" [("w:val","Source Code")] ()+                             , mknode "w:basedOn" [("w:val","Normal")] ()+                             , mknode "w:link" [("w:val","VerbatimChar")] ()+                             , mknode "w:pPr" []+                               $ mknode "w:wordWrap" [("w:val","off")] ()+                               :+                         maybe [] (\col -> [mknode "w:shd" [("w:val","clear"),("w:fill", T.pack $ drop 1 $ fromColor col)] ()]) (backgroundColor style)+                             ]++copyChildren :: (PandocMonad m)+             => Archive -> Archive -> String -> Integer -> [Text] -> m Entry+copyChildren refArchive distArchive path timestamp elNames = do+  ref  <- parseXml refArchive distArchive path+  dist <- parseXml distArchive distArchive path+  els <- foldM (addEl ref dist) [] (reverse elNames)+  return $ toEntry path timestamp+         $ renderXml dist{ elContent = map cleanElem els }+  where+    addEl ref dist els name =+      case filterChildName (hasName name) ref `mplus`+             filterChildName (hasName name) dist of+        Just el -> pure (el : els)+        Nothing -> pure els+    hasName name = (== name) . qName+    cleanElem el@Element{elName=name} = Elem el{elName=name{qURI=Nothing}}++-- this is the lowest number used for a list numId+baseListId :: Int+baseListId = 1000++-- | Standard XML namespace attributes for docx elements+stdAttributes :: [(Text, Text)]+stdAttributes =+  [("xmlns:w","http://schemas.openxmlformats.org/wordprocessingml/2006/main")+  ,("xmlns:m","http://schemas.openxmlformats.org/officeDocument/2006/math")+  ,("xmlns:r","http://schemas.openxmlformats.org/officeDocument/2006/relationships")+  ,("xmlns:o","urn:schemas-microsoft-com:office:office")+  ,("xmlns:v","urn:schemas-microsoft-com:vml")+  ,("xmlns:w10","urn:schemas-microsoft-com:office:word")+  ,("xmlns:a","http://schemas.openxmlformats.org/drawingml/2006/main")+  ,("xmlns:pic","http://schemas.openxmlformats.org/drawingml/2006/picture")+  ,("xmlns:wp","http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing")]++-- | Settings elements to copy from reference.docx (order matters)+settingsElementNames :: [Text]+settingsElementNames =+  [ "writeProtection"+  , "view"+  , "zoom"+  , "removePersonalInformation"+  , "removeDateAndTime"+  , "doNotDisplayPageBoundaries"+  , "displayBackgroundShape"+  , "printPostScriptOverText"+  , "printFractionalCharacterWidth"+  , "printFormsData"+  , "embedTrueTypeFonts"+  , "embedSystemFonts"+  , "saveSubsetFonts"+  , "saveFormsData"+  , "mirrorMargins"+  , "alignBordersAndEdges"+  , "bordersDoNotSurroundHeader"+  , "bordersDoNotSurroundFooter"+  , "gutterAtTop"+  , "hideSpellingErrors"+  , "hideGrammaticalErrors"+  , "activeWritingStyle"+  , "proofState"+  , "formsDesign"+  , "attachedTemplate"+  , "linkStyles"+  , "stylePaneFormatFilter"+  , "stylePaneSortMethod"+  , "documentType"+  , "mailMerge"+  , "revisionView"+  , "trackRevisions"+  , "doNotTrackMoves"+  , "doNotTrackFormatting"+  , "documentProtection"+  , "autoFormatOverride"+  , "styleLockTheme"+  , "styleLockQFSet"+  , "defaultTabStop"+  , "autoHyphenation"+  , "consecutiveHyphenLimit"+  , "hyphenationZone"+  , "doNotHyphenateCaps"+  , "showEnvelope"+  , "summaryLength"+  , "clickAndTypeStyle"+  , "defaultTableStyle"+  , "evenAndOddHeaders"+  , "bookFoldRevPrinting"+  , "bookFoldPrinting"+  , "bookFoldPrintingSheets"+  , "drawingGridHorizontalSpacing"+  , "drawingGridVerticalSpacing"+  , "displayHorizontalDrawingGridEvery"+  , "displayVerticalDrawingGridEvery"+  , "doNotUseMarginsForDrawingGridOrigin"+  , "drawingGridHorizontalOrigin"+  , "drawingGridVerticalOrigin"+  , "doNotShadeFormData"+  , "noPunctuationKerning"+  , "characterSpacingControl"+  , "printTwoOnOne"+  , "strictFirstAndLastChars"+  , "noLineBreaksAfter"+  , "noLineBreaksBefore"+  , "savePreviewPicture"+  , "doNotValidateAgainstSchema"+  , "saveInvalidXml"+  , "ignoreMixedContent"+  , "alwaysShowPlaceholderText"+  , "doNotDemarcateInvalidXml"+  , "saveXmlDataOnly"+  , "useXSLTWhenSaving"+  , "saveThroughXslt"+  , "showXMLTags"+  , "alwaysMergeEmptyNamespace"+  , "updateFields"+  , "hdrShapeDefaults"+  -- , "footnotePr" -- this can cause problems, see #9522+  -- , "endnotePr"+  , "compat"+  , "docVars"+  , "rsids"+  , "attachedSchema"+  , "themeFontLang"+  , "clrSchemeMapping"+  , "doNotIncludeSubdocsInStats"+  , "doNotAutoCompressPictures"+  , "forceUpgrade"+  , "captions"+  , "readModeInkLockDown"+  , "smartTagType"+  , "shapeDefaults"+  , "doNotEmbedSmartTags"+  , "decimalSymbol"+  , "listSeparator" ]++mkNumbering :: [ListMarker] -> [Element]+mkNumbering lists =+  elts ++ zipWith mkNum lists [baseListId..(baseListId + length lists - 1)]+    where elts = map mkAbstractNum (nubOrd lists)++mkNum :: ListMarker -> Int -> Element+mkNum marker numid =+  mknode "w:num" [("w:numId",tshow numid)]+   $ mknode "w:abstractNumId" [("w:val",listMarkerToId marker)] ()+   : case marker of+       NoMarker     -> []+       BulletMarker -> []+       CheckboxMarker _ -> []+       NumberMarker _ _ start ->+          map (\lvl -> mknode "w:lvlOverride" [("w:ilvl",tshow (lvl :: Int))]+              $ mknode "w:startOverride" [("w:val",tshow start)] ())+                [0..maxListLevel]++mkAbstractNum :: ListMarker -> Element+mkAbstractNum marker =+  mknode "w:abstractNum" [("w:abstractNumId",listMarkerToId marker)]+    $ mknode "w:nsid" [("w:val", T.justifyRight 8 '0' ("A" <> listMarkerToId marker))] ()+    : mknode "w:multiLevelType" [("w:val","multilevel")] ()+    : map (mkLvl marker)+      [0..maxListLevel]++mkLvl :: ListMarker -> Int -> Element+mkLvl marker lvl =+  mknode "w:lvl" [("w:ilvl",tshow lvl)] $+    (case marker of+        NumberMarker{} -> [mknode "w:start" [("w:val",start)] ()]+        _ -> []) +++    [ mknode "w:numFmt" [("w:val",fmt)] ()+    , mknode "w:lvlText" [("w:val", lvltxt)] ()+    , mknode "w:lvlJc" [("w:val","left")] ()+    , mknode "w:pPr" [] $+        mknode "w:ind" [ ("w:left",tshow $ lvl * step + step)+                       , ("w:hanging",tshow hang)+                       ] ()+    ] +++    maybe [] (\font ->+                [ mknode "w:rPr" []+                  [ mknode "w:rFonts" [ ("w:ascii", font)+                                      , ("w:hAnsi", font)+                                      , ("w:cs", font)+                                      , ("w:hint", "default") ] () ]]) mbfont+    where (fmt, lvltxt, mbfont, start) =+            case marker of+                 NoMarker             -> ("bullet"," ", Nothing, "1")+                 BulletMarker         -> bulletFor lvl+                 CheckboxMarker False -> ("bullet","\9744", Nothing, "1")+                 CheckboxMarker True  -> ("bullet","\9746", Nothing, "1")+                 NumberMarker st de n -> (styleFor st lvl+                                         ,patternFor de ("%" <> tshow (lvl + 1))+                                         ,Nothing+                                         ,tshow n)+          step = 720+          hang :: Int+          hang = 360+          bulletFor 0 = ("bullet", "\xf0b7", Just "Symbol", "1") -- filled circle+          bulletFor 1 = ("bullet", "o", Just "Courier New", "1") -- open o+          bulletFor 2 = ("bullet", "\xf0a7", Just "Wingdings", "1")  -- closed box+          bulletFor x = bulletFor (x `mod` 3)+          styleFor UpperAlpha _   = "upperLetter"+          styleFor LowerAlpha _   = "lowerLetter"+          styleFor UpperRoman _   = "upperRoman"+          styleFor LowerRoman _   = "lowerRoman"+          styleFor Decimal _      = "decimal"+          styleFor DefaultStyle 0 = "decimal"+          styleFor DefaultStyle 1 = "lowerLetter"+          styleFor DefaultStyle 2 = "lowerRoman"+          styleFor DefaultStyle 3 = "decimal"+          styleFor DefaultStyle 4 = "lowerLetter"+          styleFor DefaultStyle 5 = "lowerRoman"+          styleFor DefaultStyle x = styleFor DefaultStyle (x `mod` 6)+          styleFor _ _            = "decimal"+          patternFor OneParen s  = s <> ")"+          patternFor TwoParens s = "(" <> s <> ")"+          patternFor _ s         = s <> "."++-- | Build language transformer function for modifying XML elements.+-- Navigates directly to w:docDefaults/w:rPr/w:lang instead of generic traversal.+mkLangTransformer :: Maybe Lang -> (Element -> Element)+mkLangTransformer Nothing  = id+mkLangTransformer (Just lang) = modifyAtPath path updateLangAttrs+  where+    -- Path is: w:docDefaults / w:rPrDefault / w:rPr / w:lang+    path = [named "docDefaults", named "rPrDefault", named "rPr", named "lang"]+    named n = (== n) . qName++    updateLangAttrs e+      | isEastAsianLang lang = e{ elAttribs = map (setattr "eastAsia") $ elAttribs e }+      | isBidiLang lang      = e{ elAttribs = map (setattr "bidi") $ elAttribs e }+      | otherwise            = e{ elAttribs = map (setattr "val") $ elAttribs e }++    setattr attrname (XML.Attr qn@(QName s _ _) _)+      | s == attrname  = XML.Attr qn (renderLang lang)+    setattr _ x        = x++    isEastAsianLang Lang{ langLanguage = l } = l == "zh" || l == "ja" || l == "ko"+    isBidiLang Lang{ langLanguage = l } = l == "he" || l == "ar"++-- | Modify an element at a specific path in the XML tree.+-- The path is a list of predicates that match element names at each level.+modifyAtPath :: [(QName -> Bool)] -> (Element -> Element) -> Element -> Element+modifyAtPath [] f e = f e+modifyAtPath (p:ps) f e = e{ elContent = map go (elContent e) }+  where+    go (Elem el) | p (elName el) = Elem (modifyAtPath ps f el)+    go c = c++-- | Load reference and distribution archives+loadArchives :: PandocMonad m+             => WriterOptions+             -> m (Archive, Archive, Maybe Text, UTCTime)+loadArchives opts = do+  username <- P.lookupEnv "USERNAME"+  utctime <- P.getTimestamp+  oldUserDataDir <- P.getUserDataDir+  P.setUserDataDir Nothing+  res <- readDefaultDataFile "reference.docx"+  P.setUserDataDir oldUserDataDir+  let distArchive = toArchive $ BL.fromStrict res+  refArchive <- case writerReferenceDoc opts of+                   Just f  -> toArchive . BL.fromStrict . fst+                                 <$> P.fetchItem (T.pack f)+                   Nothing -> toArchive . BL.fromStrict <$>+                        readDataFile "reference.docx"+  return (refArchive, distArchive, username, utctime)++-- | Extract page dimensions from template+extractPageLayout :: PandocMonad m+                  => Archive -> Archive -> m (Maybe Element, Maybe Integer)+extractPageLayout refArchive distArchive = do+  parsedDoc <- parseXml refArchive distArchive "word/document.xml"+  let wname f qn = qPrefix qn == Just "w" && f (qName qn)+  let mbsectpr = filterElementName (wname (=="sectPr")) parsedDoc++  -- Gets the template size+  let mbpgsz = mbsectpr >>= filterElementName (wname (=="pgSz"))+  let mbAttrSzWidth = mbpgsz >>= lookupAttrBy ((=="w") . qName) . elAttribs++  let mbpgmar = mbsectpr >>= filterElementName (wname (=="pgMar"))+  let mbAttrMarLeft = mbpgmar >>= lookupAttrBy ((=="left") . qName) . elAttribs+  let mbAttrMarRight = mbpgmar >>= lookupAttrBy ((=="right") . qName) . elAttribs++  -- Get the available area (converting the size and the margins to int and+  -- doing the difference+  let pgContentWidth = do+                         w <- mbAttrSzWidth >>= safeRead+                         r <- mbAttrMarRight >>= safeRead+                         l <- mbAttrMarLeft >>= safeRead+                         pure $ w - r - l++  return (mbsectpr, pgContentWidth)++-- | Parse and augment relationships from reference.docx+extractRelationships :: PandocMonad m+                     => Archive -> Archive+                     -> m ([Element], [Element], [Element], Int)+extractRelationships refArchive distArchive = do+  let isImageNode e = findAttr (QName "Type" Nothing Nothing) e == Just "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"+  let isHeaderNode e = findAttr (QName "Type" Nothing Nothing) e == Just "http://schemas.openxmlformats.org/officeDocument/2006/relationships/header"+  let isFooterNode e = findAttr (QName "Type" Nothing Nothing) e == Just "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer"+  parsedRels <- filterElements+                  (\e -> isImageNode e || isHeaderNode e || isFooterNode e)+              <$> parseXml refArchive distArchive "word/_rels/document.xml.rels"+  let getRelId e =+        case findAttr (QName "Id" Nothing Nothing) e of+          Just ident -> T.stripPrefix "rId" ident >>= safeRead+          Nothing -> Nothing+  let relIds = mapMaybe getRelId parsedRels+  let maxRelId = if null relIds then 0 else maximum relIds++  let headers = filter isHeaderNode parsedRels+  let footers = filter isFooterNode parsedRels+  -- word/_rels/document.xml.rels+  let addBaseRel (url', target') (maxId, rels) =+        case [e | e <- rels+                , findAttr (QName "Target" Nothing Nothing) e ==+                   Just target'] of+          [] -> (maxId + 1, mknode "Relationship"+                            [("Type",url')+                            ,("Id","rId" <> tshow (maxId + 1))+                            ,("Target",target')] () : rels)+          _ -> (maxId, rels)++  let (newMaxRelId, baserels) = foldr addBaseRel (maxRelId, parsedRels)+                    [("http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering",+                      "numbering.xml")+                    ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles",+                      "styles.xml")+                    ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings",+                      "settings.xml")+                    ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings",+                      "webSettings.xml")+                    ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable",+                      "fontTable.xml")+                    ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme",+                      "theme/theme1.xml")+                    ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes",+                      "footnotes.xml")+                    ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments",+                      "comments.xml")+                    ]++  return (baserels, headers, footers, newMaxRelId)++-- | Create footnotes XML entry+mkFootnotesEntry :: Integer -> [Element] -> Entry+mkFootnotesEntry epochtime footnotes =+  let notes = mknode "w:footnotes" stdAttributes footnotes+  in toEntry "word/footnotes.xml" epochtime $ renderXml notes++-- | Create footnote relationships entry+mkFootnoteRelsEntry :: Integer -> M.Map Text Text -> Entry+mkFootnoteRelsEntry epochtime externalLinks =+  let linkrels = map toLinkRel $ M.toList externalLinks+      toLinkRel (src, ident) = mknode "Relationship"+        [("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink")+        ,("Id",ident)+        ,("Target",src)+        ,("TargetMode","External")] ()+  in toEntry "word/_rels/footnotes.xml.rels" epochtime+       $ renderXml $ mknode "Relationships"+           [("xmlns","http://schemas.openxmlformats.org/package/2006/relationships")]+           linkrels++-- | Create comments XML entry+mkCommentsEntry :: Integer -> [Element] -> Entry+mkCommentsEntry epochtime comments =+  toEntry "word/comments.xml" epochtime+    $ renderXml $ mknode "w:comments" stdAttributes comments++-- | Create package-level relationships entry+mkPackageRelsEntry :: Integer -> Entry+mkPackageRelsEntry epochtime =+  let rels = mknode "Relationships"+        [("xmlns", "http://schemas.openxmlformats.org/package/2006/relationships")]+        $ map (\attrs -> mknode "Relationship" attrs ())+        [ [("Id","rId1")+          ,("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument")+          ,("Target","word/document.xml")]+        , [("Id","rId4")+          ,("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties")+          ,("Target","docProps/app.xml")]+        , [("Id","rId3")+          ,("Type","http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties")+          ,("Target","docProps/core.xml")]+        , [("Id","rId5")+          ,("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties")+          ,("Target","docProps/custom.xml")]+        ]+  in toEntry "_rels/.rels" epochtime $ renderXml rels++-- | Create content types manifest entry+mkContentTypesEntry :: Integer+                    -> [(String, String, Maybe MimeType, B.ByteString)]  -- imgs+                    -> [Element]  -- headers+                    -> [Element]  -- footers+                    -> Archive    -- refArchive+                    -> Entry+mkContentTypesEntry epochtime imgs headers footers refArchive =+  let mkOverrideNode (part', contentType') = mknode "Override"+           [("PartName", T.pack part')+           ,("ContentType", contentType')] ()+      mkImageOverride (_, imgpath, mbMimeType, _) =+          mkOverrideNode ("/word/" <> imgpath,+                          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")+                  ,("/word/numbering.xml",+                    "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml")+                  ,("/word/settings.xml",+                    "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml")+                  ,("/word/theme/theme1.xml",+                    "application/vnd.openxmlformats-officedocument.theme+xml")+                  ,("/word/fontTable.xml",+                    "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml")+                  ,("/docProps/app.xml",+                    "application/vnd.openxmlformats-officedocument.extended-properties+xml")+                  ,("/docProps/core.xml",+                    "application/vnd.openxmlformats-package.core-properties+xml")+                  ,("/docProps/custom.xml",+                    "application/vnd.openxmlformats-officedocument.custom-properties+xml")+                  ,("/word/styles.xml",+                    "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml")+                  ,("/word/document.xml",+                    "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml")+                  ,("/word/comments.xml",+                    "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml")+                  ,("/word/footnotes.xml",+                    "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml")+                  ] +++                  map (\x -> (maybe "" (unrelativize . T.unpack) (extractTarget x),+                       "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml")) headers +++                  map (\x -> (maybe "" (unrelativize . T.unpack) (extractTarget x),+                       "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml")) footers) +++                    map mkImageOverride imgs +++                    [ mkMediaOverride (eRelativePath e)+                        | e <- zEntries refArchive+                        , "word/media/" `isPrefixOf` eRelativePath e+                        , not ("/" `isSuffixOf` eRelativePath e) ]+      mkDefaultNode (ext, mt) =+        mknode "Default" [("Extension",ext),("ContentType",mt)] ()+      defaultnodes = map mkDefaultNode+        [("xml", "application/xml"),+         ("rels", "application/vnd.openxmlformats-package.relationships+xml"),+         ("odttf",+           "application/vnd.openxmlformats-officedocument.obfuscatedFont")]+      contentTypesDoc = mknode "Types"+        [("xmlns","http://schemas.openxmlformats.org/package/2006/content-types")]+        $ defaultnodes ++ overrides+  in toEntry "[Content_Types].xml" epochtime $ renderXml contentTypesDoc++-- | Create document relationships entry+mkDocumentRelsEntry :: Integer+                    -> [Element]  -- baserels+                    -> [(String, String, Maybe MimeType, B.ByteString)]  -- imgs+                    -> M.Map Text Text  -- externalLinks+                    -> Entry+mkDocumentRelsEntry epochtime baserels imgs externalLinks =+  let toImgRel (ident, path, _, _) = mknode "Relationship"+        [("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/image")+        ,("Id",T.pack ident)+        ,("Target",T.pack path)] ()+      imgrels = map toImgRel imgs+      toLinkRel (src, ident) = mknode "Relationship"+        [("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink")+        ,("Id",ident)+        ,("Target",src)+        ,("TargetMode","External")] ()+      linkrels = map toLinkRel $ M.toList externalLinks+      reldoc = mknode "Relationships"+        [("xmlns","http://schemas.openxmlformats.org/package/2006/relationships")]+        $ baserels ++ imgrels ++ linkrels+  in toEntry "word/_rels/document.xml.rels" epochtime $ renderXml reldoc++-- | Create styles entry with dynamic additions+mkStylesEntry :: Integer -> Element -> StyleMaps -> WriterState -> WriterOptions -> Entry+mkStylesEntry epochtime styledoc styleMaps st opts =+  let stylepath = "word/styles.xml"+      -- We only want to inject paragraph and text properties that+      -- are not already in the style map. Note that keys in the stylemap+      -- are normalized as lowercase.+      newDynamicParaProps = filter+        (\sty -> not $ hasStyleName sty $ smParaStyle styleMaps)+        (Set.toList $ stDynamicParaProps st)++      newDynamicTextProps = filter+        (\sty -> not $ hasStyleName sty $ smCharStyle styleMaps)+        (Set.toList $ stDynamicTextProps st)++      newstyles = map newParaPropToOpenXml newDynamicParaProps +++                  map newTextPropToOpenXml newDynamicTextProps +++                  (case writerHighlightMethod opts of+                     Skylighting sty -> styleToOpenXml styleMaps sty+                     DefaultHighlighting -> styleToOpenXml styleMaps+                                              defaultStyle+                     _ -> [])+      styledoc' = styledoc{ elContent = elContent styledoc +++                                           map Elem newstyles }+  in toEntry stylepath epochtime $ renderXml styledoc'++-- | Create core document properties entry+mkCorePropsEntry :: Integer -> UTCTime -> Meta -> Entry+mkCorePropsEntry epochtime utctime meta =+  let metaValueToText (MetaString s)    = s+      metaValueToText (MetaInlines ils) = stringify ils+      metaValueToText (MetaBlocks bs)   = stringify bs+      metaValueToText (MetaBool b)      = T.pack (show b)+      metaValueToText _                 = ""+      keywords = case lookupMeta "keywords" meta of+                       Just (MetaList xs) -> map metaValueToText xs+                       _                  -> []+      docPropsPath = "docProps/core.xml"+      extraCoreProps = ["subject","lang","category","description"]+      extraCorePropsMap = M.fromList $ zip extraCoreProps+                       ["dc:subject","dc:language","cp:category","dc:description"]+      lookupMetaString' :: Text -> Meta -> Text+      lookupMetaString' key' meta' =+        case key' of+             "description" -> T.intercalate "_x000d_\n"+                                (map stringify $ lookupMetaBlocks "description" meta')+             key''         -> lookupMetaString key'' meta'++      docProps = mknode "cp:coreProperties"+          [("xmlns:cp","http://schemas.openxmlformats.org/package/2006/metadata/core-properties")+          ,("xmlns:dc","http://purl.org/dc/elements/1.1/")+          ,("xmlns:dcterms","http://purl.org/dc/terms/")+          ,("xmlns:dcmitype","http://purl.org/dc/dcmitype/")+          ,("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance")]+          $ mktnode "dc:title" [] (stringify $ docTitle meta)+          : mktnode "dc:creator" [] (T.intercalate "; " (map stringify $ docAuthors meta))+          : [ mktnode (M.findWithDefault "" k extraCorePropsMap) [] (lookupMetaString' k meta)+            | k <- M.keys (unMeta meta), k `elem` extraCoreProps]+          ++ mknode "cp:keywords" [] (T.intercalate ", " keywords)+          : (\x -> [ mknode "dcterms:created" [("xsi:type","dcterms:W3CDTF")] x+                   , mknode "dcterms:modified" [("xsi:type","dcterms:W3CDTF")] x+                   ]) (T.pack $ formatTime defaultTimeLocale "%FT%XZ" utctime)+  in toEntry docPropsPath epochtime $ renderXml docProps++-- | Create custom document properties entry+mkCustomPropsEntry :: Integer -> Meta -> Entry+mkCustomPropsEntry epochtime meta =+  let extraCoreProps = ["subject","lang","category","description"]+      customProperties :: [(Text, Text)]+      customProperties = [ (k, lookupMetaString k meta)+                         | k <- M.keys (unMeta meta)+                         , k `notElem` (["title", "author", "keywords"]+                                       ++ extraCoreProps)]+      mkCustomProp (k, v) pid = mknode "property"+         [("fmtid","{D5CDD505-2E9C-101B-9397-08002B2CF9AE}")+         ,("pid", tshow pid)+         ,("name", k)] $ mknode "vt:lpwstr" [] v+      customPropsPath = "docProps/custom.xml"+      customProps = mknode "Properties"+          [("xmlns","http://schemas.openxmlformats.org/officeDocument/2006/custom-properties")+          ,("xmlns:vt","http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes")+          ] $ zipWith mkCustomProp customProperties [(2 :: Int)..]+  in toEntry customPropsPath epochtime $ renderXml customProps++-- | Create numbering entry+mkNumberingEntry :: PandocMonad m+                 => Archive -> Archive -> Integer -> [ListMarker] -> m Entry+mkNumberingEntry refArchive distArchive epochtime lists = do+  let numpath = "word/numbering.xml"+  numbering <- parseXml refArchive distArchive numpath+  let newNumElts = mkNumbering lists+  let pandocAdded e =+       case findAttrBy ((== "abstractNumId") . qName) e >>= safeRead of+         Just numid -> numid >= (990 :: Int)+         Nothing    ->+           case findAttrBy ((== "numId") . qName) e >>= safeRead of+             Just numid -> numid >= (1000 :: Int)+             Nothing    -> False+  let oldElts = filter (not . pandocAdded) $ onlyElems (elContent numbering)+  let allElts = oldElts ++ newNumElts+  return $ toEntry numpath epochtime $ renderXml numbering{ elContent =+                       -- we want all the abstractNums first, then the nums,+                       -- otherwise things break:+                       [Elem e | e <- allElts+                               , qName (elName e) == "abstractNum" ] +++                       [Elem e | e <- allElts+                               , qName (elName e) == "num" ] }++-- | Collect auxiliary entries from reference archive+collectReferenceEntries :: PandocMonad m+                        => Archive -> Archive -> [Element] -> [Element]+                        -> m [Entry]+collectReferenceEntries refArchive distArchive headers footers = do+  let entryFromArchive arch path =+         maybe (throwError $ PandocSomeError+                           $ T.pack $ path ++ " missing in reference docx")+               return+               (findEntryByPath path arch `mplus` findEntryByPath path distArchive)+  docPropsAppEntry <- entryFromArchive refArchive "docProps/app.xml"+  themeEntry <- entryFromArchive refArchive "word/theme/theme1.xml"+  fontTableEntry <- entryFromArchive refArchive "word/fontTable.xml"+  let fontTableRelsEntries = maybeToList $+       findEntryByPath "word/_rels/fontTable.xml.rels" refArchive+  let fontEntries = [entry | entry <- zEntries refArchive+                           , "word/fonts/" `isPrefixOf` (eRelativePath entry)]+  webSettingsEntry <- entryFromArchive refArchive "word/webSettings.xml"+  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+                       , "word/_rels/" `isPrefixOf` eRelativePath e+                       , ".xml.rels" `isSuffixOf` eRelativePath e+                       , eRelativePath e /= "word/_rels/document.xml.rels"+                       , eRelativePath e /= "word/_rels/footnotes.xml.rels" ]+  let otherMediaEntries = [ e | e <- zEntries refArchive+                          , "word/media/" `isPrefixOf` eRelativePath e ]+  return $ docPropsAppEntry : themeEntry : fontTableEntry : webSettingsEntry+         : fontTableRelsEntries ++ fontEntries ++ headerFooterEntries+         ++ miscRelEntries ++ otherMediaEntries++extractTarget :: Element -> Maybe Text+extractTarget = findAttr (QName "Target" Nothing Nothing)
+ src/Text/Pandoc/Writers/Docx/OpenXML.hs view
@@ -0,0 +1,1146 @@+{-# LANGUAGE PatternGuards       #-}+{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TupleSections       #-}+{-# LANGUAGE ViewPatterns        #-}+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE LambdaCase          #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE TypeApplications    #-}+{- |+   Module      : Text.Pandoc.Writers.Docx+   Copyright   : Copyright (C) 2012-2025 John MacFarlane+   License     : GNU GPL, version 2 or above++   Maintainer  : John MacFarlane <jgm@berkeley.edu>+   Stability   : alpha+   Portability : portable++Conversion of 'Pandoc' documents to docx.+-}+module Text.Pandoc.Writers.Docx.OpenXML ( writeOpenXML, maxListLevel ) where++import Control.Monad (when, unless)+import Control.Applicative ((<|>))+import Control.Monad.Except (catchError)+import Crypto.Hash (hashWith, SHA1(SHA1))+import qualified Data.ByteString.Lazy as BL+import Data.Char (isLetter, isSpace)+import Text.Pandoc.Char (isCJK)+import Data.Ord (comparing)+import Data.String (fromString)+import qualified Data.Map as M+import Data.Maybe (fromMaybe, maybeToList, isJust)+import Control.Monad.State ( gets, modify, MonadTrans(lift) )+import Control.Monad.Reader ( asks, MonadReader(local) )+import qualified Data.Set as Set+import qualified Data.Text as T+import Data.Text (Text)+import Skylighting+import Text.DocLayout (hcat, vcat, literal, render)+import Text.Pandoc.Class (PandocMonad, report, getMediaBag)+import Text.Pandoc.Translations (Term(Abstract), translateTerm)+import Text.Pandoc.MediaBag (lookupMedia, MediaItem(..))+import qualified Text.Pandoc.Translations as Term+import qualified Text.Pandoc.Class.PandocMonad as P+import qualified Text.Pandoc.Builder as B+import Text.Pandoc.UTF8 (fromText)+import Text.Pandoc.Definition+import Text.Pandoc.Highlighting (highlight)+import Text.Pandoc.Templates (compileDefaultTemplate, renderTemplate)+import Text.Pandoc.ImageSize+import Text.Pandoc.Logging+import Text.Pandoc.MIME (extensionFromMimeType, getMimeType)+import Text.Pandoc.Options+import Text.Pandoc.Writers.Docx.StyleMap+import Text.Pandoc.Writers.Docx.Table as Table+import Text.Pandoc.Writers.Docx.Types+import Text.Pandoc.Shared+import Text.Pandoc.Walk+import qualified Text.Pandoc.Writers.GridTable as Grid+import Text.Pandoc.Writers.Math+import Text.Pandoc.Writers.Shared+import Text.TeXMath+import Text.Pandoc.Writers.OOXML+import Text.Pandoc.XML.Light as XML+import Data.List (sortBy, intercalate, groupBy)++-- from wml.xsd EG_RPrBase+rPrTagOrder :: M.Map Text Int+rPrTagOrder =+  M.fromList+  (zip [ "rStyle"+    , "rFonts"+    , "b"+    , "bCs"+    , "i"+    , "iCs"+    , "caps"+    , "smallCaps"+    , "strike"+    , "dstrike"+    , "outline"+    , "shadow"+    , "emboss"+    , "imprint"+    , "noProof"+    , "snapToGrid"+    , "vanish"+    , "webHidden"+    , "color"+    , "spacing"+    , "w"+    , "kern"+    , "position"+    , "sz"+    , "szCs"+    , "highlight"+    , "u"+    , "effect"+    , "bdr"+    , "shd"+    , "fitText"+    , "vertAlign"+    , "rtl"+    , "cs"+    , "em"+    , "lang"+    , "eastAsianLayout"+    , "specVanish"+    , "oMath"+    ] [0..])++sortSquashed :: [Element] -> [Element]+sortSquashed l =+  sortBy (comparing tagIndex) l+  where+    tagIndex :: Element -> Int+    tagIndex el =+      fromMaybe 0 (M.lookup tag rPrTagOrder)+      where tag = (qName . elName) el++squashProps :: EnvProps -> [Element]+squashProps (EnvProps Nothing es) = sortSquashed es+squashProps (EnvProps (Just e) es) = sortSquashed (e : es)++-- | Certain characters are invalid in XML even if escaped.+-- See #1992+stripInvalidChars :: Text -> Text+stripInvalidChars = T.filter isValidChar++-- | See XML reference+isValidChar :: Char -> Bool+isValidChar '\t' = True+isValidChar '\n' = True+isValidChar '\r' = True+isValidChar '\xFFFE' = False+isValidChar '\xFFFF' = False+isValidChar c = (' ' <= c && c <= '\xD7FF') || ('\xE000' <= c)++-- this is the lowest number used for a list numId+baseListId :: Int+baseListId = 1000++getNumId :: (PandocMonad m) => WS m Int+getNumId = gets (((baseListId - 1) +) . length . stLists)++makeTOC :: (PandocMonad m) => WriterOptions -> WS m [Element]+makeTOC opts = do+  let depth = "1-" <> tshow (writerTOCDepth opts)+  let tocCmd = "TOC \\o \"" <> depth <> "\" \\h \\z \\u"+  tocTitle <- gets stTocTitle+  title <- withParaPropM (pStyleM "TOC Heading") (blocksToOpenXML opts [Para tocTitle])+  return+    [mknode "w:sdt" [] [+      mknode "w:sdtPr" [] (+        mknode "w:docPartObj" []+          [mknode "w:docPartGallery" [("w:val","Table of Contents")] (),+          mknode "w:docPartUnique" [] ()]+         -- w:docPartObj+      ), -- w:sdtPr+      mknode "w:sdtContent" [] (title ++ [ Elem $+        mknode "w:p" [] (+          mknode "w:r" [] [+            mknode "w:fldChar" [("w:fldCharType","begin"),("w:dirty","true")] (),+            mknode "w:instrText" [("xml:space","preserve")] tocCmd,+            mknode "w:fldChar" [("w:fldCharType","separate")] (),+            mknode "w:fldChar" [("w:fldCharType","end")] ()+          ] -- w:r+        ) -- w:p+      ])+    ]] -- w:sdt++makeLOF :: (PandocMonad m) => WriterOptions -> WS m [Element]+makeLOF opts = do+  let lofCmd = "TOC \\h \\z \\t \"Image Caption\" \\c" :: Text+  lofTitle <- B.toList <$> B.text <$> translateTerm Term.ListOfFigures+  title <- withParaPropM (pStyleM "TOC Heading") (blocksToOpenXML opts [Para lofTitle])+  return+    [mknode "w:sdt" [] [+      mknode "w:sdtPr" [] (+        mknode "w:docPartObj" []+          [mknode "w:docPartGallery" [("w:val","List of Figures")] (),+          mknode "w:docPartUnique" [] ()]+         -- w:docPartObj+      ), -- w:sdtPr+      mknode "w:sdtContent" [] (title ++ [ Elem $+        mknode "w:p" [] (+          mknode "w:r" [] [+            mknode "w:fldChar" [("w:fldCharType","begin"),("w:dirty","true")] (),+            mknode "w:instrText" [("xml:space","preserve")] lofCmd,+            mknode "w:fldChar" [("w:fldCharType","separate")] (),+            mknode "w:fldChar" [("w:fldCharType","end")] ()+          ] -- w:r+        ) -- w:p+      ]) -- w:sdtContent+    ]] -- w:sdt++makeLOT :: (PandocMonad m) => WriterOptions -> WS m [Element]+makeLOT opts = do+  let lotCmd = "TOC \\h \\z \\t \"Table Caption\" \\c" :: Text+  lotTitle <- B.toList <$> B.text <$> translateTerm Term.ListOfTables+  title <- withParaPropM (pStyleM "TOC Heading") (blocksToOpenXML opts [Para lotTitle])+  return+    [mknode "w:sdt" [] [+      mknode "w:sdtPr" [] (+        mknode "w:docPartObj" []+          [mknode "w:docPartGallery" [("w:val","List of Tables")] (),+          mknode "w:docPartUnique" [] ()]+         -- w:docPartObj+      ), -- w:sdtPr+      mknode "w:sdtContent" [] (title ++ [ Elem $+        mknode "w:p" [] (+          mknode "w:r" [] [+            mknode "w:fldChar" [("w:fldCharType","begin"),("w:dirty","true")] (),+            mknode "w:instrText" [("xml:space","preserve")] lotCmd,+            mknode "w:fldChar" [("w:fldCharType","separate")] (),+            mknode "w:fldChar" [("w:fldCharType","end")] ()+          ] -- w:r+        ) -- w:p+      ]) -- w:sdtContent+    ]] -- w:sdt++-- | Separator element between sections+sectionSeparator :: PandocMonad m => WS m (Maybe Content)+sectionSeparator = do+  asks envSectPr >>= \case+    Just sectPrElem -> pure $+      Just $ Elem (mknode "w:p" [] (mknode "w:pPr" [] [sectPrElem]))+    Nothing -> pure+      Nothing++-- | Convert Pandoc document to rendered document contents plus two lists of+-- OpenXML elements (footnotes and comments).+writeOpenXML :: PandocMonad m+             => WriterOptions -> Pandoc+             -> WS m (Text, [Element], [Element])+writeOpenXML opts (Pandoc meta blocks) = do+  setupTranslations meta+  let includeTOC = writerTableOfContents opts || lookupMetaBool "toc" meta+  let includeLOF = writerListOfFigures opts || lookupMetaBool "lof" meta+  let includeLOT = writerListOfTables opts || lookupMetaBool "lot" meta+  abstractTitle <- case lookupMeta "abstract-title" meta of+      Just (MetaBlocks bs)   -> pure $ stringify bs+      Just (MetaInlines ils) -> pure $ stringify ils+      Just (MetaString s)    -> pure s+      _                      -> translateTerm Abstract+  abstract <-+    case lookupMetaBlocks "abstract" meta of+      [] -> return mempty+      xs -> vcat . map (literal . showContent) <$>+              withParaPropM (pStyleM "Abstract") (blocksToOpenXML opts xs)++  let toInlineMeta field = hcat . map (literal . showContent) <$>+         inlinesToOpenXML opts (lookupMetaInlines field meta)++  title <- toInlineMeta "title"+  subtitle <- toInlineMeta "subtitle"+  date <- toInlineMeta "date"++  author <- mapM+             (fmap (hcat . map (literal . showContent)) . inlinesToOpenXML opts)+             (docAuthors meta)++  doc' <- setFirstPara >> blocksToOpenXML opts blocks+  let body = vcat $ map (literal . showContent) doc'+  notes' <- gets (reverse . stFootnotes)+  comments <- gets (reverse . stComments)+  let toComment (kvs, ils) = do+        annotation <- inlinesToOpenXML opts ils+        return $+          mknode "w:comment" [("w:" <> k, v) | (k,v) <- kvs]+            [ mknode "w:p" [] $+              map Elem+              [ mknode "w:pPr" []+                [ mknode "w:pStyle" [("w:val", "CommentText")] () ]+              , mknode "w:r" []+                [ mknode "w:rPr" []+                  [ mknode "w:rStyle" [("w:val", "CommentReference")] ()+                  ]+                  , mknode "w:annotationRef" [] ()+                ]+              ] ++ annotation+            ]+  comments' <- mapM toComment comments+  toc <- if includeTOC+            then makeTOC opts+            else return []+  lof <- if includeLOF+            then makeLOF opts+            else return []+  lot <- if includeLOT+            then makeLOT opts+            else return []+  metadata <- metaToContext opts+                 (fmap (vcat . map (literal . showContent)) . blocksToOpenXML opts)+                 (fmap (hcat . map (literal . showContent)) . inlinesToOpenXML opts)+                 meta+  cStyleMap <- gets (smParaStyle . stStyleMaps)+  let styleIdOf name = fromStyleId $ getStyleIdFromName name cStyleMap+  renderedSectPr <- maybe mempty ppElement <$> asks envSectPr++  let context = resetField "body" body+              . resetField "toc"+                   (vcat (map (literal . showElement) toc))+              . resetField "lof"+                   (vcat (map (literal . showElement) lof))+              . resetField "lot"+                   (vcat (map (literal . showElement) lot))+              . resetField "title" title+              . resetField "subtitle" subtitle+              . resetField "author" author+              . resetField "date" date+              . resetField "abstract-title" abstractTitle+              . resetField "abstract" abstract+              . resetField "title-style-id" (styleIdOf "Title")+              . resetField "subtitle-style-id" (styleIdOf "Subtitle")+              . resetField "author-style-id" (styleIdOf "Author")+              . resetField "date-style-id" (styleIdOf "Date")+              . resetField "abstract-title-style-id" (styleIdOf "AbstractTitle")+              . resetField "abstract-style-id" (styleIdOf "Abstract")+              . resetField "sectpr" renderedSectPr+              $ metadata+  tpl <- maybe (lift $ compileDefaultTemplate "openxml") pure $ writerTemplate opts+  let rendered = render Nothing $ renderTemplate tpl context+  return (rendered, notes', comments')++-- | Convert a list of Pandoc blocks to OpenXML.+blocksToOpenXML :: (PandocMonad m) => WriterOptions -> [Block] -> WS m [Content]+blocksToOpenXML opts =+  fmap concat . mapM (blockToOpenXML opts)+  . separateTables . filter (not . isForeignRawBlock)++isForeignRawBlock :: Block -> Bool+isForeignRawBlock (RawBlock format _) = format /= "openxml"+isForeignRawBlock _                   = False++-- Word combines adjacent tables unless you put an empty paragraph between+-- them.  See #4315.+separateTables :: [Block] -> [Block]+separateTables [] = []+separateTables (x@Table{}:xs@(Table{}:_)) =+  x : RawBlock (Format "openxml") "<w:p />" : separateTables xs+separateTables (x:xs) = x : separateTables xs++rStyleM :: (PandocMonad m) => CharStyleName -> WS m XML.Element+rStyleM styleName = do+  cStyleMap <- gets (smCharStyle . stStyleMaps)+  let sty' = getStyleIdFromName styleName cStyleMap+  return $ mknode "w:rStyle" [("w:val", fromStyleId sty')] ()++getUniqueId :: (PandocMonad m) => WS m Text+getUniqueId = do+  n <- gets stCurId+  modify $ \st -> st{stCurId = n + 1}+  return $ tshow n++-- | Key for specifying user-defined docx styles.+dynamicStyleKey :: Text+dynamicStyleKey = "custom-style"++-- | Convert a Pandoc block element to OpenXML.+blockToOpenXML :: (PandocMonad m) => WriterOptions -> Block -> WS m [Content]+blockToOpenXML opts blk = withDirection $ blockToOpenXML' opts blk++blockToOpenXML' :: (PandocMonad m) => WriterOptions -> Block -> WS m [Content]+blockToOpenXML' opts (Div (ident,_classes,kvs) bs) = do+  stylemod <- case lookup dynamicStyleKey kvs of+                   Just (fromString . T.unpack -> sty) -> do+                      modify $ \s ->+                        s{stDynamicParaProps = Set.insert sty+                             (stDynamicParaProps s)}+                      return $ withParaPropM (pStyleM sty)+                   _ -> return id+  dirmod <- case lookup "dir" kvs of+                 Just "rtl" -> return $ local (\env -> env { envRTL = True })+                 Just "ltr" -> return $ local (\env -> env { envRTL = False })+                 _ -> return id+  let (hs, bs') = if ident == "refs"+                     then span isHeaderBlock bs+                     else ([], bs)+  let bibmod = if ident == "refs"+                  then withParaPropM (pStyleM "Bibliography")+                  else id+  let langmod = case lookup "lang" kvs of+                  Nothing -> id+                  Just lang -> local (\env -> env{envLang = Just lang})+  header <- dirmod $ stylemod $ blocksToOpenXML opts hs+  contents <- dirmod $ bibmod $ stylemod $ langmod $ blocksToOpenXML opts bs'+  wrapBookmark ident $ header <> contents+blockToOpenXML' opts (Header lev (ident,_,kvs) lst) = do+  setFirstPara+  let isSection = case writerTopLevelDivision opts of+                     TopLevelChapter -> lev == 1+                     TopLevelPart -> lev <= 2+                     _ -> False+  paraProps <- withParaPropM (pStyleM (fromString $ "Heading "++show lev)) $+                    getParaProps False+  number <-+        if writerNumberSections opts+           then+             case lookup "number" kvs of+                Just n -> do+                   num <- withTextPropM (rStyleM "SectionNumber")+                            (inlineToOpenXML opts (Str n))+                   return $ num ++ [Elem $ mknode "w:r" [] [mknode "w:tab" [] ()]]+                Nothing -> return []+           else return []+  contents <- (number ++) <$> inlinesToOpenXML opts lst+  -- 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)]+       else do+         let bookmarkName = ident+         modify $ \s -> s{ stSectionIds = Set.insert bookmarkName+                                        $ stSectionIds s }+         bookmarkedContents <- wrapBookmark bookmarkName contents+         return [Elem $ mknode "w:p" [] (map Elem paraProps ++ bookmarkedContents)]+blockToOpenXML' opts (Plain lst) = do+  isInTable <- gets stInTable+  isInList <- gets stInList+  let block = blockToOpenXML opts (Para lst)+  prop <- pStyleM "Compact"+  if isInTable || isInList+     then withParaProp prop block+     else block+blockToOpenXML' opts (Para lst)+  | null lst && not (isEnabled Ext_empty_paragraphs opts) = return []+  | [Math InlineMath _] <- lst+     = blockToOpenXML' opts (Para (lst ++ [Str "\x200B"])) -- see #11674+       -- we add a space to prevent Word from displaying the single+       -- inline math element with display math style+  | otherwise = do+      isFirstPara <- gets stFirstPara+      let displayMathPara = case lst of+                                 [x] -> isDisplayMath x+                                 _   -> False+      paraProps <- getParaProps displayMathPara+      bodyTextStyle <- pStyleM $ if isFirstPara+                       then "First Paragraph"+                       else "Body Text"+      let paraProps' = case paraProps of+            []               -> [mknode "w:pPr" [] [bodyTextStyle]]+            ps               -> ps+      modify $ \s -> s { stFirstPara = False }+      contents <- inlinesToOpenXML opts lst+      return [Elem $ mknode "w:p" [] (map Elem paraProps' ++ contents)]+blockToOpenXML' opts (LineBlock lns) = blockToOpenXML opts $ linesToPara lns+blockToOpenXML' _ b@(RawBlock format str)+  | format == Format "openxml" = return [+        Text (CData CDataRaw str Nothing)+      ]+  | otherwise                  = do+      report $ BlockNotRendered b+      return []+blockToOpenXML' opts (BlockQuote blocks) = do+  inNote <- asks envInNote+  p <- withParaPropM (pStyleM+                       (if inNote+                           then "Footnote Block Text"+                           else "Block Text"))+       $ blocksToOpenXML opts blocks+  setFirstPara+  return p+blockToOpenXML' opts (CodeBlock attrs@(ident, _, _) str) = do+  p <- withParaPropM (pStyleM "Source Code") (blockToOpenXML opts $ Para [Code attrs str])+  setFirstPara+  wrapBookmark ident p+blockToOpenXML' _ HorizontalRule = do+  setFirstPara+  return [ Elem $+    mknode "w:p" [] $ mknode "w:r" [] $ mknode "w:pict" []+    $ mknode "v:rect" [("style","width:0;height:1.5pt"),+                       ("o:hralign","center"),+                       ("o:hrstd","t"),("o:hr","t")] () ]+blockToOpenXML' opts (Table attr caption colspecs thead tbodies tfoot) = do+  -- Remove extra paragraph indentation due to list items (#5947).+  -- This means that tables in lists will not be indented, but it+  -- avoids unwanted indentation in each cell.+  content <- tableToOpenXML opts+              (local (\env -> env{ envListLevel = -1 }) . blocksToOpenXML opts)+                 (Grid.toTable attr caption colspecs thead tbodies tfoot)+  let (tableId, _, _) = attr+  wrapBookmark tableId content+blockToOpenXML' opts el+  | BulletList lst <- el+    = case mapM toTaskListItem lst of+      Just items -> mconcat <$>+        mapM (\(checked, bs) -> addOpenXMLList (CheckboxMarker checked) [bs]) items+      Nothing -> addOpenXMLList BulletMarker lst+  | OrderedList (start, numstyle, numdelim) lst <- el+    = addOpenXMLList (NumberMarker numstyle numdelim start) lst+  where+    addOpenXMLList marker items = do+      addList marker+      numid <- getNumId+      exampleid <- case marker of+                     NumberMarker Example _ _ -> gets stExampleId+                     _ -> return Nothing+      l <- asList $ concat <$>+             mapM (listItemToOpenXML opts $ fromMaybe numid exampleid) items+      setFirstPara+      return l+blockToOpenXML' opts (DefinitionList items) = do+  l <- concat `fmap` mapM (definitionListItemToOpenXML opts) items+  setFirstPara+  return l+blockToOpenXML' opts (Figure (ident, _, _) (Caption _ longcapt) body) = do+  setFirstPara+  fignum <- gets stNextFigureNum+  unless (null longcapt) $ modify $ \st -> st{ stNextFigureNum = fignum + 1 }+  let refid = if T.null ident+              then "ref_fig" <> tshow fignum+              else "ref_" <> ident+  figname <- translateTerm Term.Figure+  prop <- pStyleM $+    if null longcapt+    then "Figure"+    else "Captioned Figure"+  paraProps <- local+    (\env -> env { envParaProperties = EnvProps (Just prop) [] <>+                                       envParaProperties env })+    (getParaProps False)++  -- Figure contents+  let simpleImage x = do+        imgXML <- inlineToOpenXML opts x+        pure $ Elem (mknode "w:p" [] (map Elem paraProps ++ imgXML))+  contentsNode <- case body of+    [Plain [img@Image {}]] -> simpleImage img+    [Para  [img@Image {}]] -> simpleImage img+    _                      -> toFigureTable opts body+  -- Caption+  let imageCaption = withParaPropM (pStyleM "Image Caption")+                   . blocksToOpenXML opts+  let fstCaptionPara inlns = Para $+        if not $ isEnabled Ext_native_numbering opts+        then inlns+        else let rawfld = RawInline (Format "openxml") $ mconcat+                          [ "<w:fldSimple w:instr=\"SEQ Figure"+                          , " \\* ARABIC \"><w:r><w:t>"+                          , tshow fignum+                          , "</w:t></w:r></w:fldSimple>"+                          ]+             in Span (refid,[],[]) [Str (figname <> "\160") , rawfld]+                : Str ": " : inlns+  captionNode <- case longcapt of+    []              -> return []+    (Para xs  : bs) -> imageCaption (fstCaptionPara xs : bs)+    (Plain xs : bs) -> imageCaption (fstCaptionPara xs : bs)+    _               -> imageCaption longcapt+  wrapBookmark ident $+    case writerFigureCaptionPosition opts of+      CaptionBelow -> contentsNode : captionNode+      CaptionAbove -> captionNode ++ [contentsNode]++toFigureTable :: PandocMonad m+              => WriterOptions -> [Block] -> WS m Content+toFigureTable opts blks = do+  modify $ \s -> s { stInTable = True }+  let ncols = length blks+  let textwidth = 7920  -- 5.5 in in twips       (1 twip == 1/20 pt)+  let cellfrac = 1 / fromIntegral ncols+  let colwidth = tshow @Integer $ floor (textwidth * cellfrac) -- twips+  let gridCols = replicate ncols $ mknode "w:gridCol" [("w:w", colwidth)] ()+  let scaleImage = \case+        Image attr@(ident, classes, attribs) alt tgt ->+          let dimWidth  = case dimension Width attr of+                            Nothing -> Percent (cellfrac * 100)+                            Just d  -> scaleDimension cellfrac d+              dimHeight = scaleDimension cellfrac <$> dimension Height attr+              attribs' = (tshow Width, tshow dimWidth) :+                         (case dimHeight of+                            Nothing -> id+                            Just h  -> ((tshow Height, tshow h) :))+                         [ (k, v) | (k, v) <- attribs+                                  , k `notElem` ["width", "height"]+                                  ]+          in Image (ident, classes, attribs') alt tgt+        x -> x+  let blockToCell = Table.OOXMLCell nullAttr AlignCenter 1 1 . (:[])+                  . walk scaleImage+  tblBody <- Table.rowToOpenXML (blocksToOpenXML opts) .+             Table.OOXMLRow Table.BodyRow nullAttr $+             map blockToCell blks+  let tbl = mknode "w:tbl" []+        ( mknode "w:tblPr" []+          [ mknode "w:tblStyle" [("w:val","FigureTable")] (),+            mknode "w:tblW" [ ("w:type", "auto"), ("w:w", "0") ] (),+            mknode "w:jc" [("w:val","center")] (),+            mknode "w:tblLook" [ ("w:firstRow", "0")+                               , ("w:lastRow", "0")+                               , ("w:firstColumn", "0")+                               , ("w:lastColumn", "0")+                               ] ()+          ]+          : mknode "w:tblGrid" [] gridCols+          : maybeToList tblBody+        )+  modify $ \s -> s { stInTable = False }+  return $ Elem tbl+++definitionListItemToOpenXML  :: (PandocMonad m)+                             => WriterOptions -> ([Inline],[[Block]])+                             -> WS m [Content]+definitionListItemToOpenXML opts (term,defs) = do+  term' <- withParaPropM (pStyleM "Definition Term")+           $ blockToOpenXML opts (Para term)+  defs' <- withParaPropM (pStyleM "Definition")+           $ concat `fmap` mapM (blocksToOpenXML opts) defs+  return $ term' ++ defs'++addList :: (PandocMonad m) => ListMarker -> WS m ()+addList marker = do+  lists <- gets stLists+  lastExampleId <- gets stExampleId+  modify $ \st -> st{ stLists = lists ++ case marker of+                                         -- Use only first occurrence of Example for list declaration to avoid overhead+                                         NumberMarker Example _ _ | isJust lastExampleId -> []+                                         _ -> [marker]+                    , stExampleId = case marker of+                                         -- Reuse the same identifier for all other occurrences of Example+                                         NumberMarker Example _ _ -> lastExampleId <|> Just (baseListId + length lists)+                                         _ -> lastExampleId+                  }++listItemToOpenXML :: (PandocMonad m)+                  => WriterOptions+                  -> Int -> [Block]+                  -> WS m [Content]+listItemToOpenXML opts numid bs = do+  oldInList <- gets stInList+  modify $ \st -> st{ stInList = True }+  let isListBlock = \case+        BulletList{}  -> True+        OrderedList{} -> True+        _             -> False+  -- Prepend an empty string if the first entry is another+  -- list. Otherwise the outer bullet will disappear.+  let bs' = case bs of+                 [] -> []+                 x:xs -> if isListBlock x+                               then Plain [Str ""]:x:xs+                               else x:xs+  modify $ \st -> st{ stNumIdUsed = False }+  contents <- withNumId numid $ blocksToOpenXML opts bs'+  modify $ \st -> st{ stInList = oldInList }+  return contents++-- | Convert a list of inline elements to OpenXML.+inlinesToOpenXML :: PandocMonad m => WriterOptions -> [Inline] -> WS m [Content]+inlinesToOpenXML opts lst = concat `fmap` mapM (inlineToOpenXML opts) (convertSpace lst)++withNumId :: (PandocMonad m) => Int -> WS m a -> WS m a+withNumId numid = local $ \env -> env{ envListNumId = numid }++asList :: (PandocMonad m) => WS m a -> WS m a+asList = local $ \env -> env{ envListLevel = envListLevel env + 1 }++getTextProps :: (PandocMonad m) => WS m [Element]+getTextProps = do+  props <- asks envTextProperties+  mblang <- asks envLang+  let langnode = case mblang of+                   Nothing -> mempty+                   Just l  -> EnvProps Nothing+                               [mknode "w:lang" [("w:val", l)] ()]+  let squashed = squashProps (props <> langnode)+  return [mknode "w:rPr" [] squashed | (not . null) squashed]++withTextProp :: PandocMonad m => Element -> WS m a -> WS m a+withTextProp d p =+  local (\env -> env {envTextProperties = ep <> envTextProperties env}) p+  where ep = if isStyle d then EnvProps (Just d) [] else EnvProps Nothing [d]++withTextPropM :: PandocMonad m => WS m Element -> WS m a -> WS m a+withTextPropM md p = do+  d <- md+  withTextProp d p++getParaProps :: PandocMonad m => Bool -> WS m [Element]+getParaProps displayMathPara = do+  props <- asks envParaProperties+  listLevel <- asks envListLevel+  numid <- asks envListNumId+  numIdUsed <- gets stNumIdUsed+  -- clear numId after first use to support multiple paragraphs in the same bullet+  -- baseListId is the code for no list marker+  let numid' = if numIdUsed then baseListId else numid+  modify $ \st -> st{ stNumIdUsed = True }+  let listPr = [mknode "w:numPr" []+                [ mknode "w:ilvl" [("w:val",tshow listLevel)] ()+                , mknode "w:numId" [("w:val",tshow numid')] () ] | listLevel >= 0 && not displayMathPara]+  return $ case squashProps (EnvProps Nothing listPr <> props) of+                [] -> []+                ps -> [mknode "w:pPr" [] ps]++formattedString :: PandocMonad m => Text -> WS m [Element]+formattedString str =+  -- properly handle soft hyphens+  case splitTextBy (=='\173') str of+      [w] -> formattedString' w+      ws  -> do+         sh <- formattedRun [mknode "w:softHyphen" [] ()]+         intercalate [sh] <$> mapM formattedString' ws++formattedString' :: PandocMonad m => Text -> WS m [Element]+formattedString' str = do+  inDel <- asks envInDel+  let mkrun s =+        (if T.any isCJK s+            then withTextProp (mknode "w:rFonts" [("w:hint","eastAsia")] ())+            else id) $ formattedRun+                       [ mktnode (if inDel then "w:delText" else "w:t")+                          [("xml:space","preserve")] $ s ]+  mapM mkrun $ breakIntoChunks $ stripInvalidChars str++-- For motivation see #9817.+breakIntoChunks :: Text -> [Text]+breakIntoChunks t+  | T.null t = []+  | T.any isCJK t+    = let cs = T.groupBy (\c d -> (isSpace c && isSpace d) ||+                                  not (isSpace c || isSpace d)) t+          css = groupBy (\x y -> not (T.any isCJK x || T.any isCJK y)+                                  || (T.all isSpace x && not (T.any isCJK y))+                                  || (T.all isSpace y && not (T.any isCJK x)))+                        cs+       in map mconcat css+  | otherwise = [t]++formattedRun :: PandocMonad m => [Element] -> WS m Element+formattedRun els = do+  props <- getTextProps+  return $ mknode "w:r" [] $ props ++ els++-- | Convert an inline element to OpenXML.+inlineToOpenXML :: PandocMonad m => WriterOptions -> Inline -> WS m [Content]+inlineToOpenXML opts il = withDirection $ inlineToOpenXML' opts il++inlineToOpenXML' :: PandocMonad m => WriterOptions -> Inline -> WS m [Content]+inlineToOpenXML' _ (Str str) =+  map Elem <$> formattedString str+inlineToOpenXML' opts Space = inlineToOpenXML opts (Str " ")+inlineToOpenXML' opts SoftBreak = inlineToOpenXML opts (Str " ")+inlineToOpenXML' opts (Span ("",["mark"],[]) ils) =+  withTextProp (mknode "w:highlight" [("w:val","yellow")] ()) $+    inlinesToOpenXML opts ils+inlineToOpenXML' opts (Span ("",["csl-block"],[]) ils) =+  inlinesToOpenXML opts ils+inlineToOpenXML' opts (Span ("",["csl-left-margin"],[]) ils) =+  inlinesToOpenXML opts ils+inlineToOpenXML' opts (Span ("",["csl-right-inline"],[]) ils) =+   ([Elem $+     mknode "w:r" []+     (mknode "w:t"+       [("xml:space","preserve")]+       ("\t" :: Text))] ++)+    <$> inlinesToOpenXML opts ils+inlineToOpenXML' opts (Span ("",["csl-indent"],[]) ils) =+  inlinesToOpenXML opts ils+inlineToOpenXML' _ (Span (ident,["comment-start"],kvs) ils) = do+  -- prefer the "id" in kvs, since that is the one produced by the docx+  -- reader.+  let ident' = fromMaybe ident (lookup "id" kvs)+      kvs' = filter (("id" /=) . fst) kvs+  modify $ \st -> st{ stComments = (("id",ident'):kvs', ils) : stComments st }+  return [ Elem $ mknode "w:commentRangeStart" [("w:id", ident')] () ]+inlineToOpenXML' opts (Span (ident,["comment-end"],kvs) content) = do+  -- prefer the "id" in kvs, since that is the one produced by the docx+  -- reader.+  let ident' = fromMaybe ident (lookup "id" kvs)+  -- process nested content: see #8189+  nestedContent <- inlinesToOpenXML opts content+  let thisCommentEnd =+        [ mknode "w:commentRangeEnd" [("w:id", ident')] ()+        , mknode "w:r" []+          [ mknode "w:rPr" []+            [ mknode "w:rStyle" [("w:val", "CommentReference")] () ]+          , mknode "w:commentReference" [("w:id", ident')] () ]+        ]+  return $ map Elem thisCommentEnd ++ nestedContent+inlineToOpenXML' opts (Span (ident,classes,kvs) ils) = do+  stylemod <- case lookup dynamicStyleKey kvs of+                   Just (fromString . T.unpack -> sty) -> do+                      modify $ \s ->+                        s{stDynamicTextProps = Set.insert sty+                              (stDynamicTextProps s)}+                      return $ withTextPropM (rStyleM sty)+                   _ -> return id+  let dirmod = case lookup "dir" kvs of+                 Just "rtl" -> local (\env -> env { envRTL = True })+                 Just "ltr" -> local (\env -> env { envRTL = False })+                 _          -> id+      off x = withTextProp (mknode x [("w:val","0")] ())+      pmod =  (if "csl-no-emph" `elem` classes then off "w:i" else id) .+              (if "csl-no-strong" `elem` classes then off "w:b" else id) .+              (if "csl-no-smallcaps" `elem` classes+                  then off "w:smallCaps"+                  else id)+      getChangeAuthorDate = do+        defaultAuthor <- asks envChangesAuthor+        let author = fromMaybe defaultAuthor (lookup "author" kvs)+        let mdate = lookup "date" kvs+        return $ ("w:author", author) :+                   maybe [] (\date -> [("w:date", date)]) mdate+  insmod <- if "insertion" `elem` classes+               then do+                 changeAuthorDate <- getChangeAuthorDate+                 insId <- gets stInsId+                 modify $ \s -> s{stInsId = insId + 1}+                 return $ \f -> do+                   x <- f+                   return [Elem $+                           mknode "w:ins"+                             (("w:id", tshow insId) : changeAuthorDate) x]+               else return id+  delmod <- if "deletion" `elem` classes+               then do+                 changeAuthorDate <- getChangeAuthorDate+                 delId <- gets stDelId+                 modify $ \s -> s{stDelId = delId + 1}+                 return $ \f -> local (\env->env{envInDel=True}) $ do+                   x <- f+                   return [Elem $ mknode "w:del"+                             (("w:id", tshow delId) : changeAuthorDate) x]+               else return id+  let langmod = case lookup "lang" kvs of+                  Nothing -> id+                  Just lang -> local (\env -> env{envLang = Just lang})+  contents <- insmod $ delmod $ dirmod $ stylemod $ pmod $+              langmod $ inlinesToOpenXML opts ils+  wrapBookmark ident contents+inlineToOpenXML' opts (Strong lst) =+  withTextProp (mknode "w:bCs" [] ()) $ -- needed for LTR, #6911+  withTextProp (mknode "w:b" [] ()) $+  inlinesToOpenXML opts lst+inlineToOpenXML' opts (Emph lst) =+  withTextProp (mknode "w:iCs" [] ()) $  -- needed for LTR, #6911+  withTextProp (mknode "w:i" [] ()) $+  inlinesToOpenXML opts lst+inlineToOpenXML' opts (Underline lst) =+  withTextProp (mknode "w:u" [("w:val","single")] ()) $+    inlinesToOpenXML opts lst+inlineToOpenXML' opts (Subscript lst) =+  withTextProp (mknode "w:vertAlign" [("w:val","subscript")] ())+  $ inlinesToOpenXML opts lst+inlineToOpenXML' opts (Superscript lst) =+  withTextProp (mknode "w:vertAlign" [("w:val","superscript")] ())+  $ inlinesToOpenXML opts lst+inlineToOpenXML' opts (SmallCaps lst) =+  withTextProp (mknode "w:smallCaps" [] ())+  $ inlinesToOpenXML opts lst+inlineToOpenXML' opts (Strikeout lst) =+  withTextProp (mknode "w:strike" [] ())+  $ inlinesToOpenXML opts lst+inlineToOpenXML' _ LineBreak = return [Elem br]+inlineToOpenXML' _ il@(RawInline f str)+  | f == Format "openxml" = return+                            [Text (CData CDataRaw str Nothing)]+  | otherwise             = do+      report $ InlineNotRendered il+      return []+inlineToOpenXML' opts (Quoted quoteType lst) =+  inlinesToOpenXML opts $ [Str open] ++ lst ++ [Str close]+    where (open, close) = case quoteType of+                            SingleQuote -> ("\x2018", "\x2019")+                            DoubleQuote -> ("\x201C", "\x201D")+inlineToOpenXML' opts (Math mathType str) = do+  when (mathType == DisplayMath) setFirstPara+  res <- (lift . lift) (convertMath writeOMML mathType str)+  case res of+       Right r -> return [Elem $ fromXLElement r]+       Left il -> inlineToOpenXML' opts il+inlineToOpenXML' opts (Cite _ lst) = inlinesToOpenXML opts lst+inlineToOpenXML' opts (Code attrs str) = do+  let alltoktypes = [KeywordTok ..]+  tokTypesMap <- mapM (\tt -> (,) tt <$> rStyleM (fromString $ show tt)) alltoktypes+  let unhighlighted = (map Elem . intercalate [br]) `fmap`+                       mapM formattedString (T.lines str)+      formatOpenXML _fmtOpts = intercalate [br] . map (map toHlTok)+      toHlTok (toktype,tok) =+        mknode "w:r" []+          [ mknode "w:rPr" [] $+            maybeToList (lookup toktype tokTypesMap)+            , mknode "w:t" [("xml:space","preserve")] tok ]+  let highlighted =+        case highlight (writerSyntaxMap opts) formatOpenXML attrs str of+            Right h  -> return (map Elem h)+            Left msg -> do+              unless (T.null msg) $ report $ CouldNotHighlight msg+              unhighlighted+  withTextPropM (rStyleM "Verbatim Char")+    $ case writerHighlightMethod opts of+        DefaultHighlighting -> highlighted+        Skylighting _ -> highlighted+        _ -> unhighlighted+inlineToOpenXML' opts (Note bs) = do+  notes <- gets stFootnotes+  notenum <- getUniqueId+  oldFirstPara <- gets stFirstPara+  footnoteStyle <- rStyleM "Footnote Reference"+  let notemarker = mknode "w:r" []+                   [ mknode "w:rPr" [] footnoteStyle+                   , mknode "w:footnoteRef" [] () ]+  let notemarkerXml = RawInline (Format "openxml") $ ppElement notemarker+  let insertNoteRef (Plain ils : xs) = Plain (notemarkerXml : Space : ils) : xs+      insertNoteRef (Para ils  : xs) = Para  (notemarkerXml : Space : ils) : xs+      insertNoteRef xs               = Para [notemarkerXml] : xs++  contents <- local (\env -> env{ envListLevel = -1+                                , envParaProperties = mempty+                                , envTextProperties = mempty+                                , envInNote = True })+              (withParaPropM (pStyleM "Footnote Text") $+               blocksToOpenXML opts $ insertNoteRef bs)+  modify $ \s -> s{ stFirstPara = oldFirstPara }+  let newnote = mknode "w:footnote" [("w:id", notenum)] contents+  modify $ \s -> s{ stFootnotes = newnote : notes }+  return [ Elem $ mknode "w:r" []+           [ mknode "w:rPr" [] footnoteStyle+           , mknode "w:footnoteReference" [("w:id", notenum)] () ] ]+-- internal link:+inlineToOpenXML' opts (Link _ txt (T.uncons -> Just ('#', xs),_)) = do+  contents <- withTextPropM (rStyleM "Hyperlink") $ inlinesToOpenXML opts txt+  return+    [ Elem $ mknode "w:hyperlink" [("w:anchor", toBookmarkName xs)] contents ]+-- external link:+inlineToOpenXML' opts (Link _ txt (src,_)) = do+  contents <- withTextPropM (rStyleM "Hyperlink") $ inlinesToOpenXML opts txt+  extlinks <- gets stExternalLinks+  id' <- case M.lookup src extlinks of+            Just i   -> return i+            Nothing  -> do+              i <- ("rId" <>) <$> getUniqueId+              modify $ \st -> st{ stExternalLinks =+                        M.insert src i extlinks }+              return i+  return [ Elem $ mknode "w:hyperlink" [("r:id",id')] contents ]+inlineToOpenXML' opts (Image attr@(imgident, _, _) alt (src, title)) = do+  pageWidth <- asks envPrintWidth+  imgs <- gets stImages+  let+    stImage = M.lookup (T.unpack src) imgs+    generateImgElt (ident, _fp, mt, img) = do+      docprid <- getUniqueId+      nvpicprid <- getUniqueId+      (blipAttrs, blipContents) <-+        case T.takeWhile (/=';') <$> mt of+          Just "image/svg+xml" -> do+            -- get fallback png+            mediabag <- getMediaBag+            mbFallback <-+              case lookupMedia (T.unpack (src <> ".png")) mediabag of+                Just item -> do+                  id' <- T.unpack . ("rId" <>) <$> getUniqueId+                  let fp' = "media/" <> id' <> ".png"+                  let imgdata = (id',+                                 fp',+                                 Just (mediaMimeType item),+                                 BL.toStrict $ mediaContents item)+                  modify $ \st -> st { stImages =+                            M.insert fp' imgdata $ stImages st }+                  return $ Just id'+                Nothing -> return Nothing+            let extLst = mknode "a:extLst" []+                            [ mknode "a:ext"+                              [("uri","{28A0092B-C50C-407E-A947-70E740481C1C}")]+                              [ mknode "a14:useLocalDpi"+                                [("xmlns:a14","http://schemas.microsoft.com/office/drawing/2010/main"),+                                 ("val","0")] () ]+                            , mknode "a:ext"+                              [("uri","{96DAC541-7B7A-43D3-8B79-37D633B846F1}")]+                              [ mknode "asvg:svgBlip"+                                [("xmlns:asvg", "http://schemas.microsoft.com/office/drawing/2016/SVG/main"),+                                 ("r:embed",T.pack ident)] () ]+                            ]+            return (maybe [] (\id'' -> [("r:embed", T.pack id'')]) mbFallback,+                    [extLst])+          _ -> return ([("r:embed", T.pack ident)], [])+      let+        (xpt,ypt) = desiredSizeInPoints opts attr+               (either (const def) id (imageSize opts img))+        -- 12700 emu = 1 pt+        pageWidthPt = case dimension Width attr of+                        Just (Percent a) -> pageWidth * floor (a * 127)+                        _                -> pageWidth * 12700+        (xemu,yemu) = fitToPage (xpt * 12700, ypt * 12700) pageWidthPt+        cNvPicPr = mknode "pic:cNvPicPr" [] $+                         mknode "a:picLocks" [("noChangeArrowheads","1")+                                             ,("noChangeAspect","1")] ()+        nvPicPr  = mknode "pic:nvPicPr" []+                        [ mknode "pic:cNvPr"+                            [("descr",src)+                            ,("id", nvpicprid)+                            ,("name","Picture")] ()+                        , cNvPicPr ]+        blipFill = mknode "pic:blipFill" []+          [ mknode "a:blip" blipAttrs blipContents+          , mknode "a:stretch" [] $+              mknode "a:fillRect" [] ()+          ]+        xfrm =    mknode "a:xfrm" []+                        [ mknode "a:off" [("x","0"),("y","0")] ()+                        , mknode "a:ext" [("cx",tshow xemu)+                                         ,("cy",tshow yemu)] () ]+        prstGeom = mknode "a:prstGeom" [("prst","rect")] $+                         mknode "a:avLst" [] ()+        ln =      mknode "a:ln" [("w","9525")]+                        [ mknode "a:noFill" [] ()+                        , mknode "a:headEnd" [] ()+                        , mknode "a:tailEnd" [] () ]+        spPr =    mknode "pic:spPr" [("bwMode","auto")]+                        [xfrm, prstGeom, mknode "a:noFill" [] (), ln]+        graphic = mknode "a:graphic" [] $+          mknode "a:graphicData"+            [("uri","http://schemas.openxmlformats.org/drawingml/2006/picture")]+            [ mknode "pic:pic" []+              [ nvPicPr+              , blipFill+              , spPr+              ]+            ]+        imgElt = mknode "w:r" [] $+          mknode "w:drawing" [] $+            mknode "wp:inline" []+              [ mknode "wp:extent" [("cx",tshow xemu),("cy",tshow yemu)] ()+              , mknode "wp:effectExtent"+                [("b","0"),("l","0"),("r","0"),("t","0")] ()+              , mknode "wp:docPr"+                [ ("descr", stringify alt)+                , ("title", title)+                , ("id", docprid)+                , ("name","Picture")+                ] ()+              , graphic+              ]+      return [Elem imgElt]++  wrapBookmark imgident =<< case stImage of+    Just imgData -> generateImgElt imgData+    Nothing -> ( do --try+      (img, mt) <- P.fetchItem src+      ident <- ("rId" <>) <$> getUniqueId++      let+        imgext = case mt >>= extensionFromMimeType of+          Just x    -> "." <> x+          Nothing   -> case imageType img of+            Just Png  -> ".png"+            Just Jpeg -> ".jpeg"+            Just Gif  -> ".gif"+            Just Pdf  -> ".pdf"+            Just Eps  -> ".eps"+            Just Svg  -> ".svg"+            Just Emf  -> ".emf"+            Just Tiff -> ".tiff"+            Just Webp -> ".webp"+            Just Avif -> ".avif"+            Nothing   -> ""+        imgpath = "media/" <> ident <> imgext+        mbMimeType = mt <|> getMimeType (T.unpack imgpath)++        imgData = (T.unpack ident, T.unpack imgpath, mbMimeType, img)++      if T.null imgext+         then -- without an extension there is no rule for content type+           inlinesToOpenXML opts alt -- return alt to avoid corrupted docx+         else do+           -- insert mime type to use in constructing [Content_Types].xml+           modify $ \st -> st { stImages = M.insert (T.unpack src) imgData $ stImages st }+           generateImgElt imgData+      )+      `catchError` ( \e -> do+        report $ CouldNotFetchResource src $ T.pack (show e)+        -- emit alt text+        inlinesToOpenXML opts alt+      )++br :: Element+br = mknode "w:r" [] [mknode "w:br" [] ()]+++withDirection :: PandocMonad m => WS m a -> WS m a+withDirection x = do+  isRTL <- asks envRTL+  paraProps <- asks envParaProperties+  textProps <- asks envTextProperties+  -- We want to clean all bidirection (bidi) and right-to-left (rtl)+  -- properties from the props first. This is because we don't want+  -- them to stack up.+  let paraProps' = filter (\e -> (qName . elName) e /= "bidi") (otherElements paraProps)+      textProps' = filter (\e -> (qName . elName) e /= "rtl") (otherElements textProps)+      paraStyle = styleElement paraProps+      textStyle = styleElement textProps+  if isRTL+    -- if we are going right-to-left, we (re?)add the properties.+    then flip local x $+         \env -> env { envParaProperties = EnvProps paraStyle $ mknode "w:bidi" [] () : paraProps'+                     , envTextProperties = EnvProps textStyle $ mknode "w:rtl" [] () : textProps'+                     }+    else flip local x $ \env -> env { envParaProperties = EnvProps paraStyle paraProps'+                                    , envTextProperties = EnvProps textStyle textProps'+                                    }++wrapBookmark :: (PandocMonad m) => Text -> [Content] -> WS m [Content]+wrapBookmark "" contents = return contents+wrapBookmark ident contents = do+  id' <- getUniqueId+  let bookmarkStart = mknode "w:bookmarkStart"+                       [("w:id", id')+                       ,("w:name", toBookmarkName ident)] ()+      bookmarkEnd = mknode "w:bookmarkEnd" [("w:id", id')] ()+  return $ Elem bookmarkStart : contents ++ [Elem bookmarkEnd]++-- Word imposes a 40 character limit on bookmark names and requires+-- that they begin with a letter.  So we just use a hash of the+-- identifier when otherwise we'd have an illegal bookmark name.+toBookmarkName :: Text -> Text+toBookmarkName s+  | Just (c, _) <- T.uncons s+  , isLetter c+  , T.length s <= 40 = s+  | otherwise = T.pack $ 'X' : drop 1 (show (hashWith SHA1 (fromText s)))++maxListLevel :: Int+maxListLevel = 8++convertSpace :: [Inline] -> [Inline]+convertSpace (Str x : Space : Str y : xs) = convertSpace (Str (x <> " " <> y) : xs)+convertSpace (Str x : Str y : xs)         = convertSpace (Str (x <> y) : xs)+convertSpace (x:xs)                       = x : convertSpace xs+convertSpace []                           = []
src/Text/Pandoc/Writers/Docx/StyleMap.hs view
@@ -2,7 +2,7 @@ {- |    Module : Text.Pandoc.Writers.Docx.StyleMap    Copyright   : © 2014-2020 Jesse Rosenthal <jrosenthal@jhu.edu>,-                   2014-2023 John MacFarlane <jgm@berkeley.edu>,+                   2014-2024 John MacFarlane <jgm@berkeley.edu>,                    2015-2019 Nikolay Yakimov <root@livid.pp.ru>    License     : GNU GPL, version 2 or above 
src/Text/Pandoc/Writers/Docx/Table.hs view
@@ -3,7 +3,7 @@ {-# LANGUAGE ScopedTypeVariables #-} {- | Module      : Text.Pandoc.Writers.Docx.Table-Copyright   : Copyright (C) 2012-2023 John MacFarlane+Copyright   : Copyright (C) 2012-2024 John MacFarlane License     : GNU GPL, version 2 or above Maintainer  : John MacFarlane <jgm@berkeley.edu> @@ -22,7 +22,7 @@ import Control.Monad.Except ( throwError ) import Data.Array ( elems, (!), assocs, indices ) import Data.Text (Text)-import Data.Maybe (catMaybes)+import Data.Maybe (catMaybes, fromMaybe) import Text.Pandoc.Definition     ( ColSpec,       Caption(Caption),@@ -46,7 +46,7 @@       withParaPropM ) import Control.Monad.Reader (asks) import Text.Pandoc.Shared ( tshow, stringify )-import Text.Pandoc.Options (WriterOptions, isEnabled)+import Text.Pandoc.Options (WriterOptions(..), isEnabled, CaptionPosition(..)) import Text.Pandoc.Extensions (Extension(Ext_native_numbering)) import Text.Pandoc.Error (PandocError(PandocSomeError)) import Text.Printf (printf)@@ -71,7 +71,7 @@                -> WS m [Content] tableToOpenXML opts blocksToOpenXML gridTable = do   setFirstPara-  let (Grid.Table (ident,_,_) caption colspecs _rowheads thead tbodies tfoot) =+  let (Grid.Table (ident,_,tableAttr) caption colspecs _rowheads thead tbodies tfoot) =         gridTable   let (Caption _maybeShortCaption captionBlocks) = caption   tablenum <- gets stNextTableNum@@ -109,11 +109,12 @@   let tblLookVal = if hasHeader then (0x20 :: Int) else 0   let (gridCols, tblWattr) = tableLayout (elems colspecs)   listLevel <- asks envListLevel+  let tblStyle =  fromMaybe "Table" (lookup "custom-style" tableAttr)   let indent = (listLevel + 1) * 720   let hasWidths = not $ all ((== ColWidthDefault) . snd) colspecs   let tbl = mknode "w:tbl" []         ( mknode "w:tblPr" []-          ( [ mknode "w:tblStyle" [("w:val","Table")] (),+          ( [ mknode "w:tblStyle" [("w:val",tblStyle)] (),               mknode "w:tblW" tblWattr () ] ++             [ mknode "w:jc" [("w:val","left")] () | indent > 0 ] ++             [ mknode "w:tblInd" [("w:w", tshow indent),("w:type","dxa")] ()@@ -134,7 +135,10 @@           : head' ++ mconcat bodies ++ foot'         )   modify $ \s -> s { stInTable = False }-  return $ captionXml ++ [Elem tbl]+  return $+    case writerTableCaptionPosition opts of+      CaptionAbove -> captionXml ++ [Elem tbl]+      CaptionBelow -> Elem tbl : captionXml  addLabel :: Text -> Text -> Int -> [Block] -> [Block] addLabel tableid tablename tablenum bs =@@ -159,7 +163,7 @@   AlignLeft    -> "left"   AlignRight   -> "right"   AlignCenter  -> "center"-  AlignDefault -> "left"+  AlignDefault -> ""  tableLayout :: [ColSpec] -> ([Element], [(Text, Text)]) tableLayout specs =@@ -253,7 +257,7 @@       , mknode "w:p" [] [mknode "w:pPr" [] ()]]   OOXMLCell _attr align rowspan (ColSpan colspan) contents -> do     compactStyle <- pStyleM "Compact"-    es <- withParaProp (alignmentFor align) $ blocksToOpenXML contents+    es <- maybe id withParaProp (alignmentFor align) $ blocksToOpenXML contents     -- Table cells require a <w:p> element, even an empty one!     -- Not in the spec but in Word 2007, 2010. See #4953. And     -- apparently the last element must be a <w:p>, see #6983.@@ -271,5 +275,6 @@              e:_   | qName (elName e) == "p" -> es              _ -> es ++ [Elem $ mknode "w:p" [] ()] -alignmentFor :: Alignment -> Element-alignmentFor al = mknode "w:jc" [("w:val",alignmentToString al)] ()+alignmentFor :: Alignment -> Maybe Element+alignmentFor AlignDefault = Nothing+alignmentFor al = Just $ mknode "w:jc" [("w:val",alignmentToString al)] ()
src/Text/Pandoc/Writers/Docx/Types.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings   #-} {- | Module      : Text.Pandoc.Writers.Docx-Copyright   : Copyright (C) 2012-2023 John MacFarlane+Copyright   : Copyright (C) 2012-2024 John MacFarlane License     : GNU GPL, version 2 or above Maintainer  : John MacFarlane <jgm@berkeley.edu> @@ -40,12 +40,15 @@  data ListMarker = NoMarker                 | BulletMarker+                | CheckboxMarker Bool                 | NumberMarker ListNumberStyle ListNumberDelim Int                 deriving (Show, Read, Eq, Ord)  listMarkerToId :: ListMarker -> Text listMarkerToId NoMarker = "990" listMarkerToId BulletMarker = "991"+listMarkerToId (CheckboxMarker False) = "992"+listMarkerToId (CheckboxMarker True) = "993" listMarkerToId (NumberMarker sty delim n) = T.pack $   '9' : '9' : styNum : delimNum : show n   where styNum = case sty of@@ -86,6 +89,7 @@   , envChangesDate    :: Text   , envPrintWidth     :: Integer   , envLang           :: Maybe Text+  , envSectPr         :: Maybe Element   }  defaultWriterEnv :: WriterEnv@@ -101,6 +105,7 @@   , envChangesDate    = "1969-12-31T19:00:00Z"   , envPrintWidth     = 1   , envLang           = Nothing+  , envSectPr         = Nothing   }  @@ -116,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@@ -141,6 +147,7 @@       , stDelId          = 1       , stStyleMaps      = StyleMaps M.empty M.empty       , stFirstPara      = False+      , stFirstSectionHeader = True       , stNumIdUsed      = False       , stInTable        = False       , stInList         = False
src/Text/Pandoc/Writers/DokuWiki.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Writers.DokuWiki-   Copyright   : Copyright (C) 2008-2023 John MacFarlane+   Copyright   : Copyright (C) 2008-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : Clare Macrae <clare.macrae@googlemail.com>@@ -14,7 +14,7 @@ -}  {--    [ ] Implement nested blockquotes (currently only ever does one level)+    [x] Implement nested blockquotes (currently only ever does one level)     [x] Implement alignment of text in tables     [ ] Implement comments     [ ] Work through the Dokuwiki spec, and check I've not missed anything out@@ -32,12 +32,12 @@ import qualified Data.Text as T import Text.Pandoc.Class.PandocMonad (PandocMonad, report) import Text.Pandoc.Definition+import Text.Pandoc.Extensions import Text.Pandoc.ImageSize import Text.Pandoc.Logging import Text.Pandoc.Options (WrapOption (..), WriterOptions (writerTableOfContents,-                            writerTemplate, writerWrapText))-import Text.Pandoc.Shared (camelCaseToHyphenated, figureDiv, linesToPara,-                           removeFormatting, trimr, tshow)+                            writerTemplate, writerWrapText), isEnabled)+import Text.Pandoc.Shared (figureDiv, linesToPara, removeFormatting, trimr) import Text.Pandoc.URI (escapeURI, isURI) import Text.Pandoc.Templates (renderTemplate) import Text.DocLayout (render, literal)@@ -50,8 +50,8 @@  data WriterEnvironment = WriterEnvironment {     stIndent      :: Text          -- Indent after the marker at the beginning of list items-  , stUseTags     :: Bool            -- True if we should use HTML tags because we're in a complex list   , stBackSlashLB :: Bool     -- True if we should produce formatted strings with newlines (as in a table cell)+  , stBlockQuoteLevel :: Int   -- Block quote level   }  instance Default WriterState where@@ -59,8 +59,8 @@  instance Default WriterEnvironment where   def = WriterEnvironment { stIndent = ""-                          , stUseTags = False-                          , stBackSlashLB = False }+                          , stBackSlashLB = False+                          , stBlockQuoteLevel = 0 }  type DokuWiki m = ReaderT WriterEnvironment (StateT WriterState m) @@ -109,21 +109,23 @@   inlineListToDokuWiki opts inlines  blockToDokuWiki opts (Para inlines) = do+  bqLevel <- asks stBlockQuoteLevel+  let bqPrefix = case bqLevel of+                    0 -> ""+                    n -> T.replicate n ">" <> " "   indent <- asks stIndent-  useTags <- asks stUseTags   contents <- inlineListToDokuWiki opts inlines-  return $ if useTags-              then "<HTML><p></HTML>" <> contents <> "<HTML></p></HTML>"-              else contents <> if T.null indent then "\n" else ""+  return $ bqPrefix <> contents <> if T.null indent then "\n" else ""  blockToDokuWiki opts (LineBlock lns) =   blockToDokuWiki opts $ linesToPara lns -blockToDokuWiki _ b@(RawBlock f str)+blockToDokuWiki opts b@(RawBlock f str)   | f == Format "dokuwiki" = return str   -- See https://www.dokuwiki.org/wiki:syntax   -- use uppercase HTML tag for block-level content:-  | f == Format "html"     = return $ "<HTML>\n" <> str <> "\n</HTML>"+  | f == Format "html"+  , isEnabled Ext_raw_html opts = return $ "<HTML>\n" <> str <> "\n</HTML>"   | otherwise              = "" <$          report (BlockNotRendered b) @@ -136,19 +138,22 @@   let eqs = T.replicate ( 7 - level ) "="   return $ eqs <> " " <> contents <> " " <> eqs <> "\n" -blockToDokuWiki _ (CodeBlock (_,classes,_) str) =-  return $ "<code" <>+blockToDokuWiki _ (CodeBlock (_,classes,_) str) = do+  bqLevel <- asks stBlockQuoteLevel+  let bqPrefix = case bqLevel of+                    0 -> ""+                    n -> T.replicate n ">" <> " "+  return $ bqPrefix <>+           "<code" <>            (case classes of                []    -> ""                (x:_) -> " " <> fromMaybe x (M.lookup x languageNames)) <>            ">\n" <> str <>            (if "\n" `T.isSuffixOf` str then "" else "\n") <> "</code>\n" -blockToDokuWiki opts (BlockQuote blocks) = do-  contents <- blockListToDokuWiki opts blocks-  if isSimpleBlockQuote blocks-     then return $ T.unlines $ map ("> " <>) $ T.lines contents-     else return $ "<HTML><blockquote>\n" <> contents <> "</blockquote></HTML>"+blockToDokuWiki opts (BlockQuote blocks) =+  local (\st -> st{ stBlockQuoteLevel = stBlockQuoteLevel st + 1 })+               (blockListToDokuWiki opts blocks)  blockToDokuWiki opts (Table _ blkCapt specs thead tbody tfoot) = do   let (capt, aligns, _, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot@@ -179,37 +184,21 @@            (if null headers' then "" else renderRow "^" headers' <> "\n") <>            T.unlines (map (renderRow "|") rows') -blockToDokuWiki opts x@(BulletList items) = do-  oldUseTags <- asks stUseTags+blockToDokuWiki opts (BulletList items) = do   indent <- asks stIndent   backSlash <- asks stBackSlashLB-  let useTags = oldUseTags || not (isSimpleList x)-  if useTags-     then do-        contents <- local (\s -> s { stUseTags = True })-                      (mapM (listItemToDokuWiki opts) items)-        return $ "<HTML><ul></HTML>\n" <> vcat contents <> "<HTML></ul></HTML>\n"-     else do-        contents <- local (\s -> s { stIndent = stIndent s <> "  "-                                   , stBackSlashLB = backSlash})+  contents <- local (\s -> s { stIndent = stIndent s <> "  "+                             , stBackSlashLB = backSlash})                       (mapM (listItemToDokuWiki opts) items)-        return $ vcat contents <> if T.null indent then "\n" else ""+  return $ vcat contents <> if T.null indent then "\n" else "" -blockToDokuWiki opts x@(OrderedList attribs items) = do-  oldUseTags <- asks stUseTags+blockToDokuWiki opts (OrderedList _attribs items) = do   indent <- asks stIndent   backSlash <- asks stBackSlashLB-  let useTags = oldUseTags || not (isSimpleList x)-  if useTags-     then do-        contents <- local (\s -> s { stUseTags = True })-                      (mapM (orderedListItemToDokuWiki opts) items)-        return $ "<HTML><ol" <> listAttribsToString attribs <> "></HTML>\n" <> vcat contents <> "<HTML></ol></HTML>\n"-     else do-        contents <- local (\s -> s { stIndent = stIndent s <> "  "-                                   , stBackSlashLB = backSlash})-                      (mapM (orderedListItemToDokuWiki opts) items)-        return $ vcat contents <> if T.null indent then "\n" else ""+  contents <- local (\s -> s { stIndent = stIndent s <> "  "+                             , stBackSlashLB = backSlash})+                (mapM (orderedListItemToDokuWiki opts) items)+  return $ vcat contents <> if T.null indent then "\n" else ""  blockToDokuWiki opts (Figure attr capt body) =   blockToDokuWiki opts $ figureDiv attr capt body@@ -217,67 +206,55 @@ -- TODO Need to decide how to make definition lists work on dokuwiki - I don't think there --      is a specific representation of them. -- TODO This creates double '; ; ' if there is a bullet or ordered list inside a definition list-blockToDokuWiki opts x@(DefinitionList items) = do-  oldUseTags <- asks stUseTags+blockToDokuWiki opts (DefinitionList items) = do   indent <- asks stIndent   backSlash <- asks stBackSlashLB-  let useTags = oldUseTags || not (isSimpleList x)-  if useTags-     then do-        contents <- local (\s -> s { stUseTags = True })-                      (mapM (definitionListItemToDokuWiki opts) items)-        return $ "<HTML><dl></HTML>\n" <> vcat contents <> "<HTML></dl></HTML>\n"-     else do-        contents <- local (\s -> s { stIndent = stIndent s <> "  "-                                   , stBackSlashLB = backSlash})-                      (mapM (definitionListItemToDokuWiki opts) items)-        return $ vcat contents <> if T.null indent then "\n" else ""+  contents <- local (\s -> s { stIndent = stIndent s <> "  "+                             , stBackSlashLB = backSlash})+                (mapM (definitionListItemToDokuWiki opts) items)+  return $ vcat contents <> if T.null indent then "\n" else ""  -- Auxiliary functions for lists: --- | Convert ordered list attributes to HTML attribute string-listAttribsToString :: ListAttributes -> Text-listAttribsToString (startnum, numstyle, _) =-  let numstyle' = camelCaseToHyphenated $ tshow numstyle-  in  (if startnum /= 1-          then " start=\"" <> tshow startnum <> "\""-          else "") <>-      (if numstyle /= DefaultStyle-          then " style=\"list-style-type: " <> numstyle' <> ";\""-          else "")- -- | Convert bullet list item (list of blocks) to DokuWiki. listItemToDokuWiki :: PandocMonad m                    => WriterOptions -> [Block] -> DokuWiki m Text listItemToDokuWiki opts items = do-  useTags <- asks stUseTags-  if useTags-     then do-       contents <- blockListToDokuWiki opts items-       return $ "<HTML><li></HTML>" <> contents <> "<HTML></li></HTML>"-     else do-       bs <- mapM (blockToDokuWiki opts) items-       let contents = case items of-                           [_, CodeBlock _ _] -> T.concat bs-                           _                  -> vcat bs-       indent <- asks stIndent-       backSlash <- asks stBackSlashLB-       let indent' = if backSlash then T.drop 2 indent else indent-       return $ indent' <> "* " <> contents+  bqLevel <- asks stBlockQuoteLevel+  let bqPrefix = case bqLevel of+                    0 -> ""+                    n -> T.replicate n ">" <> " "+  let useWrap = not (isSimpleListItem items)+  bs <- mapM (blockToDokuWiki opts) items+  let contents = case items of+                      [_, CodeBlock _ _] -> T.concat bs+                      _                  -> vcat bs+  indent <- asks stIndent+  backSlash <- asks stBackSlashLB+  let indent' = if backSlash then T.drop 2 indent else indent+  return $ bqPrefix <> indent' <> "* " <>+    if useWrap+       then "<WRAP>\n" <> contents <> "\n</WRAP>"+       else contents  -- | Convert ordered list item (list of blocks) to DokuWiki. -- | TODO Emiminate dreadful duplication of text from listItemToDokuWiki orderedListItemToDokuWiki :: PandocMonad m => WriterOptions -> [Block] -> DokuWiki m Text orderedListItemToDokuWiki opts items = do-  contents <- blockListToDokuWiki opts items-  useTags <- asks stUseTags-  if useTags-     then return $ "<HTML><li></HTML>" <> contents <> "<HTML></li></HTML>"-     else do-       indent <- asks stIndent-       backSlash <- asks stBackSlashLB-       let indent' = if backSlash then T.drop 2 indent else indent-       return $ indent' <> "- " <> contents+  bqLevel <- asks stBlockQuoteLevel+  let bqPrefix = case bqLevel of+                    0 -> ""+                    n -> T.replicate n ">" <> " "+  let useWrap = not (isSimpleListItem items)+  contents <- local (\st -> st{ stBlockQuoteLevel = 0 })+               (blockListToDokuWiki opts items)+  indent <- asks stIndent+  backSlash <- asks stBackSlashLB+  let indent' = if backSlash then T.drop 2 indent else indent+  return $ bqPrefix <> indent' <> "- " <>+    if useWrap+       then "<WRAP>\n" <> contents <> "\n</WRAP>"+       else contents  -- | Convert definition list item (label, list of blocks) to DokuWiki. definitionListItemToDokuWiki :: PandocMonad m@@ -285,29 +262,24 @@                              -> ([Inline],[[Block]])                              -> DokuWiki m Text definitionListItemToDokuWiki opts (label, items) = do+  let useWrap = not (all isSimpleListItem items)+  bqLevel <- asks stBlockQuoteLevel+  let bqPrefix = case bqLevel of+                    0 -> ""+                    n -> T.replicate n ">" <> " "   labelText <- inlineListToDokuWiki opts label-  contents <- mapM (blockListToDokuWiki opts) items-  useTags <- asks stUseTags-  if useTags-     then return $ "<HTML><dt></HTML>" <> labelText <> "<HTML></dt></HTML>\n" <>-           T.intercalate "\n" (map (\d -> "<HTML><dd></HTML>" <> d <> "<HTML></dd></HTML>") contents)-     else do-       indent <- asks stIndent-       backSlash <- asks stBackSlashLB-       let indent' = if backSlash then T.drop 2 indent else indent-       return $ indent' <> "* **" <> labelText <> "** " <> T.concat contents---- | True if the list can be handled by simple wiki markup, False if HTML tags will be needed.-isSimpleList :: Block -> Bool-isSimpleList x =-  case x of-       BulletList items            -> all isSimpleListItem items-       OrderedList (1, _, _) items -> all isSimpleListItem items-       DefinitionList items        -> all (all isSimpleListItem . snd) items-       _                           -> False+  contents <- local (\st -> st{ stBlockQuoteLevel = 0 })+               (mapM (blockListToDokuWiki opts) items)+  indent <- asks stIndent+  backSlash <- asks stBackSlashLB+  let indent' = if backSlash then T.drop 2 indent else indent+  return $ bqPrefix <> indent' <> "* **" <> labelText <> "** " <>+    if useWrap+       then "<WRAP>\n" <> vcat contents <> "\n</WRAP>"+       else T.intercalate "; " contents  -- | True if list item can be handled with the simple wiki syntax.  False if---   HTML tags will be needed.+--   WRAP tags will be needed. isSimpleListItem :: [Block] -> Bool isSimpleListItem []  = True isSimpleListItem [x, CodeBlock{}] | isPlainOrPara x = True@@ -315,15 +287,21 @@   isSimpleListItem bs && all isSimpleList ys isSimpleListItem (x:ys) | isPlainOrPara x = all isSimpleList ys isSimpleListItem _ = False+--- | True if the list can be handled by simple wiki markup, False if HTML tags will be needed. +isSimpleList :: Block -> Bool+isSimpleList x =+  case x of+       BulletList items            -> all isSimpleListItem items+       OrderedList (1, _, _) items -> all isSimpleListItem items+       DefinitionList items        -> all (all isSimpleListItem . snd) items+       _                           -> False+ isPlainOrPara :: Block -> Bool isPlainOrPara (Plain _) = True isPlainOrPara (Para  _) = True isPlainOrPara _         = False -isSimpleBlockQuote :: [Block] -> Bool-isSimpleBlockQuote bs  = all isPlainOrPara bs- -- | Concatenates strings with line breaks between them. vcat :: [Text] -> Text vcat = T.intercalate "\n"@@ -353,8 +331,9 @@                  (if align' == AlignLeft || align' == AlignCenter                      then "  "                      else "")-  contents <- local (\s -> s { stBackSlashLB = True }) $-              blockListToDokuWiki opts item+  contents <- local (\s -> s { stBackSlashLB = True+                             , stBlockQuoteLevel = 0 }) $+                blockListToDokuWiki opts item   return $ mkcell contents  -- | Convert list of Pandoc block elements to DokuWiki.@@ -444,9 +423,10 @@                      DisplayMath -> "$$"                      InlineMath  -> "$" -inlineToDokuWiki _ il@(RawInline f str)+inlineToDokuWiki opts il@(RawInline f str)   | f == Format "dokuwiki" = return str-  | f == Format "html"     = return $ "<html>" <> str <> "</html>"+  | f == Format "html"+  , isEnabled Ext_raw_html opts = return $ "<html>" <> str <> "</html>"   | otherwise              = "" <$ report (InlineNotRendered il)  inlineToDokuWiki _ LineBreak = do@@ -483,7 +463,8 @@   return $ "{{" <> source <> imageDims opts attr <> txt <> "}}"  inlineToDokuWiki opts (Note contents) = do-  contents' <- blockListToDokuWiki opts contents+  contents' <- local (\st -> st{ stBlockQuoteLevel = 0 })+                 (blockListToDokuWiki opts contents)   return $ "((" <> contents' <> "))"   -- note - may not work for notes with multiple blocks 
src/Text/Pandoc/Writers/EPUB.hs view
@@ -5,7 +5,7 @@ {-# LANGUAGE ScopedTypeVariables #-} {- |    Module      : Text.Pandoc.Writers.EPUB-   Copyright   : Copyright (C) 2010-2023 John MacFarlane+   Copyright   : Copyright (C) 2010-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -466,8 +466,8 @@ pandocToEPUB version opts doc = do   let doc' = ensureValidXmlIdentifiers doc   -- handle pictures-  Pandoc meta blocks <- walkM (transformInline opts) doc' >>=-                        walkM transformBlock+  Pandoc meta blocks <- walkM (transformInline version opts) doc' >>=+                        walkM (transformBlock version)   picEntries <- mapMaybe (snd . snd) <$> gets stMediaPaths    epubSubdir <- gets stEpubSubdir@@ -522,7 +522,8 @@                   , writerWrapText = WrapAuto }    -- cover page-  (cpgEntry, cpicEntry) <- createCoverPage meta metadata opts' vars cssvars writeHtml plainTitle+  (cpgEntry, cpicEntry, mbCoverImageName) <-+    createCoverPage meta metadata opts' vars cssvars writeHtml plainTitle    -- title page   tpContent <- lift $ writeHtml opts'{@@ -642,7 +643,7 @@            [("xml:lang", epubLanguage metadata) | version == EPUB3] ++            [("unique-identifier","epub-id-1")] ++            [("prefix","ibooks: http://vocabulary.itunes.apple.com/rdf/ibooks/vocabulary-extensions-1.0/") | version == EPUB3]) $-          [ metadataElement version metadata currentTime+          [ metadataElement version metadata mbCoverImageName currentTime           , unode "manifest" $              [ unode "item" ! [("id","ncx"), ("href","toc.ncx")                               ,("media-type","application/x-dtbncx+xml")] $ ()@@ -742,6 +743,7 @@ -- | Function used during conversion from pandoc to EPUB to create the cover page. -- The first Entry list is for the cover while the second one is for the cover image. -- If no cover images are specified, empty lists will be returned.+-- The third value of the returned tuple is the cover image name. createCoverPage :: PandocMonad m =>                    Meta                    -> EPUBMetadata@@ -750,18 +752,14 @@                    -> (Bool -> Context Text)                    -> (WriterOptions -> Pandoc -> m B8.ByteString)                    -> Text-                   -> StateT EPUBState m ([Entry], [Entry])+                   -> StateT EPUBState m ([Entry], [Entry], Maybe FilePath) createCoverPage meta metadata opts' vars cssvars writeHtml plainTitle =     case epubCoverImage metadata of-        Nothing   -> return ([],[])+        Nothing   -> return ([],[], Nothing)         Just img  -> do           let fp = takeFileName img           -- retrieve cover image file-          mediaPaths <- gets (map (fst . snd) . stMediaPaths)-          coverImageName <-  -- see #4206-                if ("media/" <> fp) `elem` mediaPaths-                  then getMediaNextNewName (takeExtension fp)-                  else return fp+          coverImageName <- getMediaNextNewName (takeExtension fp) -- see #4206           -- image dimensions           imgContent <- lift $ P.readFileLazy img           (coverImageWidth, coverImageHeight) <-@@ -789,7 +787,7 @@           coverImageEntry <- mkEntry ("media/" ++ coverImageName)                                 imgContent -          return ( [ coverEntry ], [ coverImageEntry ] )+          return ( [ coverEntry ], [ coverImageEntry ], Just coverImageName )  -- | Converts the given chapters to entries using the writeHtml function -- and the various provided options@@ -924,7 +922,7 @@           subs <- catMaybes <$> mapM mkItem subsecs           let secnum' = case secNumber secinfo of                           Just num -> [Span ("", ["section-header-number"], [])-                                       [Str num] , Space]+                                       [Str num] , Str "\160"]                           Nothing -> []           let title' = secnum' <> secTitle secinfo           -- can't have <a> elements inside generated links...@@ -996,8 +994,9 @@   -- Return   mkEntry "nav.xhtml" navData -metadataElement :: EPUBVersion -> EPUBMetadata -> UTCTime -> Element-metadataElement version md currentTime =+metadataElement :: EPUBVersion -> EPUBMetadata -> Maybe FilePath -> UTCTime+                -> Element+metadataElement version md mbCoverImage currentTime =   unode "metadata" ! [("xmlns:dc","http://purl.org/dc/elements/1.1/")                      ,("xmlns:opf","http://www.idpf.org/2007/opf")] $ mdNodes   where mdNodes = identifierNodes ++ titleNodes ++ dateNodes@@ -1049,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])-            $ epubCoverImage md+            (\img -> [unode "meta" !  [("name","cover"),+                                       ("content",toId img)] $ ()])+            mbCoverImage         modifiedNodes = [ unode "meta" ! [(metaprop, "dcterms:modified")] $                showDateTimeISO8601 currentTime | version == EPUB3 ]         belongsToCollectionNodes =@@ -1142,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@@ -1198,42 +1203,47 @@   modify $ \st -> st { stMediaNextId = nextId + 1 }   return $ "file" ++ show nextId ++ ext -isHtmlFormat :: Format -> Bool-isHtmlFormat (Format "html") = True-isHtmlFormat (Format "html4") = True-isHtmlFormat (Format "html5") = True-isHtmlFormat _ = False+isHtmlFormat :: EPUBVersion -> Format -> Bool+isHtmlFormat _ (Format "html") = True+isHtmlFormat _ (Format "html4") = True+isHtmlFormat _ (Format "html5") = True+isHtmlFormat _ (Format "epub") = True+isHtmlFormat EPUB2 (Format "epub2") = True+isHtmlFormat EPUB3 (Format "epub3") = True+isHtmlFormat _ _ = False  transformBlock  :: PandocMonad m-                => Block+                => EPUBVersion+                -> Block                 -> E m Block-transformBlock (RawBlock fmt raw)-  | isHtmlFormat fmt = do+transformBlock version (RawBlock fmt raw)+  | isHtmlFormat version fmt = do   let tags = parseTags raw   tags' <- mapM transformTag tags   return $ RawBlock fmt (renderTags' tags')-transformBlock b = return b+transformBlock _ b = return b  transformInline  :: PandocMonad m-                 => WriterOptions+                 => EPUBVersion+                 -> WriterOptions                  -> Inline                  -> E m Inline-transformInline _opts (Image attr@(_,_,kvs) lab (src,tit))+transformInline _ _opts (Image attr@(_,_,kvs) lab (src,tit))   | isNothing (lookup "external" kvs) = do     newsrc <- modifyMediaRef $ T.unpack src     return $ Image attr lab ("../" <> newsrc, tit)-transformInline opts x@(Math t m)+transformInline _ opts x@(Math t m)   | WebTeX url <- writerHTMLMathMethod opts = do     newsrc <- modifyMediaRef (T.unpack (url <> urlEncode m))     let mathclass = if t == DisplayMath then "display" else "inline"     return $ Span ("",["math",mathclass],[])                 [Image nullAttr [x] ("../" <> newsrc, "")]-transformInline _opts (RawInline fmt raw)-  | isHtmlFormat fmt = do+transformInline version _opts (RawInline fmt raw)+  | isHtmlFormat version fmt = do   let tags = parseTags raw   tags' <- mapM transformTag tags   return $ RawInline fmt (renderTags' tags')-transformInline _ x = return x+transformInline _ _ x = return x  (!) :: (t -> Element) -> [(Text, Text)] -> t -> Element (!) f attrs n = add_attrs (map (\(k,v) -> Attr (unqual k) v) attrs) (f n)
src/Text/Pandoc/Writers/FB2.hs view
@@ -3,7 +3,7 @@ {- | Module      : Text.Pandoc.Writers.FB2 Copyright   : Copyright (C) 2011-2012 Sergey Astanin-                            2012-2023 John MacFarlane+                            2012-2024 John MacFarlane License     : GNU GPL, version 2 or above  Maintainer  : John MacFarlane
src/Text/Pandoc/Writers/GridTable.hs view
@@ -5,10 +5,10 @@  {- | Module      : Text.Pandoc.Writers.GridTable-Copyright   : © 2020-2023 Albert Krewinkel+Copyright   : © 2020-2024 Albert Krewinkel License     : GNU GPL, version 2 or above -Maintainer  : Albert Krewinkel <albert@zeitkraut.de>+Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>  Grid representation of pandoc tables. The structures in this module allow to describe 'Text.Pandoc.Definition.Table' elements without loss@@ -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
src/Text/Pandoc/Writers/HTML.hs view
@@ -8,7 +8,7 @@ {-# LANGUAGE ViewPatterns        #-} {- |    Module      : Text.Pandoc.Writers.HTML-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -34,8 +34,9 @@     ( StateT, MonadState(get), gets, modify, evalStateT ) import Control.Monad ( liftM, when, foldM, unless ) import Control.Monad.Trans ( MonadTrans(lift) )-import Data.Char (ord)-import Data.List (intercalate, intersperse, partition, delete, (\\), foldl')+import Data.Char (ord, isSpace, isAscii)+import Data.List (intercalate, intersperse, partition, delete, (\\))+import qualified Data.List as L import Data.List.NonEmpty (NonEmpty((:|))) import Data.Containers.ListUtils (nubOrd) import Data.Maybe (fromMaybe, isJust, isNothing)@@ -43,15 +44,17 @@ import Data.Text (Text) import qualified Data.Text as T import qualified Data.Text.Lazy as TL-import Network.URI (URI (..), parseURIReference)+import Network.URI (URI (..), parseURIReference, escapeURIString)+import Text.Pandoc.URI (urlEncode) 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 import Text.Pandoc.Highlighting (formatHtmlBlock, formatHtml4Block,-                 formatHtmlInline, highlight, styleToCss)+                 formatHtmlInline, highlight, styleToCss, defaultStyle) import Text.Pandoc.ImageSize import Text.Pandoc.Options import Text.Pandoc.Shared@@ -61,7 +64,6 @@ import Text.Pandoc.Writers.Math import Text.Pandoc.Writers.Shared import qualified Text.Pandoc.Writers.AnnotatedTable as Ann-import Text.Pandoc.URI (urlEncode) import Text.Pandoc.XML (escapeStringForXML, fromEntities, toEntities,                         html5Attributes, html4Attributes, rdfaAttributes) import qualified Text.Blaze.XHtml5 as H5@@ -124,7 +126,7 @@ strToHtml :: Text -> Html strToHtml t     | T.any isSpecial t =-       let !x = foldl' go mempty $ T.groupBy samegroup t+       let !x = L.foldl' go mempty $ T.groupBy samegroup t         in x     | otherwise = toHtml t   where@@ -240,21 +242,23 @@            Just cols -> render (Just cols) $ layoutMarkup body        Just tpl -> do          -- warn if empty lang-         when (isNothing (getField "lang" context :: Maybe Text)) $+         when (isNothing (getField "lang" context :: Maybe Text) &&+               hasVariable "lang" tpl) $            report NoLangSpecified-         -- check for empty pagetitle          (context' :: Context Text) <-+            -- check for empty pagetitle             case getField "pagetitle" context of                  Just (s :: Text) | not (T.null s) -> return context-                 _ -> do-                   let fallback = T.pack $-                         case lookupContext "sourcefile"-                                   (writerVariables opts) of-                           Nothing    -> "Untitled"-                           Just []    -> "Untitled"-                           Just (x:_) -> takeBaseName $ T.unpack x-                   report $ NoTitleElement fallback-                   return $ resetField "pagetitle" (literal fallback) context+                 _ | hasVariable "pagetitle" tpl -> do+                       let fallback = T.pack $+                             case lookupContext "sourcefile"+                                       (writerVariables opts) of+                               Nothing    -> "Untitled"+                               Just []    -> "Untitled"+                               Just (x:_) -> takeBaseName $ T.unpack x+                       report $ NoTitleElement fallback+                       return $ resetField "pagetitle" (literal fallback) context+                   | otherwise -> return context          return $ render colwidth $ renderTemplate tpl              (defField "body" (layoutMarkup body) context') @@ -289,8 +293,8 @@                           lookupMetaString "description" meta   slideVariant <- gets stSlideVariant   abstractTitle <- translateTerm Abstract-  let sects = adjustNumbers opts $-              makeSections (writerNumberSections opts) Nothing $+  let sects = makeSectionsWithOffsets+                (writerNumberOffset opts) (writerNumberSections opts) Nothing $               if slideVariant == NoSlides                  then blocks                  else prepSlides slideLevel blocks@@ -308,12 +312,14 @@         modify (\st' -> st'{ stNotes = mempty, stEmittedNotes = stEmittedNotes st' + length (stNotes st') })         return notes   st <- get+  let html5 = stHtml5 st   let thebody = blocks' >> notes   let math = layoutMarkup $ case writerHTMLMathMethod opts of         MathJax url           | slideVariant /= RevealJsSlides ->           -- mathjax is handled via a special plugin in revealjs-            H.script ! A.src (toValue url)+            H.script ! A.defer mempty+                    ! A.src (toValue $ toURI html5 url)                     ! A.type_ "text/javascript"                     $ case slideVariant of                             SlideousSlides ->@@ -323,7 +329,7 @@         KaTeX url -> do           H.script !             A.defer mempty !-            A.src (toValue $ url <> "katex.min.js") $ mempty+            A.src (toValue $ toURI html5 $ url <> "katex.min.js") $ mempty           nl           let katexFlushLeft =                 case lookupContext "classoption" metadata of@@ -346,16 +352,20 @@             ]           nl           H.link ! A.rel "stylesheet" !-            A.href (toValue $ url <> "katex.min.css")+            A.href (toValue $ toURI html5 url <> "katex.min.css")          _ -> mempty   let mCss :: Maybe [Text] = lookupContext "css" metadata   let context :: Context Text       context =   (if stHighlighting st-                      then case writerHighlightStyle opts of-                                Just sty -> defField "highlighting-css"-                                            (literal $ T.pack $ styleToCss sty)-                                Nothing  -> id+                      then case writerHighlightMethod opts of+                             Skylighting sty ->+                               defField "highlighting-css"+                                 (literal $ T.pack $ styleToCss sty)+                             DefaultHighlighting ->+                               defField "highlighting-css"+                                 (literal $ T.pack $ styleToCss defaultStyle)+                             _  -> id                       else id) .                   (if stCsl st                       then defField "csl-css" True .@@ -423,7 +433,21 @@                          defField "transitionSpeed" ("default" :: Doc Text) .                          defField "backgroundTransition" ("fade" :: Doc Text) .                          defField "viewDistance" ("3" :: Doc Text) .-                         defField "mobileViewDistance" ("2" :: Doc Text)+                         defField "mobileViewDistance" ("2" :: Doc Text) .+                         (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) .+                         (case writerHighlightMethod opts of+                            IdiomaticHighlighting+                             | slideVariant == RevealJsSlides ->+                              defField "highlight-js" True .+                              defField "highlightjs-theme" ("monokai" :: Doc Text)+                            _ -> id)                       else id) .                   defField "document-css" (isNothing mCss && slideVariant == NoSlides) .                   defField "quotes" (stQuotes st) .@@ -443,8 +467,10 @@                   defField "slidy-url"                     ("https://www.w3.org/Talks/Tools/Slidy2" :: Doc Text) .                   defField "slideous-url" ("slideous" :: Doc Text) .-                  defField "revealjs-url" ("https://unpkg.com/reveal.js@^4/" :: Doc Text) $+                  defField "revealjs-url" ("https://unpkg.com/reveal.js@^5" :: Doc Text) $                   defField "s5-url" ("s5/default" :: Doc Text) .+                  defField "table-caption-below"+                     (writerTableCaptionPosition opts == CaptionBelow) .                   defField "html5" (stHtml5 st) $                   metadata   return (thebody, context)@@ -482,21 +508,13 @@         => WriterOptions -> [Html] -> StateT WriterState m Html defList opts items = toList H.dl opts (items ++ [nl]) -isTaskListItem :: [Block] -> Bool-isTaskListItem (Plain (Str "☐":Space:_):_) = True-isTaskListItem (Plain (Str "☒":Space:_):_) = True-isTaskListItem (Para  (Str "☐":Space:_):_) = True-isTaskListItem (Para  (Str "☒":Space:_):_) = True-isTaskListItem _                           = False- listItemToHtml :: PandocMonad m                => WriterOptions -> [Block] -> StateT WriterState m Html-listItemToHtml opts bls-  | Plain (Str "☐":Space:is) : bs <- bls = taskListItem False id  is bs-  | Plain (Str "☒":Space:is) : bs <- bls = taskListItem True  id  is bs-  | Para  (Str "☐":Space:is) : bs <- bls = taskListItem False H.p is bs-  | Para  (Str "☒":Space:is) : bs <- bls = taskListItem True  H.p is bs-  | otherwise = blockListToHtml opts bls+listItemToHtml opts bls =+  case toTaskListItem bls of+    Just (checked, (Para is:bs)) -> taskListItem checked H.p is bs+    Just (checked, (Plain is:bs)) -> taskListItem checked id is bs+    _ -> blockListToHtml opts bls   where     taskListItem checked constr is bs = do       let checkbox  = if checked@@ -560,7 +578,7 @@         | html5         , refLocation == EndOfDocument         -- Note: we need a section for a new slide in slide formats.-                = H5.section ! A5.id (fromString idName)+                = H5.section ! prefixedId opts (fromString idName)                              ! A5.class_ className                              ! A5.role "doc-endnotes"                              $ x@@ -601,12 +619,14 @@ obfuscateLink :: PandocMonad m               => WriterOptions -> Attr -> Html -> Text               -> StateT WriterState m Html-obfuscateLink opts attr txt s | writerEmailObfuscation opts == NoObfuscation =-  addAttrs opts attr $ H.a ! A.href (toValue s) $ txt-obfuscateLink opts attr (TL.toStrict . renderHtml -> txt) s =+obfuscateLink opts attr txt s | writerEmailObfuscation opts == NoObfuscation = do+  html5 <- gets stHtml5+  addAttrs opts attr $ H.a ! A.href (toValue $ toURI html5 s) $ txt+obfuscateLink opts attr (TL.toStrict . renderHtml -> txt) s = do+  html5 <- gets stHtml5   let meth = writerEmailObfuscation opts-      s' = T.toLower (T.take 7 s) <> T.drop 7 s-  in  case parseMailto s' of+  let s' = T.toLower (T.take 7 s) <> T.drop 7 s+  case parseMailto s' of         (Just (name', domain)) ->           let domain'  = T.replace "." " dot " domain               at'      = obfuscateChar '@'@@ -634,7 +654,8 @@                      linkText  <> "+'<\\/'+'a'+'>');\n// -->\n")) >>                      H.noscript (preEscapedText $ obfuscateString altText)                 _ -> throwError $ PandocSomeError $ "Unknown obfuscation method: " <> tshow meth-        _ -> addAttrs opts attr $ H.a ! A.href (toValue s) $ toHtml txt  -- malformed email+        _ -> addAttrs opts attr $ H.a ! A.href (toValue $ toURI html5 s)+                                      $ toHtml txt  -- malformed email  -- | Obfuscate character as entity. obfuscateChar :: Char -> Text@@ -664,7 +685,7 @@  addAttrs :: PandocMonad m          => WriterOptions -> Attr -> Html -> StateT WriterState m Html-addAttrs opts attr h = foldl' (!) h <$> attrsToHtml opts attr+addAttrs opts attr h = L.foldl' (!) h <$> attrsToHtml opts attr  toAttrs :: PandocMonad m         => [(Text, Text)] -> StateT WriterState m [Attribute]@@ -682,7 +703,8 @@   addAttr html5 mbEpubVersion x y     | T.null x = id  -- see #7546     | html5-      = if x `Set.member` (html5Attributes <> rdfaAttributes)+      = if (x `Set.member` (html5Attributes <> rdfaAttributes)+            && x /= "label") -- #10048              || T.any (== ':') x -- e.g. epub: namespace              || "data-" `T.isPrefixOf` x              || "aria-" `T.isPrefixOf` x@@ -730,30 +752,6 @@                (Just x)         -> [("style", tshow dir <> ":" <> tshow x)]                Nothing          -> [] -adjustNumbers :: WriterOptions -> [Block] -> [Block]-adjustNumbers opts doc =-  if all (==0) (writerNumberOffset opts)-     then doc-     else walk go doc-  where-   go (Div (ident,"section":classes,kvs) lst@(Header level _ _ : _)) =-     Div (ident,"section":classes,map (fixnum level) kvs) lst-   go (Header level (ident,classes,kvs) lst) =-     Header level (ident,classes,map (fixnum level) kvs) lst-   go x = x-   fixnum level ("number",num) = ("number",-                               showSecNum $ zipWith (+)-                               (writerNumberOffset opts ++ repeat 0)-                               (padTo level $-                                map (fromMaybe 0 . safeRead) $-                                T.split (=='.') num))-   fixnum _ x = x-   padTo n xs =-     case n - length xs of-       x | x > 0 -> replicate x 0 ++ xs-         | otherwise -> xs-   showSecNum = T.intercalate "." . map tshow- blockToHtmlInner :: PandocMonad m => WriterOptions -> Block -> StateT WriterState m Html blockToHtmlInner opts (Plain lst) = inlineListToHtml opts lst blockToHtmlInner opts (Para lst) = do@@ -807,8 +805,8 @@         if titleSlide            -- title slides have no content of their own            then let (as, bs) = break isSec xs-                in  (breakOnPauses as, bs)-           else ([], breakOnPauses xs)+                in  (walk breakOnPauses as, bs)+           else ([], walk breakOnPauses xs)   let secttag  = if html5                     then H5.section                     else H.div@@ -867,6 +865,11 @@                      if null innerSecs                         then mempty                         else nl <> innerContents+blockToHtmlInner opts (Div (ident, classes, kvs) [b])+  | Just "1" <- lookup "wrapper" kvs+    -- unwrap "wrapper" div, putting attr on child+  = blockToHtmlInner opts b >>=+      addAttrs opts (ident, classes, [(k,v) | (k,v) <- kvs, k /= "wrapper"]) blockToHtmlInner opts (Div attr@(ident, classes, kvs') bs) = do   html5 <- gets stHtml5   slideVariant <- gets stSlideVariant@@ -884,12 +887,17 @@             [("role", "listitem") | isCslBibEntry && html5]   let speakerNotes = "notes" `elem` classes   -- we don't want incremental output inside speaker notes, see #1394-  let opts' = if | speakerNotes -> opts{ writerIncremental = False }-                 | "incremental" `elem` classes -> opts{ writerIncremental = True }-                 | "nonincremental" `elem` classes -> opts{ writerIncremental = False }-                 | otherwise -> opts+  let (opts', isIncrDiv) =+        if | speakerNotes ->+             (opts{ writerIncremental = False }, False)+           | "incremental" `elem` classes ->+             (opts{ writerIncremental = True }, True)+           | "nonincremental" `elem` classes ->+             (opts{ writerIncremental = False }, True)+           | otherwise ->+             (opts, False)       -- we remove "incremental" and "nonincremental" if we're in a-      -- slide presentaiton format.+      -- slide presentation format.       classes' = case slideVariant of         NoSlides -> classes         _ -> filter (\k -> k /= "incremental" && k /= "nonincremental") classes@@ -908,18 +916,22 @@   let (divtag, classes'') = if html5 && "section" `elem` classes'                             then (H5.section, filter (/= "section") classes')                             else (H.div, classes')-  if speakerNotes-     then case slideVariant of-               RevealJsSlides -> addAttrs opts' attr $-                           H5.aside contents'-               DZSlides       -> do-                 t <- addAttrs opts' attr $-                             H5.div contents'-                 return $ t ! A5.role "note"-               NoSlides       -> addAttrs opts' attr $-                           H.div contents'-               _              -> return mempty-     else addAttrs opts (ident, classes'', kvs) $+  if | isIncrDiv && (ident, classes'', kvs) == nullAttr ->+         -- Unwrap divs that only have (non)increment information+         pure contents+     | speakerNotes ->+         case slideVariant of+              RevealJsSlides -> addAttrs opts' attr $+                          H5.aside contents'+              DZSlides       -> do+                t <- addAttrs opts' attr $+                            H5.div contents'+                return $ t ! A5.role "note"+              NoSlides       -> addAttrs opts' attr $+                          H.div contents'+              _              -> return mempty+     | otherwise ->+          addAttrs opts (ident, classes'', kvs) $               divtag contents' blockToHtmlInner opts (RawBlock f str) = do   ishtml <- isRawHtml f@@ -939,6 +951,7 @@   return $ if html5 then H5.hr else H.hr blockToHtmlInner opts (CodeBlock (id',classes,keyvals) rawCode) = do   html5 <- gets stHtml5+  slideVariant <- gets stSlideVariant   id'' <- if T.null id'              then do                modify $ \st -> st{ stCodeBlockNum = stCodeBlockNum st + 1 }@@ -956,21 +969,37 @@       adjCode  = if tolhs                     then T.unlines . map ("> " <>) . T.lines $ rawCode                     else rawCode-      hlCode   = if isJust (writerHighlightStyle opts)-                    then highlight (writerSyntaxMap opts)-                         (if html5 then formatHtmlBlock else formatHtml4Block)-                            (id'',classes',keyvals) adjCode-                    else Left ""-  case hlCode of-         Left msg -> do-           unless (T.null msg) $-             report $ CouldNotHighlight msg-           addAttrs opts (id',classes,keyvals)-             $ H.pre $ H.code $ toHtml adjCode-         Right h -> modify (\st -> st{ stHighlighting = True }) >>-                    -- we set writerIdentifierPrefix to "" since id'' already-                    -- includes it:-                    addAttrs opts{writerIdentifierPrefix = ""} (id'',[],keyvals) h+      isIdiomaticRevealJs = slideVariant == RevealJsSlides &&+                            writerHighlightMethod opts == IdiomaticHighlighting+  if isIdiomaticRevealJs+     then do+       -- For idiomatic reveal.js highlighting, put attributes on <code>+       -- with language- prefix, and let highlight.js do the highlighting.+       modify (\st -> st{ stHighlighting = True })+       let (langClasses, otherClasses) = case classes' of+             (lang:rest) -> (["language-" <> lang], rest)+             []          -> ([], [])+           codeAttrs = (id', langClasses ++ otherClasses, keyvals)+       codeTag <- addAttrs opts codeAttrs $ H.code $ toHtml adjCode+       return $ H.pre codeTag+     else do+       let highlighted = highlight (writerSyntaxMap opts)+                           (if html5 then formatHtmlBlock else formatHtml4Block)+                           (id'',classes',keyvals) adjCode+           hlCode   = case writerHighlightMethod opts of+                        Skylighting _ -> highlighted+                        DefaultHighlighting -> highlighted+                        _ -> Left ""+       case hlCode of+              Left msg -> do+                unless (T.null msg) $+                  report $ CouldNotHighlight msg+                addAttrs opts (id',classes,keyvals)+                  $ H.pre $ H.code $ toHtml adjCode+              Right h -> modify (\st -> st{ stHighlighting = True }) >>+                         -- we set writerIdentifierPrefix to "" since id'' already+                         -- includes it:+                         addAttrs opts{writerIdentifierPrefix = ""} (id'',[],keyvals) h blockToHtmlInner opts (BlockQuote blocks) = do   -- in S5, treat list in blockquote specially   -- if default is incremental, make it nonincremental;@@ -1019,8 +1048,7 @@               _ -> H.p  contents' blockToHtmlInner opts (BulletList lst) = do   contents <- mapM (listItemToHtml opts) lst-  let isTaskList = not (null lst) && all isTaskListItem lst-  (if isTaskList then (! A.class_ "task-list") else id) <$>+  (if isJust (mapM toTaskListItem lst) then (! A.class_ "task-list") else id) <$>     unordList opts contents blockToHtmlInner opts (OrderedList (startnum, numstyle, _) lst) = do   contents <- mapM (listItemToHtml opts) lst@@ -1044,7 +1072,7 @@                                    numstyle']                    else [])   l <- ordList opts contents-  return $ foldl' (!) l attribs+  return $ L.foldl' (!) l attribs blockToHtmlInner opts (DefinitionList lst) = do   contents <- mapM (\(term, defs) ->                   do term' <- liftM H.dt $ inlineListToHtml opts term@@ -1060,24 +1088,26 @@    figAttrs <- attrsToHtml opts attrs   contents <- blockListToHtml opts body-  figCaption <- if null captBody-                then return mempty-                else do-                  captCont <- blockListToHtml opts captBody-                  return . mconcat $+  captCont <- blockListToHtml opts captBody+  let figCaption = mconcat $                     if html5                     then let fcattr = if captionIsAlt captBody body                                       then H5.customAttribute                                            (textTag "aria-hidden")                                            (toValue @Text "true")                                       else mempty-                         in [ H5.figcaption ! fcattr $ captCont, nl ]-                    else [ (H.div ! A.class_ "figcaption") captCont, nl ]+                         in [ H5.figcaption ! fcattr $ captCont ]+                    else [ (H.div ! A.class_ "figcaption") captCont ]+  let innards = mconcat $+                if null captBody+                   then [nl, contents, nl]+                   else case writerFigureCaptionPosition opts of+                         CaptionAbove -> [nl, figCaption, nl, contents, nl]+                         CaptionBelow -> [nl, contents, nl, figCaption, nl]   return $     if html5-    then foldl (!) H5.figure figAttrs $ mconcat [nl, contents, nl, figCaption]-    else foldl (!) H.div (A.class_ "float" : figAttrs) $ mconcat-           [nl, contents, nl, figCaption]+    then foldl (!) H5.figure figAttrs innards+    else foldl (!) H.div (A.class_ "float" : figAttrs) innards  where   captionIsAlt capt [Plain [Image (_, _, kv) desc _]] =     let alt = fromMaybe (stringify desc) $ lookup "alt" kv@@ -1272,19 +1302,13 @@                => WriterOptions                -> TableRow                -> StateT WriterState m Html-tableRowToHtml opts (TableRow tblpart attr rownum rowhead rowbody) = do-  let rowclass = case rownum of-        Ann.RowNumber x | x `rem` 2 == 1   -> "odd"-        _               | tblpart /= Thead -> "even"-        _                                  -> "header"-  let attr' = case attr of-                (id', classes, rest) -> (id', rowclass:classes, rest)+tableRowToHtml opts (TableRow tblpart attr _rownum rowhead rowbody) = do   let celltype = case tblpart of                    Thead -> HeaderCell                    _     -> BodyCell   headcells <- mapM (cellToHtml opts HeaderCell) rowhead   bodycells <- mapM (cellToHtml opts celltype) rowbody-  rowHtml <- addAttrs opts attr' $ H.tr $ do+  rowHtml <- addAttrs opts attr $ H.tr $ do     nl     mconcat headcells     mconcat bodycells@@ -1415,7 +1439,7 @@                                = Just (t . H.u, cs)                              | otherwise                                = Just (t, c:cs)-                            spanLikeTags = foldl' go Nothing+                            spanLikeTags = L.foldl' go Nothing                         in case spanLikeTags classes of                             Just (tag, cs) -> do                               h <- inlineListToHtml opts ils@@ -1455,11 +1479,12 @@                                modify $ \st -> st{ stHighlighting = True }                                addAttrs opts (ids,[],kvs) $                                  fromMaybe id sampOrVar h-                        where hlCode = if isJust (writerHighlightStyle opts)-                                          then highlight-                                                 (writerSyntaxMap opts)-                                                 formatHtmlInline attr str-                                          else Left ""+                        where hlCode = case writerHighlightMethod opts of+                                          Skylighting _ -> highlighted+                                          DefaultHighlighting -> highlighted+                                          _ -> Left ""+                              highlighted =  highlight (writerSyntaxMap opts)+                                                       formatHtmlInline attr str                               (sampOrVar,cs')                                 | "sample" `elem` cs =                                       (Just H.samp,"sample" `delete` cs)@@ -1503,8 +1528,7 @@                            InlineMath  -> "\\textstyle "                            DisplayMath -> "\\displaystyle "               return $ imtag ! A.style "vertical-align:middle"-                             ! A.src (toValue . (url <>) .-                                 urlEncode $ s <> str')+                             ! A.src (toValue . (url <>) . urlEncode $ s <> str')                              ! A.alt (toValue str')                              ! A.title (toValue str')                              ! A.class_ mathClass@@ -1555,6 +1579,9 @@              _ -> do report $ InlineNotRendered inline                      return mempty     (Link attr txt (s,_)) | "mailto:" `T.isPrefixOf` s -> do+                        -- We need to remove links from link text, because an+                        -- <a> element is not allowed inside another <a>+                        -- element.                         linkText <- inlineListToHtml opts (removeLinks txt)                         obfuscateLink opts attr linkText s     (Link (ident,classes,kvs) txt (s,tit)) -> do@@ -1566,7 +1593,8 @@                                                              else writerIdentifierPrefix opts                                              in  "#" <> prefix <> xs                                    _ -> s-                        let link = H.a ! A.href (toValue s') $ linkText+                        let link = H.a ! A.href (toValue $ toURI html5 s')+                                       $ linkText                         link' <- addAttrs opts (ident, classes, kvs) link                         return $ if T.null tit                                     then link'@@ -1581,7 +1609,7 @@                               -- reveal.js uses data-src for lazy loading                               (if isReveal                                   then customAttribute "data-src" $ toValue s-                                  else A.src $ toValue s) :+                                  else A.src $ toValue $ toURI html5 s) :                               [A.title $ toValue tit | not (T.null tit)] ++                               attrs                             imageTag = (if html5 then H5.img else H.img@@ -1592,17 +1620,23 @@                               let linkTxt = if null txt                                             then fallbackTxt                                             else alternate-                              in (tg $ H.a ! A.href (toValue s) $ toHtml linkTxt+                              in (tg $ H.a ! A.href (toValue $ toURI html5 s)+                                           $ toHtml linkTxt                                  , [A5.controls ""] )                             s' = fromMaybe s $ T.stripSuffix ".gz" s-                            normSrc = maybe (T.unpack s) uriPath (parseURIReference $ T.unpack s')-                            (tag, specAttrs) = case mediaCategory normSrc of+                            category =+                              if "data:" `T.isPrefixOf` s+                                 then Just . T.takeWhile (/= '/') . T.drop 5 $ s+                                 else case parseURIReference (T.unpack s') of+                                        Just u -> mediaCategory $ uriPath u+                                        Nothing -> mediaCategory (T.unpack s)+                            (tag, specAttrs) = case category of                               Just "image" -> imageTag                               Just "video" -> mediaTag H5.video "Video"                               Just "audio" -> mediaTag H5.audio "Audio"                               Just _       -> (H5.embed, [])                               _            -> imageTag-                        return $ foldl' (!) tag $ attributes ++ specAttrs+                        return $ L.foldl' (!) tag $ attributes ++ specAttrs                         -- note:  null title included, as in Markdown.pl     (Note contents) -> do                         notes <- gets stNotes@@ -1615,7 +1649,7 @@                         modify $ \st -> st {stNotes = htmlContents:notes}                         slideVariant <- gets stSlideVariant                         let revealSlash = T.pack ['/' | slideVariant == RevealJsSlides]-                        let link = H.a ! A.href (toValue $ "#" <>+                        let link = H.a ! A.href (toValue $ toURI html5 $ "#" <>                                          revealSlash <>                                          writerIdentifierPrefix opts <> "fn" <> ref)                                        ! A.class_ "footnote-ref"@@ -1630,7 +1664,7 @@                                       _          -> link     (Cite cits il)-> do contents <- inlineListToHtml opts                                       (if html5-                                          then walk addRoleToLink il+                                          then walk addBibliorefRole il                                           else il)                         let citationIds = T.unwords $ map citationId cits                         let result = H.span ! A.class_ "citation" $ contents@@ -1638,10 +1672,11 @@                                     then result ! customAttribute "data-cites" (toValue citationIds)                                     else result -addRoleToLink :: Inline -> Inline-addRoleToLink (Link (id',classes,kvs) ils (src,tit)) =+addBibliorefRole :: Inline -> Inline+addBibliorefRole (Link (id',classes,kvs) ils (src,tit))+   | "#ref-" `T.isPrefixOf` src =   Link (id',classes,("role","doc-biblioref"):kvs) ils (src,tit)-addRoleToLink x = x+addBibliorefRole x = x  blockListToNote :: PandocMonad m                 => WriterOptions -> Text -> [Block]@@ -1679,14 +1714,16 @@       let kvs = [("role","doc-backlink") | html5]       let backlink = Link ("",["footnote-back"],kvs)                         [Str ref] ("#" <> "fnref" <> ref,"")-      let blocks' =-           case blocks of-             (Para ils : rest) ->-                Para (backlink : Str "." : Space : ils) : rest-             (Plain ils : rest) ->-                Plain (backlink : Str "." : Space : ils) : rest-             _ -> Para [backlink , Str "."] : blocks-      contents <- blockListToHtml opts blocks'+      let addBacklinkInlines bs+             | epubv == EPUB3 = bs+             | otherwise =+                 case bs of+                   (Para ils : rest) ->+                     Para (backlink : Str "." : Space : ils) : rest+                   (Plain ils : rest) ->+                     Plain (backlink : Str "." : Space : ils) : rest+                   _ -> Para [backlink , Str "."] : blocks+      contents <- blockListToHtml opts (addBacklinkInlines blocks)       let noteItem = (if epubv == EPUB3                          then H5.aside ! customAttribute "epub:type" "footnote" ! customAttribute "role" "doc-footnote"                          else H.div) ! prefixedId opts ("fn" <> ref)@@ -1758,20 +1795,40 @@ isRawHtml :: PandocMonad m => Format -> StateT WriterState m Bool isRawHtml f = do   html5 <- gets stHtml5+  epubVersion <- gets stEPUBVersion   return $ f == Format "html" ||            ((html5 && f == Format "html5") || f == Format "html4") ||+           isEpubFormat epubVersion f ||            isSlideVariant f +-- | Check to see if Format matches with an EPUB variant+isEpubFormat :: Maybe EPUBVersion -> Format -> Bool+isEpubFormat Nothing _ = False+isEpubFormat (Just EPUB2) f =+  f == Format "epub" || f == Format "epub2"+isEpubFormat (Just EPUB3) f =+  f == Format "epub" || f == Format "epub3"+ -- | Check to see if Format matches with an HTML slide variant isSlideVariant :: Format -> Bool isSlideVariant f = f `elem` [Format "s5", Format "slidy", Format "slideous",                              Format "dzslides", Format "revealjs"] +toURI :: Bool -> Text -> Text+toURI isHtml5 t = if isHtml5 then t else escapeURI t+ where+   escapeURI = T.pack . escapeURIString (not . needsEscaping) . T.unpack+   needsEscaping c = isSpace c || T.any (== c) "<>|\"{}[]^`" || not (isAscii c) --- We need to remove links from link text, because an <a> element is--- not allowed inside another <a> element.-removeLinks :: [Inline] -> [Inline]-removeLinks = walk go+hasVariable :: Text -> DT.Template a -> Bool+hasVariable var = checkVar  where-  go (Link attr ils _) = Span attr ils-  go x = x+   matches v' = T.intercalate "." (DT.varParts v') == var+   checkVar (DT.Interpolate v) = matches v+   checkVar (DT.Conditional v t1 t2) = matches v || checkVar t1 || checkVar t2+   checkVar (DT.Iterate v t1 t2) = matches v || checkVar t1 || checkVar t2+   checkVar (DT.Nested t) = checkVar t+   checkVar (DT.Partial _ t) = checkVar t+   checkVar (DT.Concat t1 t2) = checkVar t1 || checkVar t2+   checkVar (DT.Literal _) = False+   checkVar DT.Empty = False
src/Text/Pandoc/Writers/Haddock.hs view
@@ -125,14 +125,12 @@ blockToHaddock opts (BlockQuote blocks) =   blockListToHaddock opts blocks blockToHaddock opts (Table _ blkCapt specs thead tbody tfoot) = do-  let (caption, aligns, widths, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot-  caption' <- inlineListToHaddock opts caption+  let Caption _ caption = blkCapt+  caption' <- blockListToHaddock opts caption   let caption'' = if null caption                      then empty                      else blankline <> caption' <> blankline-  tbl <- gridTable opts blockListToHaddock-              (all null headers) (map (const AlignDefault) aligns)-                widths headers rows+  tbl <- gridTable opts blockListToHaddock specs thead tbody tfoot   return $ (tbl $$ blankline $$ caption'') $$ blankline blockToHaddock opts (BulletList items) = do   contents <- mapM (bulletListItemToHaddock opts) items
src/Text/Pandoc/Writers/ICML.hs view
@@ -30,7 +30,7 @@ import Text.Pandoc.ImageSize import Text.Pandoc.Logging import Text.Pandoc.Options-import Text.DocLayout+import Text.DocLayout hiding (link) import Text.Pandoc.Shared import Text.Pandoc.URI (isURI) import Text.Pandoc.Templates (renderTemplate)@@ -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@@ -345,9 +358,9 @@                      then "0"                      else "1"       nrRows = length rows-      nrCols = if null rows-                  then 0-                  else length $ head rows+      nrCols = case rows of+                   [] -> 0+                   (r:_) -> length r       rowsToICML [] _ = return empty       rowsToICML (col:rest) rowNr =         liftM2 ($$) (colsToICML col aligns rowNr (0::Int)) $ rowsToICML rest (rowNr+1)@@ -430,14 +443,15 @@                then firstListItemName:style                else style       stl' = makeNumbStart attribs ++ stl-  in  if length item > 1-         then do-           let insertTab (Para lst) = blockToICML opts (subListParName:style) $ Para $ Str "\t":lst-               insertTab block      = blockToICML opts style block-           f <- blockToICML opts stl' $ head item-           r <- mapM insertTab $ tail item-           return $ intersperseBrs (f : r)-         else blocksToICML opts stl' item+  in  case item of+          (i:rest@(_:_)) -> do+             let insertTab (Para lst) = blockToICML opts (subListParName:style)+                                         (Para (Str "\t":lst))+                 insertTab block      = blockToICML opts style block+             f <- blockToICML opts stl' i+             r <- mapM insertTab rest+             return $ intersperseBrs (f : r)+          _ -> blocksToICML opts stl' item  definitionListItemToICML :: PandocMonad m => WriterOptions -> Style -> ([Inline],[[Block]]) -> WS m (Doc Text) definitionListItemToICML opts style (term,defs) = do@@ -484,9 +498,9 @@ inlineToICML opts style ident (Link _ lst (url, title)) = do   content <- inlinesToICML opts (linkName:style) ident lst   state $ \st ->-            let link_id = if null $ links st-                            then 1::Int-                            else 1 + fst (head $ links st)+            let link_id = case links st of+                              [] -> 1 :: Int+                              ((n,_):_) -> 1 + n                 newst = st{ links = (link_id, url):links st }                 cont  = inTags True "HyperlinkTextSource"                          [("Self","htss-"<>tshow link_id), ("Name",title), ("Hidden","false")] content@@ -545,11 +559,12 @@       attrs' =  if firstListItemName `elem` style                    then let ats = attrs : [("NumberingContinue", "false")]                             begins = filter (Text.isPrefixOf beginsWithName) style-                        in  if null begins-                               then ats-                               else let i = fromMaybe "" $ Text.stripPrefix beginsWithName-                                                         $ head begins-                                    in  ("NumberingStartAt", i) : ats+                        in  case begins of+                                [] -> ats+                                (b:_) ->+                                   let i = fromMaybe ""+                                             (Text.stripPrefix beginsWithName b)+                                   in  ("NumberingStartAt", i) : ats                    else [attrs]   in  do       content <- inlinesToICML opts [] ident lst@@ -599,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@@ -645,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+    })
src/Text/Pandoc/Writers/Ipynb.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE ScopedTypeVariables #-} {- |    Module      : Text.Pandoc.Writers.Ipynb-   Copyright   : Copyright (C) 2019-2023 John MacFarlane+   Copyright   : Copyright (C) 2019-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>
src/Text/Pandoc/Writers/JATS.hs view
@@ -4,7 +4,7 @@ {-# LANGUAGE ViewPatterns        #-} {- |    Module      : Text.Pandoc.Writers.JATS-   Copyright   : 2017-2023 John MacFarlane+   Copyright   : 2017-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -27,7 +27,7 @@ import Control.Monad.State import Data.Generics (everywhere, mkT) import qualified Data.Map as M-import Data.Maybe (fromMaybe, listToMaybe)+import Data.Maybe (fromMaybe, listToMaybe, isNothing) import Data.Time (toGregorian, Day, parseTimeM, defaultTimeLocale, formatTime) import qualified Data.Text as T import Data.Text (Text)@@ -43,7 +43,7 @@ import Text.Pandoc.Shared import Text.Pandoc.URI import Text.Pandoc.Templates (renderTemplate)-import Text.DocTemplates (Context(..), Val(..))+import Text.DocTemplates (Context(..), Val(..), toVal) import Text.Pandoc.Writers.JATS.References (referencesToJATS) import Text.Pandoc.Writers.JATS.Table (tableToJATS) import Text.Pandoc.Writers.JATS.Types@@ -54,6 +54,54 @@ import qualified Text.Pandoc.Writers.AnnotatedTable as Ann import qualified Text.XML.Light as Xml +-- | Default human-readable names for roles in the Contributor Role+-- Taxonomy (CRediT). This is useful for generating JATS that annotate+-- contributor roles+creditNames :: M.Map Text Text+creditNames = M.fromList [+    ("conceptualization", "Conceptualization"),+    ("data-curation", "Data curation"),+    ("formal-analysis", "Formal analysis"),+    ("funding-acquisition", "Funding acquisition"),+    ("investigation", "Investigation"),+    ("methodology", "Methodology"),+    ("project-administration", "Project administration"),+    ("resources", "Resources"),+    ("software", "Software"),+    ("supervision", "Supervision"),+    ("validation", "Validation"),+    ("visualization", "Visualization"),+    ("writing-original-draft", "Writing – original draft"),+    ("writing-review-editing", "Writing – review &amp; editing")]++-- | Ensure every role with a `credit` key also has a `credit-name`,+-- using a default value if necessary+addCreditNames :: Context Text -> Context Text+addCreditNames context =+  case getField "author" context of+    -- If there is an "authors" key, then we replace the existing value+    -- with one we mutate by running the addCreditNamesToAuthor helper+    -- function on each+    Just (ListVal authors) ->+      resetField "author" (map addCreditNamesToAuthor authors) context+    -- If there is no "authors" key in the context, then we don't have to do+    -- anything, and just return the context as is+    _ -> context+  where+    addCreditNamesToAuthor :: Val Text -> Val Text+    addCreditNamesToAuthor val = fromMaybe val $ do+      MapVal authorCtx <- pure val+      ListVal roles <- getField "roles" authorCtx+      return $ toVal $ resetField "roles" (map addCreditNameToRole roles) authorCtx++    addCreditNameToRole :: Val Text -> Val Text+    addCreditNameToRole val = fromMaybe val $ do+      MapVal roleCtx <- pure val+      guard $ isNothing (getField "credit-name" roleCtx :: Maybe (Val Text))+      creditId <- getField "credit" roleCtx+      creditName <- M.lookup creditId creditNames+      return $ toVal $ resetField "credit-name" creditName roleCtx+ -- | Convert a @'Pandoc'@ document to JATS (Archiving and Interchange -- Tag Set.) writeJatsArchiving :: PandocMonad m => WriterOptions -> Pandoc -> m Text@@ -159,6 +207,7 @@                (lookupMetaInlines "title" meta)   let context = defField "body" main               $ defField "back" back+              $ addCreditNames               $ resetField "title" title'               $ resetField "date" date               $ defField "mathml" (case writerHTMLMathMethod opts of@@ -311,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'@@ -390,12 +449,36 @@   capt <- if null longcapt           then pure empty           else inTagsSimple "caption" <$> blocksToJATS opts longcapt-  figbod <- blocksToJATS opts $ walk unsetAltIfDupl body-  let figattr = [("id", escapeNCName ident) | not (T.null ident)] ++-                [(k,v) | (k,v) <- kvs-                       , k `elem` [ "fig-type", "orientation"-                                  , "position", "specific-use"]]-  return $ inTags True "fig" figattr $ capt $$ figbod++  -- We handle the element specially if it's a figure with subfigures, i.e., if+  -- all immediate children are figures themselves.+  let hasSubfigures = all (\case { Figure{} -> True; _ -> False}) body+      needsWrapping = if hasSubfigures+                      then (const False)+                      else \case+                        -- Wrap all figure content elements, except for those+                        -- allowed as direct subelements.+                        BlockQuote{}    -> False+                        CodeBlock{}     -> False+                        Para{}          -> False+                        Plain [Image{}] -> False+                        Plain [Math{}]  -> False+                        Table{}         -> False+                        _               -> True++  children <- wrappedBlocksToJATS needsWrapping opts $ walk unsetAltIfDupl body+  let (tag, allowedAttributes) =+        if hasSubfigures+        then ( "fig-group"+             , ["content-type", "orientation", "position", "specific-use"]+             )+        else ("fig"+             , ["fig-type", "orientation", "position", "specific-use"]+             )+  let xmlattr =  [("id", escapeNCName ident) | not (T.null ident)] +++                 [(k,v) | (k,v) <- kvs+                        , k `elem` allowedAttributes]+  return $ inTags True tag xmlattr $ capt $$ children  -- | Convert a list of inline elements to JATS. inlinesToJATS :: PandocMonad m => WriterOptions -> [Inline] -> JATS m (Doc Text)
src/Text/Pandoc/Writers/JATS/References.hs view
@@ -2,10 +2,10 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Writers.JATS.References-   Copyright   : © 2021-2023 Albert Krewinkel+   Copyright   : © 2021-2024 Albert Krewinkel    License     : GNU GPL, version 2 or above -   Maintainer  : Albert Krewinkel <tarleb@zeitkraut.de>+   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>    Stability   : alpha    Portability : portable 
src/Text/Pandoc/Writers/JATS/Table.hs view
@@ -3,10 +3,10 @@ {-# LANGUAGE TupleSections #-} {- |    Module      : Text.Pandoc.Writers.JATS.Table-   Copyright   : © 2020-2023 Albert Krewinkel+   Copyright   : © 2020-2024 Albert Krewinkel    License     : GNU GPL, version 2 or above -   Maintainer  : Albert Krewinkel <tarleb@zeitkraut.de>+   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>    Stability   : alpha    Portability : portable 
src/Text/Pandoc/Writers/JATS/Types.hs view
@@ -1,6 +1,6 @@ {- |    Module      : Text.Pandoc.Writers.JATS.Types-   Copyright   : Copyright (C) 2017-2023 John MacFarlane+   Copyright   : Copyright (C) 2017-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>
src/Text/Pandoc/Writers/Jira.hs view
@@ -3,10 +3,10 @@ {-# LANGUAGE PatternGuards #-} {- |    Module      : Text.Pandoc.Writers.Jira-   Copyright   : © 2010-2023 Albert Krewinkel, John MacFarlane+   Copyright   : © 2010-2024 Albert Krewinkel, John MacFarlane    License     : GNU GPL, version 2 or above -   Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>    Stability   : alpha    Portability : portable 
src/Text/Pandoc/Writers/LaTeX.hs view
@@ -7,7 +7,7 @@ {-# LANGUAGE ViewPatterns        #-} {- |    Module      : Text.Pandoc.Writers.LaTeX-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2025 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -30,20 +30,24 @@       liftM,       when,       unless )+import Crypto.Hash (hashWith, MD5(MD5)) import Data.Containers.ListUtils (nubOrd)-import Data.Char (isDigit)-import Data.List (intersperse, (\\))-import Data.Maybe (catMaybes, fromMaybe, isJust, mapMaybe, isNothing)+import Data.Char (isDigit, isAscii, isLetter)+import Data.List (intersperse, partition, (\\))+import qualified Data.Set as Set+import Data.Maybe (catMaybes, fromMaybe, isJust, listToMaybe, mapMaybe, isNothing) import Data.Monoid (Any (..)) import Data.Text (Text) import qualified Data.Text as T import Network.URI (unEscapeString)-import Text.DocTemplates (FromContext(lookupContext), renderTemplate)+import Text.DocTemplates (Context(..), FromContext(lookupContext), Val(..), renderTemplate)+import qualified Data.Map as M import Text.Collate.Lang (renderLang)-import Text.Pandoc.Class.PandocMonad (PandocMonad, report, toLang)+import Text.Pandoc.Class.PandocMonad (PandocMonad, getPOSIXTime, lookupEnv,+                                      report, toLang) import Text.Pandoc.Definition import Text.Pandoc.Highlighting (formatLaTeXBlock, formatLaTeXInline, highlight,-                                 styleToLaTeX)+                                 defaultStyle, styleToLaTeX) import Text.Pandoc.ImageSize import Text.Pandoc.Logging import Text.Pandoc.Options@@ -56,14 +60,18 @@ import Text.Pandoc.Writers.LaTeX.Table (tableToLaTeX) import Text.Pandoc.Writers.LaTeX.Citation (citationsToNatbib,                                            citationsToBiblatex)-import Text.Pandoc.Writers.LaTeX.Types (LW, WriterState (..), startingState)+import Text.Pandoc.Writers.LaTeX.Types (LW, WriterState (..), startingState,+                                        PdfStandard (..)) import Text.Pandoc.Writers.LaTeX.Lang (toBabel) import Text.Pandoc.Writers.LaTeX.Util (stringToLaTeX, StringContext(..),                                        toLabel, inCmd,                                        wrapDiv, hypertarget, labelFor,                                        getListingsLanguage, mbBraced) import Text.Pandoc.Writers.Shared+import qualified Data.Attoparsec.Text as A+import qualified Text.Pandoc.UTF8 as UTF8 import qualified Text.Pandoc.Writers.AnnotatedTable as Ann+import Control.Applicative ((<|>))  -- Work around problems with notes inside emphasis (see #8982) isolateBigNotes :: ([Inline] -> Inline) -> [Inline] -> [Inline]@@ -156,11 +164,15 @@                                           _               -> "article"   when (documentClass `elem` chaptersClasses) $      modify $ \s -> s{ stHasChapters = True }-  case lookupContext "csquotes" (writerVariables options) `mplus`-       (stringify <$> lookupMeta "csquotes" meta) of-     Nothing      -> return ()-     Just "false" -> return ()-     Just _       -> modify $ \s -> s{stCsquotes = True}+  let csquotes =+        case lookupContext "csquotes" (writerVariables options) of+          Just (BoolVal v) -> v+          Just (SimpleVal (Text _ t)) -> t /= ("false" :: Text)+          _ -> case stringify <$> lookupMeta "csquotes" meta of+                  Nothing -> False+                  Just "false" -> False+                  Just _ -> True+  when csquotes $ modify $ \s -> s{stCsquotes = True}   let (blocks'', lastHeader) = if writerCiteMethod options == Citeproc then                                  (blocks', [])                                else case reverse blocks' of@@ -172,8 +184,23 @@   main <- blockListToLaTeX blocks'''   biblioTitle <- inlineListToLaTeX lastHeader   st <- get-  titleMeta <- stringToLaTeX TextString $ stringify $ docTitle meta+  titleMeta <- escapeCommas <$> -- see #10501+                stringToLaTeX TextString (stringify $ docTitle meta)+  subtitleMeta <- stringToLaTeX TextString (stringify $ lookupMetaInlines "subtitle" meta)   authorsMeta <- mapM (stringToLaTeX TextString . stringify) $ docAuthors meta+  -- The trailer ID is as hash used to identify the PDF. Taking control of its+  -- value is important when aiming for reproducible PDF generation. Setting+  -- `SOURCE_DATE_EPOCH` is the traditional method used to control+  -- reproducible builds. There are no cryptographic requirements for the ID,+  -- so the 128bits (16 bytes) of MD5 are appropriate.+  reproduciblePDF <- isJust <$> lookupEnv "SOURCE_DATE_EPOCH"+  trailerID <- do+    time <- getPOSIXTime+    let hash = T.pack . show . hashWith MD5 $ mconcat+               [ UTF8.fromString $ show time+               , UTF8.fromText $ render Nothing main+               ]+    pure $ mconcat [ "<", hash, "> <", hash, ">" ]   -- we need a default here since lang is used in template conditionals   let hasStringValue x = isJust (getField x metadata :: Maybe (Doc Text))   let geometryFromMargins = mconcat $ intersperse ("," :: Doc Text) $@@ -192,7 +219,20 @@                            _         -> [])                     $ lookupMetaInlines "nocite" meta -  let context  =  defField "toc" (writerTableOfContents options) $+   -- see #7414, avoid escaped underscores+  let unescapeUnderscore = T.replace "\\_" "_"+  let bibliography' = map unescapeUnderscore <$>+                        getField "bibliography" metadata++  -- Process PDF standard metadata for DocumentMetadata+  pdfStd <- processPdfStandard metadata++  let context  =  (case bibliography' of+                     Nothing -> id+                     Just xs -> resetField "bibliography" xs) $+                  defField "toc" (writerTableOfContents options) $+                  defField "lof" (writerListOfFigures options) $+                  defField "lot" (writerListOfTables options) $                   defField "toc-depth" (tshow                                         (writerTOCDepth options -                                               if stHasChapters st@@ -200,12 +240,14 @@                                                  else 0)) $                   defField "body" main $                   defField "title-meta" titleMeta $+                  defField "subtitle-meta" subtitleMeta $                   defField "author-meta"                         (T.intercalate "; " authorsMeta) $                   defField "documentclass" documentClass $                   defField "verbatim-in-note" (stVerbInNote st) $                   defField "tables" (stTable st) $                   defField "multirow" (stMultiRow st) $+                  defField "cancel" (stCancel st) $                   defField "strikeout" (stStrikeout st) $                   defField "url" (stUrl st) $                   defField "numbersections" (writerNumberSections options) $@@ -215,15 +257,20 @@                   defField "svg" (stSVG st) $                   defField "has-chapters" (stHasChapters st) $                   defField "has-frontmatter" (documentClass `elem` frontmatterClasses) $-                  defField "listings" (writerListings options || stLHS st) $+                  defField "listings" (writerHighlightMethod options ==+                                       IdiomaticHighlighting+                                       || stLHS st) $                   defField "zero-width-non-joiner" (stZwnj st) $                   defField "beamer" beamer $                   (if stHighlighting st-                      then case writerHighlightStyle options of-                                Just sty ->+                      then case writerHighlightMethod options of+                             Skylighting sty ->                                    defField "highlighting-macros"                                       (T.stripEnd $ styleToLaTeX sty)-                                Nothing -> id+                             DefaultHighlighting ->+                                   defField "highlighting-macros"+                                      (T.stripEnd $ styleToLaTeX defaultStyle)+                             _ -> id                       else id) $                   (case writerCiteMethod options of                          Natbib   -> defField "biblio-title" biblioTitle .@@ -248,7 +295,17 @@                       Just (Just ('A', ds))                         | not (T.null ds) && T.all isDigit ds                           -> resetField "papersize" ("a" <> ds)-                      _   -> id)+                      _   -> id) .+                  (if reproduciblePDF+                    then defField "pdf-trailer-id" trailerID+                    else id) $+                  (if not (null (pdfStandards pdfStd)) || isJust (pdfVersion pdfStd)+                    then resetField "pdfstandard" $ MapVal $ Context $ M.fromList+                           [ ("standards", ListVal $ map (SimpleVal . literal) (pdfStandards pdfStd))+                           , ("version", maybe NullVal (SimpleVal . literal) (pdfVersion pdfStd))+                           , ("tagging", BoolVal (pdfTagging pdfStd))+                           ]+                    else id) $                   metadata   let babelLang = mblang >>= toBabel   let context' =@@ -258,9 +315,15 @@                       (literal $ renderLang l)) mblang         $ maybe id (\l -> defField "babel-lang"                       (literal l)) babelLang+        $ (case babelLang of -- see #8283+                Just l | l `notElem` ldfLanguages+                         -> defField "babeloptions" ("provide=*" :: Text)+                _ -> id)         $ defField "babel-otherlangs"              (map literal-               (nubOrd . catMaybes . filter (/= babelLang)+               (filter (`elem` ldfLanguages) .+                nubOrd . catMaybes .+                filter (/= babelLang)                 $ map toBabel docLangs))         $ defField "latex-dir-rtl"            ((render Nothing <$> getField "dir" context) ==@@ -270,6 +333,10 @@        Nothing  -> main        Just tpl -> renderTemplate tpl context' +-- Commas in title-meta need to be put in braces; see #10501+escapeCommas :: Text -> Text+escapeCommas = T.replace "," "{,}"+ toSlides :: PandocMonad m => [Block] -> LW m [Block] toSlides bs = do   opts <- gets stOptions@@ -369,8 +436,9 @@      then modify $ \st -> st{ stIncremental = True }      else when (beamer && "nonincremental" `elem` classes) $              modify $ \st -> st { stIncremental = False }-  result <- if identifier == "refs" || -- <- for backwards compatibility-               "csl-bib-body" `elem` classes+  result <- if (identifier == "refs" || -- <- for backwards compatibility+                "csl-bib-body" `elem` classes) &&+               (not (null bs))                then do                  modify $ \st -> st{ stHasCslRefs = True }                  inner <- blockListToLaTeX bs@@ -417,6 +485,7 @@   blockToLaTeX $ linesToPara lns blockToLaTeX (BlockQuote lst) = do   beamer <- gets stBeamer+  csquotes <- liftM stCsquotes get   case lst of        [b] | beamer && isListBlock b -> do          oldIncremental <- gets stIncremental@@ -429,7 +498,10 @@          modify (\s -> s{stInQuote = True})          contents <- blockListToLaTeX lst          modify (\s -> s{stInQuote = oldInQuote})-         return $ "\\begin{quote}" $$ contents $$ "\\end{quote}"+         let envname = if csquotes then "displayquote" else "quote"+         return $ ("\\begin" <> braces envname) $$+                  contents $$+                  ("\\end" <> braces envname) blockToLaTeX (CodeBlock (identifier,classes,keyvalAttr) str) = do   opts <- gets stOptions   inNote <- stInNote <$> get@@ -452,7 +524,8 @@         ref <- toLabel identifier         kvs <- mapM (\(k,v) -> (k,) <$>                        stringToLaTeX TextString v) keyvalAttr-        let params = if writerListings (stOptions st)+        let params = if writerHighlightMethod (stOptions st)+                        == IdiomaticHighlighting                      then (case getListingsLanguage classes of                                 Just l  -> [ "language=" <> mbBraced l ]                                 Nothing -> []) ++@@ -485,13 +558,16 @@                Right h -> do                   when inNote $ modify (\s -> s{ stVerbInNote = True })                   modify (\s -> s{ stHighlighting = True })-                  return (flush $ linkAnchor $$ text (T.unpack h))+                  return (flush $ linkAnchor $$ literal h)   case () of      _ | isEnabled Ext_literate_haskell opts && "haskell" `elem` classes &&          "literate" `elem` classes           -> lhsCodeBlock-       | writerListings opts                 -> listingsCodeBlock-       | not (null classes) && isJust (writerHighlightStyle opts)+       | writerHighlightMethod opts == IdiomaticHighlighting+                                             -> listingsCodeBlock+       | not (null classes), Skylighting _ <- writerHighlightMethod opts                                              -> highlightedCodeBlock+       | not (null classes), DefaultHighlighting <- writerHighlightMethod opts+                                             -> highlightedCodeBlock        -- we don't want to use \begin{verbatim} if our code        -- contains \end{verbatim}:        | inNote@@ -513,14 +589,15 @@   isFirstInDefinition <- gets stIsFirstInDefinition   beamer <- gets stBeamer   let inc = if beamer && incremental then "[<+->]" else ""-  items <- mapM listItemToLaTeX lst+  items <- mapM (listItemToLaTeX False) lst   let spacing = if isTightList lst                    then text "\\tightlist"                    else empty-  return $ text ("\\begin{itemize}" <> inc) $$+  return $ -- force list to start on new line if in a defn list+             (if isFirstInDefinition then "\\hfill" else mempty) $$+             text ("\\begin{itemize}" <> inc) $$              spacing $$              -- force list at beginning of definition to start on new line-             (if isFirstInDefinition then "\\item[]" else mempty) $$              vcat items $$              "\\end{itemize}" blockToLaTeX (OrderedList _ []) = return empty -- otherwise latex error@@ -530,7 +607,7 @@   let oldlevel = stOLLevel st   isFirstInDefinition <- gets stIsFirstInDefinition   put $ st {stOLLevel = oldlevel + 1}-  items <- mapM listItemToLaTeX lst+  items <- mapM (listItemToLaTeX True) lst   modify (\s -> s {stOLLevel = oldlevel})   let beamer = stBeamer st   let tostyle x = case numstyle of@@ -568,12 +645,12 @@   let spacing = if isTightList lst                    then text "\\tightlist"                    else empty-  return $ text ("\\begin{enumerate}" <> inc)+  return $ -- force list at beginning of definition to start on new line+           (if isFirstInDefinition then "\\hfill" else mempty)+         $$ text ("\\begin{enumerate}" <> inc)          $$ stylecommand          $$ resetcounter          $$ spacing-         -- force list at beginning of definition to start on new line-         $$ (if isFirstInDefinition then "\\item[]" else mempty)          $$ vcat items          $$ "\\end{enumerate}" blockToLaTeX (DefinitionList []) = return empty@@ -598,10 +675,14 @@ blockToLaTeX (Table attr blkCapt specs thead tbodies tfoot) =   tableToLaTeX inlineListToLaTeX blockListToLaTeX                (Ann.toTable attr blkCapt specs thead tbodies tfoot)-blockToLaTeX (Figure (ident, _, _) captnode body) = do+blockToLaTeX (Figure (ident, _, kvs) captnode body) = do+  opts <- gets stOptions   (capt, captForLof, footnotes) <- getCaption inlineListToLaTeX True captnode   lab <- labelFor ident   let caption = "\\caption" <> captForLof <> braces capt <> lab+      placement = case lookup "latex-placement" kvs of+        Just p -> brackets (text (T.unpack p))+        _      -> text ""    isSubfigure <- gets stInFigure   modify $ \st -> st{ stInFigure = True }@@ -609,13 +690,16 @@     [b] -> blockToLaTeX b     bs  -> mconcat . intersperse (cr <> "\\hfill") <$>            mapM (toSubfigure (length bs)) bs-  let innards = "\\centering" $$ contents $$ caption <> cr+  let innards = "\\centering" $$+                (case writerFigureCaptionPosition opts of+                  CaptionBelow -> contents $$ caption+                  CaptionAbove -> caption $$ contents) <> cr   modify $ \st ->     st{ stInFigure = isSubfigure       , stSubfigure = stSubfigure st || isSubfigure       } -  let containsTable = getAny . (query $ \case+  let containsTable = getAny . query (\case         Table {}  -> Any True         _         -> Any False)   st <- get@@ -630,7 +714,7 @@           cr <> "\\begin{center}" $$ contents $+$ capt $$ "\\end{center}"     _ | isSubfigure ->           innards-    _ ->  cr <> "\\begin{figure}" $$ innards $$ "\\end{figure}")+    _ ->  cr <> "\\begin{figure}" <> placement $$ innards $$ "\\end{figure}")     $$ footnotes  toSubfigure :: PandocMonad m => Int -> Block -> LW m (Doc Text)@@ -653,27 +737,27 @@ blockListToLaTeX lst =   vsep `fmap` mapM (\b -> setEmptyLine True >> blockToLaTeX b) lst -listItemToLaTeX :: PandocMonad m => [Block] -> LW m (Doc Text)-listItemToLaTeX lst+listItemToLaTeX :: PandocMonad m => Bool -> [Block] -> LW m (Doc Text)+listItemToLaTeX isOrdered lst   -- we need to put some text before a header if it's the first   -- element in an item. This will look ugly in LaTeX regardless, but   -- this will keep the typesetter from throwing an error.   | (Header{} :_) <- lst =     (text "\\item ~" $$) . nest 2 <$> blockListToLaTeX lst-  | Plain (Str "☐":Space:is) : bs <- lst = taskListItem False is bs-  | Plain (Str "☒":Space:is) : bs <- lst = taskListItem True  is bs-  | Para  (Str "☐":Space:is) : bs <- lst = taskListItem False is bs-  | Para  (Str "☒":Space:is) : bs <- lst = taskListItem True  is bs+  | not isOrdered+  , Just (checked, bs) <- toTaskListItem lst+   = taskListItem checked bs   | otherwise = (text "\\item" $$) . nest 2 <$> blockListToLaTeX lst   where-    taskListItem checked is bs = do+    taskListItem checked bs = do       let checkbox  = if checked                       then "$\\boxtimes$"                       else "$\\square$"-      isContents <- inlineListToLaTeX is-      bsContents <- blockListToLaTeX bs-      return $ "\\item" <> brackets checkbox-        $$ nest 2 (isContents $+$ bsContents)+      let bs' = case bs of+                  Plain ils : xs -> Para ils : xs+                  _ -> bs+      bsContents <- blockListToLaTeX bs'+      return $ "\\item" <> brackets checkbox $$ nest 2 bsContents  defListItemToLaTeX :: PandocMonad m => ([Inline], [[Block]]) -> LW m (Doc Text) defListItemToLaTeX (term, defs) = do@@ -723,6 +807,7 @@       removeInvalidInline x                    = [x]   let lstNoNotes = foldr (mappend . (\x -> walkM removeInvalidInline x)) mempty lst   txtNoNotes <- inlineListToLaTeX lstNoNotes+  txtNoLinksNoNotes <- inlineListToLaTeX (removeLinks lstNoNotes)   -- footnotes in sections don't work (except for starred variants)   -- unless you specify an optional argument:   -- \section[mysec]{mysec\footnote{blah}}@@ -760,7 +845,7 @@                           5  -> "subparagraph"                           _  -> ""   inQuote <- gets stInQuote-  let prefix = if inQuote && level' >= 4+  let prefix = if inQuote                   then text "\\mbox{}%"                   -- needed for \paragraph, \subparagraph in quote environment                   -- see http://tex.stackexchange.com/questions/169830/@@ -775,7 +860,7 @@                    $$ if unnumbered && not unlisted                          then "\\addcontentsline{toc}" <>                                 braces (text sectionType) <>-                                braces txtNoNotes+                                braces txtNoLinksNoNotes                          else empty  -- | Convert list of inline elements to LaTeX.@@ -821,7 +906,7 @@               -> LW m (Doc Text) inlineToLaTeX (Span ("",["mark"],[]) lst) = do   modify $ \st -> st{ stStrikeout = True } -- this gives us the soul package-  inCmd "hl" <$> inlineListToLaTeX lst+  inCmd "hl" <$> inSoulCommand (inlineListToLaTeX lst) inlineToLaTeX (Span (id',classes,kvs) ils) = do   linkAnchor <- hypertarget id'   lang <- toLang $ lookup "lang" kvs@@ -859,19 +944,11 @@ inlineToLaTeX (Emph lst) = inCmd "emph" <$> inlineListToLaTeX lst inlineToLaTeX (Underline lst) = do   modify $ \st -> st{ stStrikeout = True } -- this gives us the soul package-  inCmd "ul" <$> inlineListToLaTeX lst+  inCmd "ul" <$> inSoulCommand (inlineListToLaTeX lst) inlineToLaTeX (Strong lst) = inCmd "textbf" <$> inlineListToLaTeX lst inlineToLaTeX (Strikeout lst) = do-  -- we need to protect VERB in an mbox or we get an error-  -- see #1294-  -- with regular texttt we don't get an error, but we get-  -- incorrect results if there is a space, see #5529-  contents <- inlineListToLaTeX $ walk (concatMap protectCode) lst   modify $ \s -> s{ stStrikeout = True }-  -- soul doesn't like \(..\) delimiters, so we change these to $ (#9597):-  let fixMath = T.replace "\\(" "$" . T.replace "\\)" "$" .-                T.replace "\\[" "$$" . T.replace "\\]" "$$"-  return $ inCmd "st" $ fixMath <$> contents+  inCmd "st" <$> inSoulCommand (inlineListToLaTeX lst) inlineToLaTeX (Superscript lst) =   inCmd "textsuperscript" <$> inlineListToLaTeX lst inlineToLaTeX (Subscript lst) =@@ -892,6 +969,8 @@   opts <- gets stOptions   inHeading <- gets stInHeading   inItem <- gets stInItem+  inSoul <- gets stInSoulCommand+  inCaption <- gets stInCaption   let listingsCode = do         let listingsopts = (case getListingsLanguage classes of                                 Just l  -> (("language", mbBraced l):)@@ -940,12 +1019,26 @@                  rawCode                Right h -> modify (\st -> st{ stHighlighting = True }) >>                           return (text (T.unpack h))-  case () of+  -- for soul commands we need to protect VERB in an mbox or we get an error+  -- (see #1294). with regular texttt we don't get an error, but we get+  -- incorrect results if there is a space (see #5529).+  let inMbox x = "\\mbox" <> braces x++  -- for captions we need to protect VERB with \protect (see #6821)+  let protect x = "\\protect" <> x++  let optionalProtect = case () of _ | inSoul -> inMbox+                                     | inCaption -> protect+                                     | otherwise -> id+  optionalProtect <$>+   case writerHighlightMethod opts of      _ | inHeading || inItem  -> rawCode  -- see #5574-       | writerListings opts  -> listingsCode-       | isJust (writerHighlightStyle opts) && not (null classes)+     IdiomaticHighlighting    -> listingsCode+     Skylighting _ | not (null classes)                               -> highlightCode-       | otherwise            -> rawCode+     DefaultHighlighting | not (null classes)+                              -> highlightCode+     _noHighlighting          -> rawCode inlineToLaTeX (Quoted qt lst) = do   contents <- inlineListToLaTeX lst   csquotes <- liftM stCsquotes get@@ -982,12 +1075,29 @@ inlineToLaTeX (Str str) = do   setEmptyLine False   liftM literal $ stringToLaTeX TextString str+inlineToLaTeX (Math _ str)+  | isMathEnv str -- see #9711+  = do setEmptyLine False+       when (needsCancel str) $ modify $ \st -> st{ stCancel = True }+       pure $ literal str inlineToLaTeX (Math InlineMath str) = do   setEmptyLine False-  return $ "\\(" <> literal (handleMathComment str) <> "\\)"+  inSoul <- gets stInSoulCommand+  let contents = literal (handleMathComment str)+  when (needsCancel str) $ modify $ \st -> st{ stCancel = True }+  return $+    if inSoul -- #9597+       then "$" <> contents <> "$"+       else "\\(" <> contents <> "\\)" inlineToLaTeX (Math DisplayMath str) = do   setEmptyLine False-  return $ "\\[" <> literal (handleMathComment str) <> "\\]"+  inSoul <- gets stInSoulCommand+  let contents = literal (handleMathComment str)+  when (needsCancel str) $ modify $ \st -> st{ stCancel = True }+  return $+    if inSoul -- # 9597+       then "$$" <> contents <> "$$"+       else "\\[" <> contents <> "\\]" inlineToLaTeX il@(RawInline f str) = do   beamer <- gets stBeamer   if f == Format "latex" || f == Format "tex" ||@@ -1023,21 +1133,25 @@                      then "\\hyperlink" <> braces (literal lab) <> braces contents                      else "\\hyperref" <> brackets (literal lab) <> braces contents      _ -> case txt of-          [Str x] | unEscapeString (T.unpack x) == unEscapeString (T.unpack src) ->  -- autolink+          -- For soul sommands we need to protect \url and \href in an mbox or+          -- we get an error (see #9366)+          [Str x] | T.all isAscii x  -- see #8802+                  , unEscapeString (T.unpack x) ==+                    unEscapeString (T.unpack src) ->  -- autolink                do modify $ \s -> s{ stUrl = True }                   src' <- stringToLaTeX URLString (escapeURI src)-                  return $ literal $ "\\url{" <> src' <> "}"+                  protectInMboxIfInSoul $ literal $ "\\url{" <> src' <> "}"           [Str x] | Just rest <- T.stripPrefix "mailto:" src,                     unEscapeString (T.unpack x) == unEscapeString (T.unpack rest) -> -- email autolink                do modify $ \s -> s{ stUrl = True }                   src' <- stringToLaTeX URLString (escapeURI src)                   contents <- inlineListToLaTeX txt-                  return $ "\\href" <> braces (literal src') <>+                  protectInMboxIfInSoul $ "\\href" <> braces (literal src') <>                      braces ("\\nolinkurl" <> braces contents)           _ -> do contents <- inlineListToLaTeX txt                   src' <- stringToLaTeX URLString (escapeURI src)-                  return $ literal ("\\href{" <> src' <> "}{") <>-                           contents <> char '}')+                  protectInMboxIfInSoul $ literal ("\\href{" <> src' <> "}{") <>+                    contents <> char '}')      >>= (if T.null id'              then return              else \x -> do@@ -1047,12 +1161,20 @@   | Just _ <- T.stripPrefix "data:" src = do       report $ InlineNotRendered il       return empty-inlineToLaTeX (Image attr@(_,_,kvs) _ (source, _)) = do+inlineToLaTeX (Image attr@(_,_,kvs) description (source, _)) = do   setEmptyLine False   let isSVG = ".svg" `T.isSuffixOf` source || ".SVG" `T.isSuffixOf` source   modify $ \s -> s{ stGraphics = True                   , stSVG = stSVG s || isSVG }   opts <- gets stOptions+  mbalt <- if isSVG+              then pure Nothing+              else case lookup "alt" kvs of+                     Just x -> Just <$> stringToLaTeX TextString x+                     Nothing+                       | null description -> pure Nothing+                       | otherwise -> Just <$> stringToLaTeX TextString+                                                  (stringify description)   let showDim dir = let d = text (show dir) <> "="                     in case dimension dir attr of                          Just (Pixel a)   ->@@ -1060,7 +1182,7 @@                          Just (Percent a) ->                            [d <> literal (showFl (a / 100)) <>                              case dir of-                                Width  -> "\\textwidth"+                                Width  -> "\\linewidth"                                 Height -> "\\textheight"                            ]                          Just dim         ->@@ -1068,13 +1190,17 @@                          Nothing          ->                            case dir of                                 Width | isJust (dimension Height attr) ->-                                  [d <> "\\textwidth"]+                                  [d <> "\\linewidth"]                                 Height | isJust (dimension Width attr) ->                                   [d <> "\\textheight"]                                 _ -> []       optList = showDim Width <> showDim Height <>+                (case (dimension Height attr, dimension Width attr) of+                  (Just _, Just _) -> []+                  _ -> ["keepaspectratio"]) <>                 maybe [] (\x -> ["page=" <> literal x]) (lookup "page" kvs) <>                 maybe [] (\x -> ["trim=" <> literal x]) (lookup "trim" kvs) <>+                maybe [] (\x -> ["alt=" <> braces (literal x)]) mbalt <>                 maybe [] (const ["clip"]) (lookup "clip" kvs)       options = if null optList                    then empty@@ -1086,8 +1212,11 @@   inHeading <- gets stInHeading   return $     (if inHeading then "\\protect" else "") <>-      (if isSVG then "\\includesvg" else "\\includegraphics") <>-    options <> braces (literal source'')+    (case dimension Width attr `mplus` dimension Height attr of+       Just _ -> id+       Nothing -> ("\\pandocbounded" <>) . braces)+      ((if isSVG then "\\includesvg" else "\\includegraphics") <>+        options <> braces (literal source'')) inlineToLaTeX (Note contents) = do   setEmptyLine False   externalNotes <- gets stExternalNotes@@ -1100,8 +1229,12 @@   let noteContents = nest 2 contents' <> optnl   beamer <- gets stBeamer   -- in beamer slides, display footnote from current overlay forward+  -- and ensure that the note is on the frame, not e.g. the column (#5769, #5954)+  incremental <- gets stIncremental   let beamerMark = if beamer-                      then text "<.->"+                      then if incremental+                           then text "<.->[frame]"+                           else text "<\\value{beamerpauses}->[frame]"                       else empty   if externalNotes      then do@@ -1121,11 +1254,6 @@           _              -> s <> "\n"         _                -> s -protectCode :: Inline -> [Inline]-protectCode x@(Code _ _) = [ltx "\\mbox{" , x , ltx "}"]-  where ltx = RawInline (Format "latex")-protectCode x = [x]- setEmptyLine :: PandocMonad m => Bool -> LW m () setEmptyLine b = modify $ \st -> st{ stEmptyLine = b } @@ -1145,3 +1273,239 @@ -- Look up a key in an attribute and give a list of its values lookKey :: Text -> Attr -> [Text] lookKey key (_,_,kvs) =  maybe [] T.words $ lookup key kvs++-- soul doesn't like \(..\) delimiters, so we change these to $ (#9597)+-- when processing their contents.+inSoulCommand :: PandocMonad m => LW m a -> LW m a+inSoulCommand pa = do+  oldInSoulCommand <- gets stInSoulCommand+  modify $ \st -> st{ stInSoulCommand = True }+  result <- pa+  modify $ \st -> st{ stInSoulCommand = oldInSoulCommand }+  pure result++-- Inside soul commands some commands need to be protected in an mbox+-- or we get an error (e.g. see #1294)+protectInMboxIfInSoul :: (PandocMonad m, HasChars a) => Doc a -> LW m (Doc a)+protectInMboxIfInSoul command = do+  inSoul <- gets stInSoulCommand+  return $ if inSoul+    then "\\mbox" <> braces command+    else command++-- Babel languages with a .ldf that works well with all engines (see #8283).+-- We follow the guidance from the Babel documentation:+-- "In general, you should do this for European languages written in Latin+-- and Cyrillic scripts, as well as for Vietnamese."+ldfLanguages :: [Text]+ldfLanguages =+  [ "magyar"+  , "croatian"+  , "ngerman"+  , "germanb"+  , "german"+  , "austrian"+  , "ngermanb"+  , "naustrian"+  , "nswissgerman"+  , "swissgerman"+  , "italian"+  , "greek"+  , "azerbaijani"+  , "american"+  , "newzealand"+  , "UKenglish"+  , "USenglish"+  , "australian"+  , "british"+  , "canadian"+  , "english"+  , "bahasa"+  , "slovak"+  , "finnish"+  , "occitan"+  , "swedish"+  , "brazil"+  , "portuguese"+  , "portuges"+  , "brazilian"+  , "spanish"+  , "norwegian"+  , "norsk"+  , "nynorsk"+  , "bulgarian"+  , "breton"+  , "belarusian"+  , "piedmontese"+  , "esperanto"+  , "lithuanian"+  , "ukraineb"+  , "scottishgaelic"+  , "scottish"+  , "dutch"+  , "afrikaans"+  , "czech"+  , "serbian"+  , "latvian"+  , "catalan"+  , "basque"+  , "albanian"+  , "irish"+  , "serbianc"+  , "interlingua"+  , "bosnian"+  , "friulan"+  , "romanian"+  , "icelandic"+  , "classiclatin"+  , "ecclesiasticlatin"+  , "medievallatin"+  , "latin"+  , "georgian"+  , "macedonian"+  , "welsh"+  , "vietnamese"+  , "romansh"+  , "danish"+  , "lsorbian"+  , "usorbian"+  , "polish-compat"+  , "polish"+  , "estonian"+  , "french"+  , "frenchb"+  , "canadien"+  , "acadian"+  , "francais"+  , "turkish"+  , "hindi"+  , "northernsami"+  , "samin"+  , "russianb"+  , "galician"+  , "slovene"+  ]++isMathEnv :: Text -> Bool+isMathEnv t =+  case T.stripPrefix "\\begin{" (T.dropWhile isSpaceChar t) of+    Nothing -> False+    Just t' -> T.takeWhile (/= '}') t' `elem`+      [ "align", "align*"+      , "flalign", "flalign*"+      , "alignat", "alignat*"+      , "dmath", "dmath*"+      , "dgroup", "dgroup*"+      , "darray", "darray*"+      , "gather", "gather*"+      , "multline", "multline*"+      , "subequations"+      , "equation", "equation*"+      , "eqnarray"+      , "displaymath"+      ]+ where+   isSpaceChar '\n' = True+   isSpaceChar '\r' = True+   isSpaceChar '\t' = True+   isSpaceChar ' ' = True+   isSpaceChar _ = False++-- True if the math needs the cancel package+needsCancel :: Text -> Bool+needsCancel t =+  case A.parseOnly pCancel t of+    Right True -> True+    _ -> False+ where+  pCancel = (False <$ A.endOfInput) <|> do+    c <- A.anyChar+    case c of+      '\\' -> do+        x <- A.takeWhile isLetter+        if x == "cancel" || x == "xcancel" || x == "bcancel"+           then return True+           else pCancel+      _ -> pCancel++-- PDF standard support for DocumentMetadata++-- | PDF standards supported by LaTeX's DocumentMetadata+-- See: https://github.com/latex3/latex2e documentmetadata-support.dtx+latexSupportedStandards :: Set.Set Text+latexSupportedStandards = Set.fromList+  [ -- PDF/A standards (note: a-1a is NOT supported by LaTeX, only a-1b)+    "a-1b", "a-2a", "a-2b", "a-2u", "a-3a", "a-3b", "a-3u"+  , "a-4", "a-4e", "a-4f"+    -- PDF/X standards+  , "x-4", "x-4p", "x-5g", "x-5n", "x-5pg", "x-6", "x-6n", "x-6p"+    -- PDF/UA standards+  , "ua-1", "ua-2"+  ]++-- | Standards that require PDF tagging (document structure)+-- PDF/A level "a" variants and PDF/UA require tagged structure+taggingRequiredStandards :: Set.Set Text+taggingRequiredStandards = Set.fromList+  ["a-2a", "a-3a", "ua-1", "ua-2"]++-- | Valid PDF versions for DocumentMetadata+validPdfVersions :: Set.Set Text+validPdfVersions = Set.fromList+  ["1.4", "1.5", "1.6", "1.7", "2.0"]++-- | PDF version required by each standard+-- LaTeX defaults to PDF 2.0 with \DocumentMetadata, but some standards+-- have maximum version requirements that are incompatible with 2.0+standardRequiredVersion :: M.Map Text Text+standardRequiredVersion = M.fromList+  [ ("a-1b", "1.4")  -- PDF/A-1 requires exactly PDF 1.4+    -- PDF/A-2 and PDF/A-3 require 1.7; must set explicitly since LaTeX defaults to 2.0+  , ("a-2a", "1.7"), ("a-2b", "1.7"), ("a-2u", "1.7")+  , ("a-3a", "1.7"), ("a-3b", "1.7"), ("a-3u", "1.7")+    -- PDF/A-4, PDF/UA-1, PDF/UA-2 work with PDF 2.0 (the default)+  ]++-- | Normalize a PDF standard string: lowercase, strip "pdf" prefix+normalizePdfStandard :: Text -> Text+normalizePdfStandard t =+  let lower = T.toLower t+  in case T.stripPrefix "pdf" lower of+       Just rest -> T.dropWhile (`elem` ['-', '/']) rest+       Nothing   -> lower++-- | Normalize a PDF version string+-- Handles YAML parsing quirk where 2.0 becomes integer 2, then string "2"+normalizeVersion :: Text -> Text+normalizeVersion t+  | t == "2" = "2.0"+  | otherwise = t++-- | Check if text is a valid PDF version (after normalization)+isPdfVersion :: Text -> Bool+isPdfVersion t = Set.member (normalizeVersion t) validPdfVersions++-- | Process pdfstandard metadata, returning PDF standard settings+processPdfStandard :: PandocMonad m+                   => Context Text+                   -> m PdfStandard+processPdfStandard ctx = do+  let standards = fromMaybe [] $ getField "pdfstandard" ctx+      normalized = map normalizePdfStandard standards+      (versions, pdfStds) = partition isPdfVersion normalized+      validStandards = filter (`Set.member` latexSupportedStandards) pdfStds+      invalidStandards = filter (\s -> not (Set.member s latexSupportedStandards)+                                    && not (isPdfVersion s)) pdfStds+      needsTagging = any (`Set.member` taggingRequiredStandards) validStandards+      -- Use explicit version if provided, otherwise infer from standards+      -- Apply normalizeVersion to handle YAML parsing "2" -> "2.0"+      explicitVersion = normalizeVersion <$> listToMaybe versions+      inferredVersion = listToMaybe $ mapMaybe (`M.lookup` standardRequiredVersion) validStandards+      version = explicitVersion <|> inferredVersion+  -- Warn about unsupported standards+  mapM_ (report . UnsupportedPdfStandard) invalidStandards+  return PdfStandard+    { pdfStandards = validStandards+    , pdfVersion = version+    , pdfTagging = needsTagging+    }
src/Text/Pandoc/Writers/LaTeX/Caption.hs view
@@ -1,6 +1,6 @@ {- |    Module      : Text.Pandoc.Writers.LaTeX.Caption-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -23,7 +23,7 @@ import Text.Pandoc.Walk import Text.Pandoc.Writers.LaTeX.Notes (notesToLaTeX) import Text.Pandoc.Writers.LaTeX.Types-  ( LW, WriterState (stExternalNotes, stNotes) )+  ( LW, WriterState (stExternalNotes, stNotes, stInCaption) )   -- | Produces the components of a LaTeX 'caption' command. Returns a triple@@ -35,6 +35,7 @@            -> Caption            -> LW m (Doc Text, Doc Text, Doc Text) getCaption inlineListToLaTeX externalNotes (Caption maybeShort long) = do+  modify $ \st -> st{ stInCaption = True }   let long' = blocksToInlines long   oldExternalNotes <- gets stExternalNotes   modify $ \st -> st{ stExternalNotes = externalNotes, stNotes = [] }@@ -53,4 +54,5 @@                              then toShortCapt long'                              else return empty                   Just short -> toShortCapt short+  modify $ \st -> st{ stInCaption = False }   return (capt, captForLof, footnotes)
src/Text/Pandoc/Writers/LaTeX/Citation.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Writers.LaTeX.Citation-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -18,17 +18,19 @@ import Control.Monad.State (gets) import Data.Maybe (fromMaybe) import qualified Data.Text as T+import Text.Pandoc.Options import Text.Pandoc.Class.PandocMonad (PandocMonad) import Text.Pandoc.Definition-import Data.List (foldl')+import qualified Data.List as L import Text.DocLayout (Doc, brackets, empty, (<+>), text, isEmpty, literal,                        braces) import Text.Pandoc.Walk-import Text.Pandoc.Writers.LaTeX.Types ( LW, WriterState(stLang) )+import Text.Pandoc.Writers.LaTeX.Types ( LW, WriterState(stLang, stOptions) ) import Text.Pandoc.Citeproc.Locator (parseLocator, LocatorInfo(..),                                      toLocatorMap) import Citeproc.Types (Lang(..)) import Citeproc.Locale (getLocale)+import Safe (headMay, lastMay)  citationsToNatbib :: PandocMonad m                   => ([Inline] -> LW m (Doc Text))@@ -49,16 +51,17 @@              NormalCitation -> "citep"  citationsToNatbib inlineListToLaTeX cits-  | noPrefix (tail cits) && noSuffix (init cits) && ismode NormalCitation cits+  | noInnerPrefix cits && noInnerSuffix cits && ismode NormalCitation cits   = citeCommand inlineListToLaTeX "citep" p s ks   where-     noPrefix  = all (null . citationPrefix)-     noSuffix  = all (null . citationSuffix)+     noInnerPrefix []     = True+     noInnerPrefix (_:xs) = all (null . citationPrefix) xs+     noInnerSuffix []     = True+     noInnerSuffix [_]    = True+     noInnerSuffix (x:xs) = null (citationSuffix x) && noInnerSuffix xs      ismode m  = all ((==) m  . citationMode)-     p         = citationPrefix  $-                 head cits-     s         = citationSuffix  $-                 last cits+     p         = maybe mempty citationPrefix $ headMay cits+     s         = maybe mempty citationSuffix $ lastMay cits      ks        = T.intercalate ", " $ map citationId cits  citationsToNatbib inlineListToLaTeX (c:cs)@@ -70,7 +73,7 @@  citationsToNatbib inlineListToLaTeX cits = do   cits' <- mapM convertOne cits-  return $ text "\\citetext{" <> foldl' combineTwo empty cits' <> text "}"+  return $ text "\\citetext{" <> L.foldl' combineTwo empty cits' <> text "}"   where     citeCommand' = citeCommand inlineListToLaTeX     combineTwo a b | isEmpty a = b@@ -107,8 +110,13 @@               -> LW m (Doc Text) citeArgumentsList _inlineListToLaTeX (CiteGroup _ _ []) = return empty citeArgumentsList inlineListToLaTeX (CiteGroup pfxs sfxs ids) = do+      opts <- gets stOptions       mblang <- gets stLang-      let sfxs' = removePageLabel mblang $+      let sfxs' = (case writerCiteMethod opts of+                     -- In biblatex, the label p. or pp. can be omitted;+                     -- ranges are treated as page ranges by default. See #9275.+                     Biblatex -> removePageLabel mblang+                     _ -> id) $               stripLocatorBraces $ case sfxs of                 (Str t : r) -> case T.uncons t of                   Just (x, xs)@@ -174,7 +182,7 @@                     NormalCitation -> "\\autocites"        groups <- mapM (citeArgumentsList inlineListToLaTeX)-                     (reverse (foldl' grouper [] (c:cs)))+                     (reverse (L.foldl' grouper [] (c:cs)))        return $ text cmd <> mconcat groups @@ -189,9 +197,6 @@  citationsToBiblatex _ _ = return empty --- | In natbib and biblatex, the label p. or pp. can be--- omitted; ranges will be treated as page ranges by default.--- See #9275. removePageLabel :: Maybe Lang -> [Inline] -> [Inline] removePageLabel mblang ils =   case mbLocinfo of
src/Text/Pandoc/Writers/LaTeX/Lang.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE ScopedTypeVariables #-} {- |    Module      : Text.Pandoc.Writers.LaTeX.Lang-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -33,14 +33,14 @@   | otherwise                           = Just "ngerman" toBabel (Lang "dsb" _ _ _ _ _)          = Just "lowersorbian" toBabel (Lang "el" _ _ vars _ _)-  | "polyton" `elem` vars               = Just "polutonikogreek"+  | "polyton" `elem` vars               = Just "polytonicgreek" toBabel (Lang "en" _ (Just "AU") _ _ _) = Just "australian" toBabel (Lang "en" _ (Just "CA") _ _ _) = Just "canadian" toBabel (Lang "en" _ (Just "GB") _ _ _) = Just "british" toBabel (Lang "en" _ (Just "NZ") _ _ _) = Just "newzealand" toBabel (Lang "en" _ (Just "UK") _ _ _) = Just "british" toBabel (Lang "en" _ (Just "US") _ _ _) = Just "american"-toBabel (Lang "fr" _ (Just "CA") _ _ _) = Just "canadien"+toBabel (Lang "fr" _ (Just "CA") _ _ _) = Just "french" toBabel (Lang "fra" _ _ vars _ _)   | "aca" `elem` vars                   = Just "acadian" toBabel (Lang "grc" _ _ _ _ _)          = Just "ancientgreek"
src/Text/Pandoc/Writers/LaTeX/Notes.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Writers.LaTeX.Notes-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>
src/Text/Pandoc/Writers/LaTeX/Table.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Writers.LaTeX.Table-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -33,11 +33,12 @@ import Text.Pandoc.Writers.LaTeX.Notes (notesToLaTeX) import Text.Pandoc.Writers.LaTeX.Types   ( LW, WriterState (stBeamer, stExternalNotes, stInMinipage, stMultiRow-                    , stNotes, stTable) )+                    , stNotes, stTable, stOptions) ) import Text.Pandoc.Writers.LaTeX.Util (labelFor) import Text.Printf (printf) import qualified Text.Pandoc.Builder as B import qualified Text.Pandoc.Writers.AnnotatedTable as Ann+import Text.Pandoc.Options (CaptionPosition(..), WriterOptions(..))  tableToLaTeX :: PandocMonad m              => ([Inline] -> LW m (Doc Text))@@ -45,8 +46,13 @@              -> Ann.Table              -> LW m (Doc Text) tableToLaTeX inlnsToLaTeX blksToLaTeX tbl = do+  opts <- gets stOptions   let (Ann.Table (ident, _, _) caption specs thead tbodies tfoot) = tbl   CaptionDocs capt captNotes <- captionToLaTeX inlnsToLaTeX caption ident+  let hasTopCaption = not (isEmpty capt) &&+                        writerTableCaptionPosition opts == CaptionAbove+  let hasBottomCaption = not (isEmpty capt) &&+                          writerTableCaptionPosition opts == CaptionBelow   let isSimpleTable =         all ((== ColWidthDefault) . snd) specs &&         all (all isSimpleCell)@@ -64,29 +70,38 @@   -- duplicate the header rows for this.   head' <- do     let mkHead = headToLaTeX blksToLaTeX isSimpleTable colCount-    case (not $ isEmpty capt, not $ isEmptyHead thead) of-      (False, False) -> return "\\toprule\\noalign{}"-      (False, True)  -> mkHead thead-      (True, False)  -> return (capt $$ "\\toprule\\noalign{}" $$ "\\endfirsthead")-      (True, True)   -> do+    case (hasTopCaption, isEmptyHead thead) of+      (False, True) -> return "\\toprule\\noalign{}"+      (False, False)  -> mkHead thead+      (True, True)  -> return (capt <> "\\tabularnewline"+                                $$ "\\toprule\\noalign{}"+                                $$ "\\endfirsthead")+      (True, False)   -> do         -- avoid duplicate notes in head and firsthead:         firsthead <- mkHead thead         repeated  <- mkHead (walk removeNote thead)-        return $ capt $$ firsthead $$ "\\endfirsthead" $$ repeated+        return $ capt <> "\\tabularnewline"+                 $$ firsthead+                 $$ "\\endfirsthead"+                 $$ repeated   rows' <- mapM (rowToLaTeX blksToLaTeX isSimpleTable colCount BodyCell) $                 mconcat (map bodyRows tbodies)-  foot' <- if isEmptyFoot tfoot-           then pure empty-           else do-             lastfoot <- mapM-                (rowToLaTeX blksToLaTeX isSimpleTable colCount BodyCell) $-                footRows tfoot-             pure $ "\\midrule\\noalign{}" $$ vcat lastfoot+  lastfoot <- mapM (rowToLaTeX blksToLaTeX isSimpleTable colCount BodyCell) $+                    footRows tfoot+  let foot' = (if isEmptyFoot tfoot+                  then mempty+                  else "\\midrule\\noalign{}" $$ vcat lastfoot)+              $$ "\\bottomrule\\noalign{}"+              $$ (if hasBottomCaption+                     then "\\tabularnewline" $$ capt+                     else mempty)   modify $ \s -> s{ stTable = True }   notes <- notesToLaTeX <$> gets stNotes   beamer <- gets stBeamer+  let makeUnnumbered x = "{\\def\\LTcaptype{none} % do not increment counter" $$ x $$ "}"   return-    $  "\\begin{longtable}[]" <>+    $ (if null capt then makeUnnumbered else id)+    $ "\\begin{longtable}[]" <>           braces ("@{}" <> colDescriptors isSimpleTable tbl <> "@{}")           -- the @{} removes extra space at beginning and end     $$ head'@@ -99,10 +114,8 @@        (if beamer              then [ vcat rows'                   , foot'-                  , "\\bottomrule\\noalign{}"                   ]              else [ foot'-                  , "\\bottomrule\\noalign{}"                   , "\\endlastfoot"                   ,  vcat rows'                   ])@@ -149,7 +162,7 @@     toColDescriptor :: Int -> Alignment -> Double -> Text     toColDescriptor numcols align width =       T.pack $ printf-      ">{%s\\arraybackslash}p{(\\columnwidth - %d\\tabcolsep) * \\real{%0.4f}}"+      ">{%s\\arraybackslash}p{(\\linewidth - %d\\tabcolsep) * \\real{%0.4f}}"       (T.unpack (alignCommand align))       ((numcols - 1) * 2)       width@@ -192,7 +205,6 @@                        else "\\caption" <> captForLot <>                             braces captionText                             <> label-                            <> "\\tabularnewline"     }  type BlocksWriter m = [Block] -> LW m (Doc Text)@@ -356,12 +368,20 @@                                <> braces (literal colDescr)                                <> braces ("%\n" <> x)                                   -- linebreak for readability+  let hasColWidths = not (all (== ColWidthDefault) colWidths)+  let aligncmd = case specAlign of+                   AlignCenter -> "\\centering\\arraybackslash "+                   AlignRight -> "\\raggedright\\arraybackslash "+                   _ -> mempty   let inMultiRow x = case rowspan of                        (RowSpan 1) -> x                        (RowSpan n) -> let nrows = literal (tshow n)                                       in "\\multirow" <> braces nrows-                                         <> braces "=" -- width of column-                                         <> braces x+                                         <> braces -- width of column+                                             (if hasColWidths+                                                 then "=" -- max width+                                                 else "*") -- natural width+                                         <> braces (aligncmd <> x)   return . inMultiColumn . inMultiRow $ result  -- | Returns the width of a cell spanning @n@ columns.@@ -391,7 +411,7 @@               (T.unpack (colAlign align))               (if colnum + colspan >= numcols then skipColSep else "") -        else printf "%s>{%s\\arraybackslash}p{(\\columnwidth - %d\\tabcolsep) * \\real{%0.4f} + %d\\tabcolsep}%s"+        else printf "%s>{%s\\arraybackslash}p{(\\linewidth - %d\\tabcolsep) * \\real{%0.4f} + %d\\tabcolsep}%s"               (if colnum == 0 then skipColSep else "")               (T.unpack (alignCommand align))               (2 * (numcols - 1))
src/Text/Pandoc/Writers/LaTeX/Types.hs view
@@ -2,6 +2,7 @@   ( LW   , WriterState (..)   , startingState+  , PdfStandard (..)   ) where  import Control.Monad.State.Strict (StateT)@@ -52,8 +53,18 @@   , stHasCslRefs    :: Bool          -- ^ has a Div with class refs   , stIsFirstInDefinition :: Bool    -- ^ first block in a defn list   , stLang          :: Maybe Lang    -- ^ lang specified in metadata+  , stInSoulCommand :: Bool          -- ^ in a soul command like ul+  , stCancel        :: Bool          -- ^ true if document uses \cancel+  , stInCaption     :: Bool          -- ^ true if in a caption   } +-- | PDF standard settings for DocumentMetadata+data PdfStandard = PdfStandard+  { pdfStandards :: [Text]     -- ^ list of standards (e.g., ["a-2b", "ua-1"])+  , pdfVersion   :: Maybe Text -- ^ PDF version (e.g., "1.7", "2.0")+  , pdfTagging   :: Bool       -- ^ whether tagging is required+  }+ startingState :: WriterOptions -> WriterState startingState options =   WriterState@@ -91,4 +102,7 @@   , stHasCslRefs = False   , stIsFirstInDefinition = False   , stLang = Nothing+  , stInSoulCommand = False+  , stCancel = False+  , stInCaption = False   }
src/Text/Pandoc/Writers/LaTeX/Util.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings   #-} {- |    Module      : Text.Pandoc.Writers.LaTeX.Util-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -108,11 +108,11 @@          '}' -> emits "\\}"          '?' | ligatures ->  -- avoid ?` ligature            case xs of-             '`':_ -> emits "?{}"+             '`':_ -> emits "?{\\kern0pt}" -- se #10610              _     -> emitc x          '!' | ligatures ->  -- avoid !` ligature            case xs of-             '`':_ -> emits "!{}"+             '`':_ -> emits "!{\\kern0pt}"              _     -> emitc x          '`' | ctx == CodeString -> emitcseq "\\textasciigrave"          '$' -> emits "\\$"@@ -134,6 +134,7 @@          ']'  -> emits "{]}"  -- optional arguments          '\'' -> emitcseq "\\textquotesingle"          '\160' -> emits "~"+         '\x00AD' -> emits "\\-"  -- shy hyphen          '\x200B' -> emits "\\hspace{0pt}"  -- zero-width space          '\x202F' -> emits "\\,"          '\x2026' | ligatures -> emitcseq "\\ldots"@@ -235,7 +236,7 @@                                w = maybe "0.48" fromPct (lookup "width" kvs)                            in  inCmd "begin" "column" <>                                valign <>-                               braces (literal w <> "\\textwidth")+                               braces (literal w <> "\\linewidth")                                $$ contents                                $$ inCmd "end" "column"                     else id@@ -267,7 +268,7 @@       return $ text "\\protect\\hypertarget" <> braces ref <> "{}"      else do       label <- labelFor ident-      return $ text "\\phantomsection" <> label+      return $ text "\\protect\\phantomsection" <> label  labelFor :: PandocMonad m => Text -> LW m (Doc Text) labelFor ""    = return empty
src/Text/Pandoc/Writers/Man.hs view
@@ -3,7 +3,7 @@ {-# LANGUAGE ViewPatterns      #-} {- |    Module      : Text.Pandoc.Writers.Man-   Copyright   : Copyright (C) 2007-2023 John MacFarlane+   Copyright   : Copyright (C) 2007-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -14,7 +14,7 @@  -} module Text.Pandoc.Writers.Man ( writeMan ) where-import Control.Monad ( liftM, zipWithM, forM, unless )+import Control.Monad ( liftM, zipWithM, unless ) import Control.Monad.State.Strict ( StateT, gets, modify, evalStateT ) import Control.Monad.Trans (MonadTrans(lift)) import Data.List (intersperse)@@ -86,9 +86,9 @@        Just tpl -> renderTemplate tpl context  escString :: WriterOptions -> Text -> Text-escString opts = escapeString (if writerPreferAscii opts-                                  then AsciiOnly-                                  else AllowUTF8)+escString opts = escapeString True (if writerPreferAscii opts+                                       then AsciiOnly+                                       else AllowUTF8)  -- | Return man representation of notes. notesToMan :: PandocMonad m => WriterOptions -> [[Block]] -> StateT WriterState m (Doc Text)@@ -200,7 +200,7 @@ bulletListItemToMan opts (Plain first:rest) = do   first' <- blockToMan opts (Plain first)   rest' <- blockListToMan opts rest-  let first'' = literal ".IP \\[bu] 2" $$ first'+  let first'' = literal ".IP \\(bu 2" $$ first'   let rest''  = if null rest                    then empty                    else literal ".RS 2" $$ rest' $$ literal ".RE"@@ -208,7 +208,7 @@ bulletListItemToMan opts (first:rest) = do   first' <- blockToMan opts first   rest' <- blockListToMan opts rest-  return $ literal "\\[bu] .RS 2" $$ first' $$ rest' $$ literal ".RE"+  return $ literal "\\(bu .RS 2" $$ first' $$ rest' $$ literal ".RE"  -- | Convert ordered list item (a list of blocks) to man. orderedListItemToMan :: PandocMonad m@@ -241,7 +241,7 @@   labelText <- inlineListToMan opts label   contents <- if null defs                  then return empty-                 else liftM vcat $ forM defs $ \case+                 else case mconcat defs of                           (x:xs) -> do                             first' <- blockToMan opts $                                       case x of@@ -299,7 +299,7 @@   return $ char '`' <> contents <> char '\'' inlineToMan opts (Quoted DoubleQuote lst) = do   contents <- inlineListToMan opts lst-  return $ literal "\\[lq]" <> contents <> literal "\\[rq]"+  return $ literal "\\(lq" <> contents <> literal "\\(rq" inlineToMan opts (Cite _ lst) =   inlineListToMan opts lst inlineToMan opts (Code _ str) =@@ -362,7 +362,10 @@ formatTok :: WriterOptions -> FormatOptions -> (TokenType, Text) -> Doc Text formatTok wopts _fopts (toktype, t) =   let txt = literal (escString wopts t)-      styleMap = tokenStyles <$> writerHighlightStyle wopts+      styleMap = case writerHighlightMethod wopts of+        Skylighting style   -> Just $ tokenStyles style+        DefaultHighlighting -> Just $ tokenStyles defaultStyle+        _ -> Nothing       tokStyle = fromMaybe defStyle $ styleMap >>= M.lookup toktype   in  if toktype == NormalTok          then txt
src/Text/Pandoc/Writers/Markdown.hs view
@@ -5,7 +5,7 @@ {-# LANGUAGE BangPatterns        #-} {- |    Module      : Text.Pandoc.Writers.Markdown-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -21,11 +21,11 @@   writeCommonMark,   writeMarkua,   writePlain) where-import Control.Monad (foldM, zipWithM, MonadPlus(..), when)+import Control.Monad (foldM, zipWithM, MonadPlus(..), when, liftM) import Control.Monad.Reader ( asks, MonadReader(local) ) import Control.Monad.State.Strict ( gets, modify ) import Data.Default-import Data.List (intersperse, sortOn, union)+import Data.List (intersperse, sortOn, union, find) import Data.List.NonEmpty (nonEmpty, NonEmpty(..)) import qualified Data.Map as M import Data.Maybe (fromMaybe, mapMaybe, isNothing)@@ -369,18 +369,17 @@                  -> Block         -- ^ Block element                  -> MD m (Doc Text) blockToMarkdown' opts (Div attrs@(_,classes,_) bs)+  | ("sourceCode":_) <- classes+  , [CodeBlock (_,"sourceCode":_,_) _] <- bs+     -- skip pandoc-generated Div wrappers around code blocks+   = blockListToMarkdown opts bs   | 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@@ -396,8 +395,7 @@                          | (take 3 (T.unpack id')) == "ref"                            -> contents <> blankline                          | otherwise -> contents <> blankline-             | isEnabled Ext_fenced_divs opts &&-               attrs /= nullAttr ->+             | isEnabled Ext_fenced_divs opts ->                   let attrsToMd = if variant == Commonmark                                   then attrsToMarkdown opts                                   else classOrAttrsToMarkdown opts@@ -447,12 +445,19 @@   return $ contents <> cr blockToMarkdown' opts (Para inlines) =   (<> blankline) `fmap` blockToMarkdown opts (Plain inlines)-blockToMarkdown' opts (LineBlock lns) =-  if isEnabled Ext_line_blocks opts-  then do-    mdLines <- mapM (inlineListToMarkdown opts) lns-    return $ vcat (map (hang 2 (literal "| ")) mdLines) <> blankline-  else blockToMarkdown opts $ linesToPara lns+blockToMarkdown' opts (LineBlock lns) = do+  variant <- asks envVariant+  case variant of+    PlainText -> do+      let emptyToBlank l = if isEmpty l then blankline else l+      mdLines <- mapM (liftM emptyToBlank . inlineListToMarkdown opts) lns+      return $ vcat mdLines <> blankline+    _ ->+      if isEnabled Ext_line_blocks opts+      then do+        mdLines <- mapM (inlineListToMarkdown opts) lns+        return $ vcat (map (hang 2 (literal "| ")) mdLines) <> blankline+      else blockToMarkdown opts $ linesToPara lns blockToMarkdown' opts b@(RawBlock f str) = do   variant <- asks envVariant   let Format fmt = f@@ -463,19 +468,20 @@   let renderEmpty = mempty <$ report (BlockNotRendered b)   case variant of     PlainText-      | f == "plain" -> return $ literal str <> literal "\n"+      | f == "plain" -> return $ nest 0 (literal str) <> literal "\n"     Commonmark       | f `elem` ["gfm", "commonmark", "commonmark_x", "markdown"]-         -> return $ literal str <> literal "\n"+         -> return $ nest 0 (literal str) $$ blankline       | f `elem` ["html", "html5", "html4"]-         -> return $ literal (removeBlankLinesInHTML str) <> literal "\n"+         -> return $ literal (removeBlankLinesInHTML str) $$ blankline     Markdown       | f `elem` ["markdown", "markdown_github", "markdown_phpextra",                   "markdown_mmd", "markdown_strict"]-         -> return $ literal str <> literal "\n"+        -- the 'nest 0' ensures that leading and trailing newlines+        -- don't get collapsed. See #10477 for context;+         -> return $ nest 0 (literal str) <> literal "\n"     Markua -> renderEmpty-    _ | isEnabled Ext_raw_attribute opts -> rawAttribBlock-      | f `elem` ["html", "html5", "html4"]+    _ | f `elem` ["html", "html5", "html4"]       , isEnabled Ext_markdown_attribute opts          -> return $ literal (addMarkdownAttribute str) <> literal "\n"       | f `elem` ["html", "html5", "html4"]@@ -484,6 +490,7 @@       | f `elem` ["latex", "tex"]       , isEnabled Ext_raw_tex opts          -> return $ literal str <> literal "\n"+      | isEnabled Ext_raw_attribute opts -> rawAttribBlock     _ -> renderEmpty blockToMarkdown' opts HorizontalRule = do   variant <- asks envVariant@@ -517,15 +524,19 @@                        isEnabled Ext_attributes opts ->                                     space <> attrsToMarkdown opts attr                      | otherwise -> empty+  let setext = level <= 2 && writerSetextHeaders opts ||+                              (variant == Commonmark &&+                               hasLineBreaks inlines) -- #11341   contents <- inlineListToMarkdown opts $-                 -- ensure no newlines; see #3736-                 walk lineBreakToSpace $+                 (if variant == Commonmark && setext+                     then id+                     else -- ensure no newlines; see #3736+                          walk lineBreakToSpace) $                    if level == 1 && variant == PlainText &&                       isEnabled Ext_gutenberg opts                       then capitalize inlines                       else inlines -  let setext = writerSetextHeaders opts   when (not setext && isEnabled Ext_literate_haskell opts) $     report $ ATXHeadingInLHS level (render Nothing contents) @@ -567,7 +578,10 @@           tildes <> attrs <> cr <> literal str <> cr <> tildes <> blankline      _ | variant == Markua -> blankline <> attrsToMarkua opts attribs <> cr <> backticks <> cr <>                                 literal str <> cr <> backticks <> cr <> blankline-       | otherwise -> nest (writerTabStop opts) (literal str) <> blankline+       | otherwise -> -- don't use nest: see #11542+           let addIndent "" = "\n"+               addIndent x  = (T.replicate (writerTabStop opts) " ") <> x <> "\n"+          in  literal (mconcat $ map addIndent (T.lines str)) $$ blankline    where      endlineLen c = maybe 3 ((+1) . maximum) $ nonEmpty                         [T.length ln@@ -580,9 +594,11 @@      attrs  = if isEnabled Ext_fenced_code_attributes opts ||                  isEnabled Ext_attributes opts                  then nowrap $ " " <> classOrAttrsToMarkdown opts attribs-                 else case attribs of-                            (_,cls:_,_) -> " " <> literal cls-                            _             -> empty+                 else+                   let (_,cls,_) = attribs+                    in case getLangFromClasses cls of+                              Just l -> " " <> literal l+                              Nothing -> empty blockToMarkdown' opts (BlockQuote blocks) = do   variant <- asks envVariant   -- if we're writing literate haskell, put a space before the bird tracks@@ -592,25 +608,38 @@         | variant == PlainText = "  "         | otherwise            = "> "   contents <- blockListToMarkdown opts blocks-  return $ prefixed leader contents <> blankline-blockToMarkdown' opts t@(Table (ident,_,_) blkCapt specs thead tbody tfoot) = do+  return $ text leader <> prefixed leader contents <> blankline+blockToMarkdown' opts t@(Table attr blkCapt specs thead tbody tfoot) = do   let (caption, aligns, widths, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot+  let isColRowSpans (Cell _ _ rs cs _) = rs > 1 || cs > 1+  let rowHasColRowSpans (Row _ cs) = any isColRowSpans cs+  let hasFooter = case tfoot of+                    TableFoot _ [] -> False+                    _ -> True+  let tbodyHasColRowSpans (TableBody _ _ rhs rs) =+        any rowHasColRowSpans rhs || any rowHasColRowSpans rs+  let theadHasColRowSpans (TableHead _ rs) = any rowHasColRowSpans rs+  let tfootHasColRowSpans (TableFoot _ rs) = any rowHasColRowSpans rs+  let hasColRowSpans = theadHasColRowSpans thead ||+                       any tbodyHasColRowSpans tbody ||+                       tfootHasColRowSpans tfoot   let numcols = maximum (length aligns :| length widths :                            map length (headers:rows))   caption' <- inlineListToMarkdown opts caption-  let caption'' = if T.null ident+  let caption'' = if attr == nullAttr                      then caption'-                     else caption' <+> attrsToMarkdown opts (ident,[],[])+                     else caption' <+> attrsToMarkdown opts attr   let caption'''         | null caption = blankline         | isEnabled Ext_table_captions opts         = blankline $$ (": " <> caption'') $$ blankline         | otherwise = blankline $$ caption'' $$ blankline   let hasSimpleCells = onlySimpleTableCells $ headers : rows-  let isSimple = hasSimpleCells && all (==0) widths+  let isSimple = hasSimpleCells && not hasFooter &&+                 all (==0) widths && not hasColRowSpans   let isPlainBlock (Plain _) = True       isPlainBlock _         = False-  let hasBlocks = not (all isPlainBlock $ concat . concat $ headers:rows)+  let hasBlocks = not (all (all (all isPlainBlock)) $ headers:rows)   let padRow r = case numcols - length r of                        x | x > 0 -> r ++ replicate x empty                          | otherwise -> r@@ -620,45 +649,51 @@   let widths' = case numcols - length widths of                      x | x > 0 -> widths ++ replicate x 0.0                        | otherwise -> widths-  (nst,tbl) <--     case True of-          _ | isSimple &&-              isEnabled Ext_simple_tables opts -> do-                rawHeaders <- padRow <$> mapM (blockListToMarkdown opts) headers-                rawRows <- mapM (fmap padRow . mapM (blockListToMarkdown opts))-                           rows-                (nest 2,) <$> pandocTable opts False (all null headers)-                                aligns' widths' rawHeaders rawRows-            | isSimple &&-              isEnabled Ext_pipe_tables opts -> do-                rawHeaders <- padRow <$> mapM (blockListToMarkdown opts) headers-                rawRows <- mapM (fmap padRow . mapM (blockListToMarkdown opts))-                           rows-                (id,) <$> pipeTable opts (all null headers) aligns' widths'-                            rawHeaders rawRows-            | not hasBlocks &&-              isEnabled Ext_multiline_tables opts -> do-                rawHeaders <- padRow <$> mapM (blockListToMarkdown opts) headers-                rawRows <- mapM (fmap padRow . mapM (blockListToMarkdown opts))-                           rows-                (nest 2,) <$> pandocTable opts True (all null headers)-                                aligns' widths' rawHeaders rawRows-            | isEnabled Ext_grid_tables opts &&-               writerColumns opts >= 8 * numcols -> (id,) <$>-                gridTable opts blockListToMarkdown-                  (all null headers) aligns' widths' headers rows-            | hasSimpleCells &&-              isEnabled Ext_pipe_tables opts -> do-                rawHeaders <- padRow <$> mapM (blockListToMarkdown opts) headers-                rawRows <- mapM (fmap padRow . mapM (blockListToMarkdown opts))-                           rows-                (id,) <$> pipeTable opts (all null headers) aligns' widths'-                           rawHeaders rawRows-            | isEnabled Ext_raw_html opts -> fmap (id,) $-                   literal . removeBlankLinesInHTML <$>-                   writeHtml5String opts{ writerTemplate = Nothing } (Pandoc nullMeta [t])-            | otherwise -> return (id, literal "[TABLE]")-  return $ nst (tbl $$ caption''') $$ blankline+  let mkTable f = do+       rawHeaders <- padRow <$> mapM (blockListToMarkdown opts) headers+       rawRows <- mapM (fmap padRow . mapM (blockListToMarkdown opts)) rows+       f (all null headers) aligns' widths' rawHeaders rawRows+  case True of+     _ | isSimple &&+         isEnabled Ext_simple_tables opts -> do+           tbl <- mkTable (pandocTable opts False)+           return $ nest 2 (tbl $$ caption''') $$ blankline+       | isSimple &&+         isEnabled Ext_pipe_tables opts -> do+           tbl <- mkTable (pipeTable opts)+           return $ (tbl $$ caption''') $$ blankline+       | not (hasBlocks || hasColRowSpans || hasFooter) &&+         isEnabled Ext_multiline_tables opts -> do+           tbl <- mkTable (pandocTable opts True)+           return $ nest 2 (tbl $$ caption''') $$ blankline+       | isEnabled Ext_grid_tables opts &&+          (hasColRowSpans || writerColumns opts >= 8 * numcols+                          || hasFooter) -> do+           tbl <- gridTable opts blockListToMarkdown+                     specs thead tbody tfoot+           return $ (tbl $$ caption''') $$ blankline+       | hasSimpleCells,+         not hasColRowSpans,+         isEnabled Ext_pipe_tables opts -> do+           tbl <- mkTable (pipeTable opts)+           return $ (tbl $$ caption''') $$ blankline+       | isEnabled Ext_raw_html opts -> do -- HTML fallback+           tbl <- literal . removeBlankLinesInHTML <$>+                     writeHtml5String opts{ writerTemplate = Nothing }+                     (Pandoc nullMeta [t])+           return $ tbl $$ blankline  -- caption is in the HTML table+       | hasSimpleCells,+         hasColRowSpans,+         isEnabled Ext_pipe_tables opts -> do+           -- In this case an approximate pipe table will be rendered,+           -- without col/row spans. This is better than nothing, since+           -- we have no other way to render the table correctly (#11128).+           tbl <- mkTable (pipeTable opts)+           return $ (tbl $$ caption''') $$ blankline+       | otherwise+         -> do+           report (BlockNotRendered t)+           return $ (literal "[TABLE]" $$ caption''') $$ blankline blockToMarkdown' opts (BulletList items) = do   contents <- inList $ mapM (bulletListItemToMarkdown opts) items   return $ (if isTightList items then vcat else vsep)@@ -692,31 +727,41 @@   return $ mconcat contents <> blankline blockToMarkdown' opts (Figure figattr capt body) = do   let combinedAttr imgattr = case imgattr of-        ("", cls, kv) | (figid, [], []) <- figattr -> Just (figid, cls, kv)-        _ -> Nothing-  let combinedAlt alt = case capt of-        Caption Nothing [] -> if null alt-                              then Just [Str "image"]-                              else Just alt-        Caption Nothing [Plain captInlines]-          | captInlines == alt || null alt -> Just captInlines+        ("", cls, kvs)+          | (figid, [], []) <- figattr+            -> Just (figid, cls, [(k,v) | (k,v) <- kvs+                                        , k /= "alt" ||+                                          v /= "" && v /= trim (stringify capt)])         _ -> Nothing   case body of     [Plain [Image imgAttr alt (src, ttl)]]       | isEnabled Ext_implicit_figures opts-      , Just descr    <- combinedAlt alt       , Just imgAttr' <- combinedAttr imgAttr       , isEnabled Ext_link_attributes opts || imgAttr' == nullAttr         -> do           -- use implicit figures if possible           let tgt' = (src, fromMaybe ttl $ T.stripPrefix "fig:" ttl)-          contents <- inlineListToMarkdown opts [Image imgAttr' descr tgt']+          let descr = case capt of+                        Caption _ bs -> blocksToInlines bs+          -- add alt attribute if image description different from caption,+          -- so this won't be lost:+          let imgAttr'' = case imgAttr' of+                            (i,c,kv)+                              | not (null alt)+                              , Nothing <- lookup "alt" kv+                              , stringify descr /= stringify alt ->+                                 (i, c, ("alt", stringify alt) : kv)+                            _ -> imgAttr'+          contents <- inlineListToMarkdown opts [Image imgAttr'' descr tgt']           return $ contents <> blankline     _ ->       -- fallback to raw html if possible or div otherwise       if isEnabled Ext_raw_html opts       then figureToMarkdown opts figattr capt body-      else blockToMarkdown' opts $ figureDiv figattr capt body+      else if (isEnabled Ext_fenced_divs opts || isEnabled Ext_native_divs opts) ||+                  not (isEnabled Ext_implicit_figures opts)+              then blockToMarkdown' opts $ figureDiv figattr capt body+              else blockListToMarkdown opts body  inList :: Monad m => MD m a -> MD m a inList p = local (\env -> env {envInList = True}) p@@ -743,8 +788,11 @@       writeHtml5String         opts{ writerTemplate = Nothing }         (Pandoc nullMeta [Figure attr capt body])-  | otherwise = let attr' = (ident, ["figure"] `union` classes, kvs)-                in blockToMarkdown' opts (Div attr' body)+  | otherwise = do+      let attr' = (ident, ["figure"] `union` classes, kvs)+      let Caption _mbshort caption = capt+      let captionBs = [Div ("",["caption"],[]) caption | not (null caption)]+      blockToMarkdown' opts (Div attr' (body <> captionBs))  itemEndsWithTightList :: [Block] -> Bool itemEndsWithTightList bs =@@ -762,7 +810,13 @@   let start = case variant of               Markua -> "* "               Commonmark -> "- "-              _ -> "- " <> T.replicate (writerTabStop opts - 2) " "+              Markdown+                | isEnabled Ext_four_space_rule opts+                  -> "- " <> T.replicate (writerTabStop opts - 2) " "+              PlainText+                | isEnabled Ext_four_space_rule opts+                  -> "- " <> T.replicate (writerTabStop opts - 2) " "+              _ -> "- "   -- remove trailing blank line if item ends with a tight list   let contents' = if itemEndsWithTightList bs                      then chomp contents <> cr@@ -807,26 +861,23 @@        let tabStop = writerTabStop opts        variant <- asks envVariant        let leader  = case variant of-                        PlainText -> "   "-                        Markua -> ":"-                        _ -> ":  "-       let sps = case writerTabStop opts - 3 of-                      n | n > 0   -> literal $ T.replicate n " "-                      _ -> literal " "+                        PlainText -> " "+                        _ -> ":"+       let leadingChars = case tabStop of+                            -- Always use two leading characters for Markua+                            n | variant == Markua -> 2+                              | isEnabled Ext_four_space_rule opts+                              , n >= 2 -> n+                              | otherwise -> 2+       let sps = literal $ T.replicate (leadingChars - 1) " "        let isTight = case defs of                         ((Plain _ : _): _) -> True                         _                  -> False-       if isEnabled Ext_compact_definition_lists opts-          then do-            let contents = vcat $ map (\d -> hang tabStop (leader <> sps)-                                $ vcat d <> cr) defs'-            return $ nowrap labelText <> cr <> contents <> cr-          else do-            let contents = (if isTight then vcat else vsep) $ map-                            (\d -> hang tabStop (leader <> sps) $ vcat d)-                            defs'-            return $ blankline <> nowrap labelText $$-                     (if isTight then empty else blankline) <> contents <> blankline+       let contents = (if isTight then vcat else vsep) $ map+                       (\d -> hang leadingChars (leader <> sps) $ vcat d)+                       defs'+       return $ blankline <> nowrap labelText $$+                (if isTight then empty else blankline) <> contents <> blankline      else        return $ nowrap (chomp labelText <> literal "  " <> cr) <>                 vsep (map vsep defs') <> blankline@@ -904,3 +955,14 @@  where    go (Div _ bls') n = max (n + 1) (foldr go (n + 1) bls')    go _ n = n++-- Identify the class in a list of classes that corresponds to+-- the language syntax.  language-X turns to X.+getLangFromClasses :: [Text] -> Maybe Text+getLangFromClasses cs =+  case find ("language-" `T.isPrefixOf`) cs of+    Just x -> Just (T.drop 9 x)+    Nothing ->+      case filter (/= "sourceCode") cs of+        (x:_) -> Just x+        [] -> Nothing
src/Text/Pandoc/Writers/Markdown/Inline.hs view
@@ -3,7 +3,7 @@ {-# LANGUAGE ViewPatterns        #-} {- |    Module      : Text.Pandoc.Writers.Markdown.Inline-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -74,6 +74,9 @@     | isEnabled Ext_smart opts = '\\':'-':go('-':cs)   go ('.':'.':'.':cs)     | isEnabled Ext_smart opts = '\\':'.':'.':'.':go cs+  go (':':':':':':cs)+    | isEnabled Ext_fenced_divs opts -- see #11571+    = '\\':':':':':':': (takeWhile (==':') cs ++ go cs)   go (c:'_':d:cs)     | isAlphaNum c     , isAlphaNum d =@@ -89,6 +92,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@@ -365,14 +371,16 @@                         tagWithAttrs "span" attrs <> contents <> literal "</span>"                       | otherwise -> contents inlineToMarkdown _ (Emph []) = return empty+inlineToMarkdown opts (Emph [Emph ils]) = -- #10642+  inlineListToMarkdown opts ils inlineToMarkdown opts (Emph lst) = do   variant <- asks envVariant   contents <- inlineListToMarkdown opts lst   return $ case variant of              PlainText-               | isEnabled Ext_gutenberg opts -> "_" <> contents <> "_"+               | isEnabled Ext_gutenberg opts -> delimited "_" "_" contents                | otherwise ->  contents-             _ -> "*" <> contents <> "*"+             _ -> delimited "*" "*" contents inlineToMarkdown _ (Underline []) = return empty inlineToMarkdown opts (Underline lst) = do   variant <- asks envVariant@@ -380,7 +388,7 @@   case variant of     PlainText -> return contents     _     | isEnabled Ext_bracketed_spans opts ->-            return $ "[" <> contents <> "]" <> "{.underline}"+            return $ delimited "[" "]{.underline}" contents           | isEnabled Ext_native_spans opts ->             return $ tagWithAttrs "span" ("", ["underline"], [])               <> contents@@ -399,12 +407,12 @@                   else lst     _ -> do        contents <- inlineListToMarkdown opts lst-       return $ "**" <> contents <> "**"+       return $ delimited "**" "**" contents inlineToMarkdown _ (Strikeout []) = return empty inlineToMarkdown opts (Strikeout lst) = do   contents <- inlineListToMarkdown opts lst   return $ if isEnabled Ext_strikeout opts-              then "~~" <> contents <> "~~"+              then delimited "~~" "~~" contents               else if isEnabled Ext_raw_html opts                        then "<s>" <> contents <> "</s>"                        else contents@@ -413,7 +421,7 @@   local (\env -> env {envEscapeSpaces = envVariant env == Markdown}) $ do     contents <- inlineListToMarkdown opts lst     if isEnabled Ext_superscript opts-       then return $ "^" <> contents <> "^"+       then return $ delimited "^" "^" contents        else if isEnabled Ext_raw_html opts                 then return $ "<sup>" <> contents <> "</sup>"                 else@@ -431,7 +439,7 @@   local (\env -> env {envEscapeSpaces = envVariant env == Markdown}) $ do     contents <- inlineListToMarkdown opts lst     if isEnabled Ext_subscript opts-       then return $ "~" <> contents <> "~"+       then return $ delimited "~" "~" contents        else if isEnabled Ext_raw_html opts                 then return $ "<sub>" <> contents <> "</sub>"                 else@@ -498,22 +506,24 @@                         else escapeText opts) $ str   return $ literal str' inlineToMarkdown opts (Math InlineMath str) = do+  let str' = T.strip str   variant <- asks envVariant   case () of     _ | variant == Markua -> return $ "`" <> literal str <> "`" <> "$"       | otherwise -> case writerHTMLMathMethod opts of           WebTeX url ->-            let str' = T.strip str-             in inlineToMarkdown opts+             inlineToMarkdown opts                   (Image nullAttr [Str str'] (url <> urlEncode str', str'))-          _ | isEnabled Ext_tex_math_dollars opts ->-                return $ "$" <> literal str <> "$"+          _ | isEnabled Ext_tex_math_gfm opts ->+                return $ "$`" <> literal str' <> "`$"+            | isEnabled Ext_tex_math_dollars opts ->+                return $ "$" <> literal str' <> "$"             | isEnabled Ext_tex_math_single_backslash opts ->-                return $ "\\(" <> literal str <> "\\)"+                return $ "\\(" <> literal str' <> "\\)"             | isEnabled Ext_tex_math_double_backslash opts ->-                return $ "\\\\(" <> literal str <> "\\\\)"+                return $ "\\\\(" <> literal str' <> "\\\\)"             | otherwise ->-                texMathToInlines InlineMath str >>=+                texMathToInlines InlineMath str' >>=                   inlineListToMarkdown opts .                     (if variant == PlainText then makeMathPlainer else id) @@ -531,7 +541,11 @@              in (\x -> blankline <> x <> blankline) `fmap`                  inlineToMarkdown opts (Image nullAttr [Str str']                         (url <> urlEncode str', str'))-          _ | isEnabled Ext_tex_math_dollars opts ->+          _ | isEnabled Ext_tex_math_gfm opts ->+                return $ cr <> (literal "``` math"+                             $$ literal (T.dropAround (=='\n') str)+                             $$ literal "```") <> cr+            | isEnabled Ext_tex_math_dollars opts ->                 return $ "$$" <> literal str <> "$$"             | isEnabled Ext_tex_math_single_backslash opts ->                 return $ "\\[" <> literal str <> "\\]"@@ -575,7 +589,7 @@   if variant == PlainText || isEnabled Ext_hard_line_breaks opts      then return cr      else return $-          if isEnabled Ext_escaped_line_breaks opts+          if variant == Commonmark || isEnabled Ext_escaped_line_breaks opts              then "\\" <> cr              else "  " <> cr inlineToMarkdown _ Space = do@@ -643,7 +657,7 @@                 case txt of                       [Str s] | escapeURI s == srcSuffix -> True                       _       -> False-  let useWikilink = tit == "wikilink" &&+  let useWikilink = "wikilink" `elem` classes &&                     (isEnabled Ext_wikilinks_title_after_pipe opts ||                      isEnabled Ext_wikilinks_title_before_pipe opts)   let useRefLinks = writerReferenceLinks opts && not useAuto@@ -724,19 +738,3 @@   where   go (Emph xs) = Span nullAttr xs   go x         = x--toSubscriptInline :: Inline -> Maybe Inline-toSubscriptInline Space = Just Space-toSubscriptInline (Span attr ils) = Span attr <$> traverse toSubscriptInline ils-toSubscriptInline (Str s) = Str . T.pack <$> traverse toSubscript (T.unpack s)-toSubscriptInline LineBreak = Just LineBreak-toSubscriptInline SoftBreak = Just SoftBreak-toSubscriptInline _ = Nothing--toSuperscriptInline :: Inline -> Maybe Inline-toSuperscriptInline Space = Just Space-toSuperscriptInline (Span attr ils) = Span attr <$> traverse toSuperscriptInline ils-toSuperscriptInline (Str s) = Str . T.pack <$> traverse toSuperscript (T.unpack s)-toSuperscriptInline LineBreak = Just LineBreak-toSuperscriptInline SoftBreak = Just SoftBreak-toSuperscriptInline _ = Nothing
src/Text/Pandoc/Writers/Markdown/Table.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings   #-} {- |    Module      : Text.Pandoc.Writers.Markdown-   Copyright   : © 2006-2023 John MacFarlane+   Copyright   : © 2006-2024 John MacFarlane    License     : GPL-2.0-or-later    Maintainer  : John MacFarlane <jgm@berkeley.edu> @@ -36,15 +36,18 @@           -> MD m (Doc Text) pipeTable opts headless aligns widths rawHeaders rawRows = do   let sp = literal " "-  let blockFor AlignLeft   x y = lblock (x + 2) (sp <> y) <> lblock 0 empty-      blockFor AlignCenter x y = cblock (x + 2) (sp <> y <> sp) <> lblock 0 empty-      blockFor AlignRight  x y = rblock (x + 2) (y <> sp) <> lblock 0 empty-      blockFor _           x y = lblock (x + 2) (sp <> y) <> lblock 0 empty   let contentWidths = map (max 3 . maybe 3 maximum . nonEmpty . map offset) $                        transpose (rawHeaders : rawRows)   let colwidth = writerColumns opts   let numcols = length contentWidths   let maxwidth = sum contentWidths+  -- if cell contents are > COLUMNS, adding padding looks bad+  let pad = maxwidth <= writerColumns opts+  let blockFor _ _ y | not pad = sp <> y <> sp <> lblock 0 empty+      blockFor AlignLeft   x y = lblock (x + 2) (sp <> y) <> lblock 0 empty+      blockFor AlignCenter x y = cblock (x + 2) (sp <> y <> sp) <> lblock 0 empty+      blockFor AlignRight  x y = rblock (x + 2) (y <> sp) <> lblock 0 empty+      blockFor AlignDefault x y = lblock (x + 2) (sp <> y) <> lblock 0 empty   variant <- asks envVariant   let pipeWidths = if variant == Markdown &&                       not (all (== 0) widths) &&@@ -54,7 +57,9 @@                               floor .                                 (* fromIntegral (colwidth - (numcols +1))))                             widths-                      else contentWidths+                      else if pad+                              then contentWidths+                              else map (const 2) widths   let torow cs = nowrap $ literal "|" <>                     hcat (intersperse (literal "|") $                           zipWith3 blockFor aligns contentWidths (map chomp cs))
src/Text/Pandoc/Writers/Markdown/Types.hs view
@@ -1,6 +1,6 @@ {- |    Module      : Text.Pandoc.Writers.Markdown.Types-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>
src/Text/Pandoc/Writers/MediaWiki.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Writers.MediaWiki-   Copyright   : Copyright (C) 2008-2023 John MacFarlane+   Copyright   : Copyright (C) 2008-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -26,8 +26,7 @@ import Text.Pandoc.ImageSize import Text.Pandoc.Logging import Text.Pandoc.Options-import Text.Pandoc.Walk-import Text.DocLayout (render, literal)+import Text.DocLayout import Text.Pandoc.Shared import Text.Pandoc.URI import Text.Pandoc.Templates (renderTemplate)@@ -38,6 +37,7 @@ data WriterState = WriterState {     stNotes   :: Bool            -- True if there are notes   , stOptions :: WriterOptions   -- writer options+  , stInDefLabel :: Bool         -- True if in definition list label   }  data WriterReader = WriterReader {@@ -51,7 +51,8 @@ -- | Convert Pandoc to MediaWiki. writeMediaWiki :: PandocMonad m => WriterOptions -> Pandoc -> m Text writeMediaWiki opts document =-  let initialState = WriterState { stNotes = False, stOptions = opts }+  let initialState = WriterState {+        stNotes = False, stOptions = opts, stInDefLabel = False }       env = WriterReader { options = opts, listLevel = [], useTags = False }   in  evalStateT (runReaderT (pandocToMediaWiki document) env) initialState @@ -60,21 +61,21 @@ pandocToMediaWiki (Pandoc meta blocks) = do   opts <- asks options   metadata <- metaToContext opts-              (fmap (literal . trimr) . blockListToMediaWiki)-              (fmap (literal . trimr) . inlineListToMediaWiki)+              (fmap chomp . blockListToMediaWiki)+              (fmap chomp . inlineListToMediaWiki)               meta   body <- blockListToMediaWiki blocks   notesExist <- gets stNotes   let notes = if notesExist-                 then "\n<references />"-                 else ""+                 then cr <> literal "<references />"+                 else mempty   let main = body <> notes   let context = defField "body" main                 $ defField "toc" (writerTableOfContents opts) metadata-  return $+  return $ render Nothing $     case writerTemplate opts of          Nothing  -> main-         Just tpl -> render Nothing $ renderTemplate tpl context+         Just tpl -> renderTemplate tpl context  -- | Escape special characters for MediaWiki. escapeText :: Text -> Text@@ -83,12 +84,14 @@ -- | Convert Pandoc block element to MediaWiki. blockToMediaWiki :: PandocMonad m                  => Block         -- ^ Block element-                 -> MediaWikiWriter m Text+                 -> MediaWikiWriter m (Doc Text)  blockToMediaWiki (Div attrs bs) = do   contents <- blockListToMediaWiki bs-  return $ render Nothing (tagWithAttrs "div" attrs) <> "\n\n" <>-                     contents <> "\n\n" <> "</div>"+  return $ tagWithAttrs "div" attrs $$+            contents $$+            literal "</div>" $$+            blankline  blockToMediaWiki (Plain inlines) =   inlineListToMediaWiki inlines@@ -96,57 +99,69 @@ blockToMediaWiki (SimpleFigure attr txt (src, tit)) = do   capt <- inlineListToMediaWiki txt   img  <- imageToMediaWiki attr+  let capt' = render Nothing capt   let opt = if T.null tit                then-                 if T.null capt+                 if T.null capt'                     then ""-                    else "alt=" <> capt+                    else "alt=" <> capt'                else "alt=" <> tit-  return $ "[[" <>-            T.intercalate "|"-            (filter (not . T.null) ["File:" <> src-                                 , "thumb"-                                 , "none"-                                 , img-                                 , opt-                                 , capt-                                 ]) <>-            "]]\n"+  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   lev <- asks listLevel   contents <- inlineListToMediaWiki inlines+  let contents' = render Nothing contents+  let initEsc = if startsWithListMarker contents'+                   then literal "<nowiki></nowiki>"+                   else mempty   return $ if tags-              then  "<p>" <> contents <> "</p>"-              else contents <> if null lev then "\n" else ""+              then literal "<p>" <> contents <> literal "</p>"+              else initEsc <> contents $$+                   if null lev then blankline else mempty  blockToMediaWiki (LineBlock lns) =   blockToMediaWiki $ linesToPara lns  blockToMediaWiki b@(RawBlock f str)-  | f == Format "mediawiki" = return str-  | f == Format "html"      = return str-  | otherwise               = "" <$ report (BlockNotRendered b)+  | f == Format "mediawiki" = return $ literal str+  | f == Format "html"      = return $ literal str+  | otherwise               = mempty <$ report (BlockNotRendered b) -blockToMediaWiki HorizontalRule = return "\n-----\n"+blockToMediaWiki HorizontalRule = return $ blankline <> literal "-----" <> blankline  blockToMediaWiki (Header level (ident,_,_) inlines) = do   let autoId = T.replace " " "_" $ stringify inlines   contents <- inlineListToMediaWiki inlines-  let eqs = T.replicate level "="+  let eqs = literal $ T.replicate level "="   return $     (if T.null ident || autoId == ident-        then ""-        else "<span id=\"" <> ident <> "\"></span>\n")-    <> eqs <> " " <> contents <> " " <> eqs <> "\n"+        then mempty+        else literal ("<span id=\"" <> ident <> "\"></span>") <> cr)+    <> eqs <> space <> contents <> space <> eqs <> blankline  blockToMediaWiki (CodeBlock (_,classes,keyvals) str) = do   let at  = Set.fromList classes `Set.intersection` highlightingLangs   let numberLines = any (`elem` ["number","numberLines", "number-lines"])                     classes   let start = lookup "startFrom" keyvals-  return $+  return $ literal $     case Set.toList at of        [] -> "<pre" <> (if null classes                            then ">"@@ -161,7 +176,7 @@  blockToMediaWiki (BlockQuote blocks) = do   contents <- blockListToMediaWiki blocks-  return $ "<blockquote>" <> contents <> "</blockquote>"+  return $ literal "<blockquote>" <> chomp contents <> cr <> literal "</blockquote>"  blockToMediaWiki (Table attr capt colSpecs thead tbody tfoot) = do     tableToMediaWiki (Ann.toTable attr capt colSpecs thead tbody tfoot)@@ -172,11 +187,11 @@   if tags      then do         contents <- local (\ s -> s { useTags = True }) $ mapM listItemToMediaWiki items-        return $ "<ul>\n" <> vcat contents <> "</ul>\n"+        return $ literal "<ul>" <> cr <> vcat contents <> literal "</ul>" <> blankline      else do         lev <- asks listLevel         contents <- local (\s -> s { listLevel = listLevel s <> "*" }) $ mapM listItemToMediaWiki items-        return $ vcat contents <> if null lev then "\n" else ""+        return $ vcat contents <> if null lev then blankline else mempty  blockToMediaWiki x@(OrderedList attribs items) = do   tags <-@@ -184,11 +199,11 @@   if tags      then do         contents <- local (\s -> s { useTags = True }) $ mapM listItemToMediaWiki items-        return $ "<ol" <> listAttribsToText attribs <> ">\n" <> vcat contents <> "</ol>\n"+        return $ literal ("<ol" <> listAttribsToText attribs <> ">") <> cr <> vcat contents <> literal "</ol>" <> blankline      else do         lev <- asks listLevel         contents <- local (\s -> s { listLevel = listLevel s <> "#" }) $ mapM listItemToMediaWiki items-        return $ vcat contents <> if null lev then "\n" else ""+        return $ vcat contents <> if null lev then blankline else mempty  blockToMediaWiki x@(DefinitionList items) = do   tags <-@@ -196,11 +211,11 @@   if tags      then do         contents <- local (\s -> s { useTags = True }) $ mapM definitionListItemToMediaWiki items-        return $ "<dl>\n" <> vcat contents <> "</dl>\n"+        return $ literal "<dl>" <> cr <> vcat contents <> literal "</dl>" <> blankline      else do         lev <- asks listLevel         contents <- local (\s -> s { listLevel = listLevel s <> ";" }) $ mapM definitionListItemToMediaWiki items-        return $ vcat contents <> if null lev then "\n" else ""+        return $ vcat contents <> if null lev then blankline else mempty  blockToMediaWiki (Figure (ident, classes, kvs) _ body) =   blockToMediaWiki (Div (ident, ["figure"] `DL.union` classes, kvs) body)@@ -219,31 +234,33 @@           else "")  -- | Convert bullet or ordered list item (list of blocks) to MediaWiki.-listItemToMediaWiki :: PandocMonad m => [Block] -> MediaWikiWriter m Text+listItemToMediaWiki :: PandocMonad m => [Block] -> MediaWikiWriter m (Doc Text) listItemToMediaWiki items = do   contents <- blockListToMediaWiki items   tags <- asks useTags   if tags-     then return $ "<li>" <> contents <> "</li>"+     then return $ literal "<li>" <> chomp contents <> literal "</li>"      else do        marker <- asks listLevel-       return $ T.pack marker <> " " <> contents+       return $ literal (T.pack marker) <> space <> chomp contents  -- | Convert definition list item (label, list of blocks) to MediaWiki. definitionListItemToMediaWiki :: PandocMonad m                               => ([Inline],[[Block]])-                              -> MediaWikiWriter m Text+                              -> MediaWikiWriter m (Doc Text) definitionListItemToMediaWiki (label, items) = do+  modify $ \st -> st{ stInDefLabel = True }   labelText <- inlineListToMediaWiki label+  modify $ \st -> st{ stInDefLabel = False }   contents <- mapM blockListToMediaWiki items   tags <- asks useTags   if tags-     then return $ "<dt>" <> labelText <> "</dt>\n" <>-           T.intercalate "\n" (map (\d -> "<dd>" <> d <> "</dd>") contents)+     then return $ literal "<dt>" <> chomp labelText <> literal "</dt>" <> cr <>+           vcat (map (\d -> literal "<dd>" <> chomp d <> literal "</dd>") contents)      else do        marker <- asks listLevel-       return $ T.pack marker <> " " <> labelText <> "\n" <>-           T.intercalate "\n" (map (\d -> T.pack (init marker) <> ": " <> d) contents)+       return $ literal (T.pack marker) <> space <> chomp labelText <> cr <>+           vcat (map (\d -> literal (T.pack (init marker)) <> literal ": " <> chomp d) contents)  -- | True if the list can be handled by simple wiki markup, False if HTML tags will be needed. isSimpleList :: Block -> Bool@@ -280,59 +297,53 @@ isPlainOrPara (Para  _) = True isPlainOrPara _         = False --- | Concatenates strings with line breaks between them.-vcat :: [Text] -> Text-vcat = T.intercalate "\n"- -- Auxiliary functions for tables: -tableToMediaWiki :: PandocMonad m => Ann.Table -> MediaWikiWriter m Text+tableToMediaWiki :: PandocMonad m => Ann.Table -> MediaWikiWriter m (Doc Text) tableToMediaWiki (Ann.Table attr capt _ thead tbodies tfoot) = do     let (ident,classes,kvs) = attr     caption <- case capt of         Caption _ [] -> return mempty         Caption _ longCapt -> do             c <- blockListToMediaWiki longCapt-            return [ "|+ " <> trimr c ]+            return $ literal "|+ " <> chomp c <> cr     head' <- tableHeadToMW thead-    bodies' <- concat <$> mapM tableBodyToMW tbodies+    bodies' <- mconcat <$> mapM tableBodyToMW tbodies     foot' <- tableFootToMW tfoot-    return $ T.unlines $ [-            "{|" <> (render Nothing (htmlAttrs (ident, "wikitable":classes, kvs)))-        ] <> caption <> head' <> bodies' <> foot' <> [-            "|}"-        ]+    return $ literal "{|" <> htmlAttrs (ident, "wikitable":classes, kvs) <> cr+             <> caption <> head' <> bodies' <> foot'+             <> literal "|}" <> blankline -tableHeadToMW :: PandocMonad m => Ann.TableHead -> MediaWikiWriter m [Text]+tableHeadToMW :: PandocMonad m => Ann.TableHead -> MediaWikiWriter m (Doc Text) tableHeadToMW (Ann.TableHead _ rows) = headerRowsToMW rows -tableFootToMW :: PandocMonad m => Ann.TableFoot -> MediaWikiWriter m [Text]+tableFootToMW :: PandocMonad m => Ann.TableFoot -> MediaWikiWriter m (Doc Text) tableFootToMW (Ann.TableFoot _ rows) = headerRowsToMW rows -tableBodyToMW :: PandocMonad m => Ann.TableBody -> MediaWikiWriter m [Text]+tableBodyToMW :: PandocMonad m => Ann.TableBody -> MediaWikiWriter m (Doc Text) tableBodyToMW (Ann.TableBody _ _ headerRows bodyRows) = do   headerRows' <- headerRowsToMW headerRows   bodyRows' <- bodyRowsToMW bodyRows   return $ headerRows' <> bodyRows' -headerRowsToMW :: PandocMonad m => [Ann.HeaderRow] -> MediaWikiWriter m [Text]-headerRowsToMW rows = (\x -> mconcat x) <$> mapM headerRowToMW rows+headerRowsToMW :: PandocMonad m => [Ann.HeaderRow] -> MediaWikiWriter m (Doc Text)+headerRowsToMW rows = mconcat <$> mapM headerRowToMW rows -headerRowToMW :: PandocMonad m => Ann.HeaderRow -> MediaWikiWriter m [Text]+headerRowToMW :: PandocMonad m => Ann.HeaderRow -> MediaWikiWriter m (Doc Text) headerRowToMW (Ann.HeaderRow attr _ cells) = do-  cells' <- (\x -> mconcat x) <$> mapM (cellToMW "!") cells-  return $ ["|-" <> (render Nothing (htmlAttrs attr))] <> cells'+  cells' <- mconcat <$> mapM (cellToMW "!") cells+  return $ literal "|-" <> htmlAttrs attr <> cr <> cells' -bodyRowsToMW :: PandocMonad m => [Ann.BodyRow] -> MediaWikiWriter m [Text]-bodyRowsToMW rows = (\x -> mconcat x) <$> mapM bodyRowToMW rows+bodyRowsToMW :: PandocMonad m => [Ann.BodyRow] -> MediaWikiWriter m (Doc Text)+bodyRowsToMW rows = mconcat <$> mapM bodyRowToMW rows -bodyRowToMW :: PandocMonad m => Ann.BodyRow -> MediaWikiWriter m [Text]+bodyRowToMW :: PandocMonad m => Ann.BodyRow -> MediaWikiWriter m (Doc Text) bodyRowToMW (Ann.BodyRow attr _ headCells bodyCells) = do-  headCells' <- (\x -> mconcat x) <$> mapM (cellToMW "!") headCells-  bodyCells' <- (\x -> mconcat x) <$> mapM (cellToMW "|") bodyCells-  return $ ["|-" <> (render Nothing (htmlAttrs attr))] <> headCells' <> bodyCells'+  headCells' <- mconcat <$> mapM (cellToMW "!") headCells+  bodyCells' <- mconcat <$> mapM (cellToMW "|") bodyCells+  return $ literal "|-" <> htmlAttrs attr <> cr <> headCells' <> bodyCells' -cellToMW :: PandocMonad m => Text -> Ann.Cell -> MediaWikiWriter m [Text]+cellToMW :: PandocMonad m => Text -> Ann.Cell -> MediaWikiWriter m (Doc Text) cellToMW marker (Ann.Cell (colSpec :| _) _ (Cell attr align rowspan colspan content)) = do   content' <- blockListToMediaWiki content   let (ident,classes,keyVals) = attr@@ -349,14 +360,12 @@   let colspan' = case colspan of                   ColSpan 1 -> mempty                   ColSpan n -> [("colspan", T.pack(show n))]-  let attrs' = addPipeIfNotEmpty (render Nothing (htmlAttrs (ident, classes, rowspan' <> colspan' <> keyVals')))-  return [marker <> attrs' <> addSpaceIfNotEmpty(content')]--addPipeIfNotEmpty :: Text -> Text-addPipeIfNotEmpty f = if T.null f then f else f <> "|"--addSpaceIfNotEmpty :: Text -> Text-addSpaceIfNotEmpty f = if T.null f then f else " " <> f+  let attrs' = htmlAttrs (ident, classes, rowspan' <> colspan' <> keyVals')+  let attrsRendered = render Nothing attrs'+  let pipeAttr = if T.null attrsRendered then mempty else attrs' <> literal "|"+  let contentRendered = render Nothing content'+  let spaceContent = if T.null contentRendered then mempty else space <> chomp content'+  return $ literal marker <> pipeAttr <> spaceContent <> cr  imageToMediaWiki :: PandocMonad m => Attr -> MediaWikiWriter m Text imageToMediaWiki attr = do@@ -378,14 +387,14 @@ -- | Convert list of Pandoc block elements to MediaWiki. blockListToMediaWiki :: PandocMonad m                      => [Block]       -- ^ List of block elements-                     -> MediaWikiWriter m Text+                     -> MediaWikiWriter m (Doc Text) blockListToMediaWiki blocks =   vcat <$> mapM blockToMediaWiki blocks  -- | Convert list of Pandoc inline elements to MediaWiki.-inlineListToMediaWiki :: PandocMonad m => [Inline] -> MediaWikiWriter m Text+inlineListToMediaWiki :: PandocMonad m => [Inline] -> MediaWikiWriter m (Doc Text) inlineListToMediaWiki lst =-  fmap T.concat $ mapM inlineToMediaWiki $ fixup lst+  hcat <$> mapM inlineToMediaWiki (fixup lst)     where      fixup [] = []      fixup (Str t : x : xs)@@ -398,121 +407,131 @@      isLinkOrImage _         = False  -- | Convert Pandoc inline element to MediaWiki.-inlineToMediaWiki :: PandocMonad m => Inline -> MediaWikiWriter m Text+inlineToMediaWiki :: PandocMonad m => Inline -> MediaWikiWriter m (Doc Text)  inlineToMediaWiki (Span attrs ils) = do   contents <- inlineListToMediaWiki ils-  return $ render Nothing (tagWithAttrs "span" attrs) <> contents <> "</span>"+  return $ tagWithAttrs "span" attrs <> contents <> literal "</span>"  inlineToMediaWiki (Emph lst) = do   contents <- inlineListToMediaWiki lst-  return $ "''" <> contents <> "''"+  return $ literal "''" <> contents <> literal "''"  inlineToMediaWiki (Underline lst) = do   contents <- inlineListToMediaWiki lst-  return $ "<u>" <> contents <> "</u>"+  return $ literal "<u>" <> contents <> literal "</u>"  inlineToMediaWiki (Strong lst) = do   contents <- inlineListToMediaWiki lst-  return $ "'''" <> contents <> "'''"+  return $ literal "'''" <> contents <> literal "'''"  inlineToMediaWiki (Strikeout lst) = do   contents <- inlineListToMediaWiki lst-  return $ "<s>" <> contents <> "</s>"+  return $ literal "<s>" <> contents <> literal "</s>"  inlineToMediaWiki (Superscript lst) = do   contents <- inlineListToMediaWiki lst-  return $ "<sup>" <> contents <> "</sup>"+  return $ literal "<sup>" <> contents <> literal "</sup>"  inlineToMediaWiki (Subscript lst) = do   contents <- inlineListToMediaWiki lst-  return $ "<sub>" <> contents <> "</sub>"+  return $ literal "<sub>" <> contents <> literal "</sub>"  inlineToMediaWiki (SmallCaps lst) = inlineListToMediaWiki lst  inlineToMediaWiki (Quoted SingleQuote lst) = do   contents <- inlineListToMediaWiki lst-  return $ "\8216" <> contents <> "\8217"+  return $ literal "\8216" <> contents <> literal "\8217"  inlineToMediaWiki (Quoted DoubleQuote lst) = do   contents <- inlineListToMediaWiki lst-  return $ "\8220" <> contents <> "\8221"+  return $ literal "\8220" <> contents <> literal "\8221"  inlineToMediaWiki (Cite _  lst) = inlineListToMediaWiki lst  inlineToMediaWiki (Code _ str) =-  return $ "<code>" <> escapeText str <> "</code>"+  return $ literal $ "<code>" <> escapeText str <> "</code>" -inlineToMediaWiki (Str str) = return $ escapeText str+inlineToMediaWiki (Str str) = do+  inDefLabel <- gets stInDefLabel+  return $ literal $+    if inDefLabel+       then T.intercalate "<nowiki>:</nowiki>" $+              map escapeText $ T.splitOn ":" str+       else escapeText str -inlineToMediaWiki (Math mt str) = return $+inlineToMediaWiki (Math mt str) = return $ literal $   "<math display=\"" <>   (if mt == DisplayMath then "block" else "inline") <>   "\">" <> str <> "</math>"   -- note:  str should NOT be escaped  inlineToMediaWiki il@(RawInline f str)-  | f == Format "mediawiki" = return str-  | f == Format "html"      = return str-  | otherwise               = "" <$ report (InlineNotRendered il)+  | f == Format "mediawiki" = return $ literal str+  | f == Format "html"      = return $ literal str+  | otherwise               = mempty <$ report (InlineNotRendered il) -inlineToMediaWiki LineBreak = return "<br />\n"+inlineToMediaWiki LineBreak = return $ literal "<br />" <> cr  inlineToMediaWiki SoftBreak = do   wrapText <- gets (writerWrapText . stOptions)   listlevel <- asks listLevel   case wrapText of-       WrapAuto     -> return " "-       WrapNone     -> return " "+       WrapAuto     -> return space+       WrapNone     -> return space        WrapPreserve -> if null listlevel-                          then return "\n"-                          else return " "+                          then return cr+                          else return space -inlineToMediaWiki Space = return " "+inlineToMediaWiki Space = return space  inlineToMediaWiki (Link _ txt (src, _)) = do+  -- We need to remove links from link text, because an <a> element is+  -- not allowed inside another <a> element.   label <- inlineListToMediaWiki (removeLinks txt)+  let label' = render Nothing label   case txt of-     [Str s] | isURI src && escapeURI s == src -> return src-     _  -> return $ if isURI src-       then "[" <> src <> " " <> label <> "]"+     [Str s] | isURI src && escapeURI s == src -> return $ literal src+     _  -> return $ literal $ if isURI (T.takeWhile (/= '#') src) -- see #11562+       then "[" <> src <> " " <> label' <> "]"        else-         if src == label+         if src == label'            then "[[" <> src' <> "]]"-           else "[[" <> src' <> "|" <> label <> "]]"+           else "[[" <> src' <> "|" <> label' <> "]]"        -- with leading / it's a link to a help page        where src' = fromMaybe src $ T.stripPrefix "/" src  inlineToMediaWiki (Image attr alt (source, tit)) = do-  img  <- imageToMediaWiki attr-  alt' <- inlineListToMediaWiki alt-  let txt = if T.null alt'-               then if T.null tit-                       then ""-                       else tit-               else alt'-  return $ "[[" <>-           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   modify (\s -> s { stNotes = True })-  return $ "<ref>" <> stripTrailingNewlines contents' <> "</ref>"+  let rendered = render Nothing contents'+  return $ literal $ "<ref>" <> stripTrailingNewlines rendered <> "</ref>"   -- note - does not work for notes with multiple blocks --- We need to remove links from link text, because an <a> element is--- not allowed inside another <a> element.-removeLinks :: [Inline] -> [Inline]-removeLinks = walk go- where-  go (Link _ ils _) = SmallCaps ils-  go x = x- highlightingLangs :: Set.Set Text highlightingLangs = Set.fromList [   "abap",@@ -1144,3 +1163,9 @@   "yaml",   "yaml+jinja",   "zephir" ]++startsWithListMarker :: Text -> Bool+startsWithListMarker t =+  case T.uncons t of+    Nothing -> False+    Just (c,_) -> c == '#' || c == ':' || c == ';' || c == '*'
src/Text/Pandoc/Writers/Ms.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE ViewPatterns      #-} {- |    Module      : Text.Pandoc.Writers.Ms-   Copyright   : Copyright (C) 2007-2023 John MacFarlane+   Copyright   : Copyright (C) 2007-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -28,7 +28,7 @@ import Data.List (intercalate, intersperse) import Data.List.NonEmpty (nonEmpty) import qualified Data.Map as Map-import Data.Maybe (catMaybes)+import Data.Maybe (catMaybes, isNothing) import Data.Text (Text) import qualified Data.Text as T import Network.URI (escapeURIString, isAllowedInURI)@@ -41,12 +41,14 @@ import Text.Pandoc.ImageSize import Text.Pandoc.Logging import Text.Pandoc.Options-import Text.DocLayout+import Text.DocLayout hiding (Color)+import Text.DocTemplates (lookupContext) import Text.Pandoc.Shared import Text.Pandoc.Templates (renderTemplate) import Text.Pandoc.Writers.Math import Text.Pandoc.Writers.Shared import Text.Pandoc.Writers.Roff+import Text.Pandoc.Writers.Markdown (writePlain) import Text.Printf (printf) import Text.TeXMath (writeEqn) import qualified Data.Text.Encoding as TE@@ -74,7 +76,9 @@   let authorsMeta = map (escapeStr opts . stringify) $ docAuthors meta   hasHighlighting <- gets stHighlighting   let highlightingMacros = if hasHighlighting-                              then maybe mempty styleToMs $ writerHighlightStyle opts+                              then case writerHighlightMethod opts of+                                     Skylighting sty -> styleToMs sty+                                     _ -> mempty                               else mempty    let context = defField "body" main@@ -92,14 +96,13 @@  escapeStr :: WriterOptions -> Text -> Text escapeStr opts =-  escapeString (if writerPreferAscii opts then AsciiOnly else AllowUTF8)+  escapeString False (if writerPreferAscii opts then AsciiOnly else AllowUTF8)  -- In PDFs we need to escape parentheses and backslash. -- In PDF we need to encode as UTF-16 BE. escapePDFString :: Text -> Text escapePDFString t-  | T.all isAscii t =-    T.replace "(" "\\(" .  T.replace ")" "\\)" . T.replace "\\" "\\\\" $ t+  | T.all (\c -> isAscii c && c /= '(' && c /= ')' && c /= '\\' && c /= '"') t = t   | otherwise = ("\\376\\377" <>) .  -- add bom     mconcat . map encodeChar .  T.unpack $ t  where@@ -127,12 +130,15 @@ -- line.  roff treats the line-ending period differently. -- See http://code.google.com/p/pandoc/issues/detail?id=148. +getPdfEngine :: WriterOptions -> Maybe Text+getPdfEngine opts = lookupContext "pdf-engine" (writerVariables opts)+ blockToMs :: PandocMonad m           => WriterOptions -- ^ Options           -> Block         -- ^ Block element           -> MS m (Doc Text) blockToMs opts (Div (ident,cls,kvs) bs) = do-  let anchor = if T.null ident+  let anchor = if isNothing (getPdfEngine opts) || T.null ident                   then empty                   else nowrap $                          literal ".pdfhref M "@@ -181,23 +187,30 @@ blockToMs opts (Header level (ident,classes,_) inlines) = do   setFirstPara   modify $ \st -> st{ stInHeader = True }-  contents <- inlineListToMs' opts $ map breakToSpace inlines+  let inlines' = map breakToSpace inlines+  contents <- inlineListToMs' opts inlines'+  plainContents <- inlinesToPlain inlines'   modify $ \st -> st{ stInHeader = False }   let (heading, secnum) = if writerNumberSections opts &&                               "unnumbered" `notElem` classes                              then (".NH", "\\*[SN]")                              else (".SH", "")+  let mbPdfEngine = getPdfEngine opts   let anchor = if T.null ident                   then empty                   else nowrap $                          literal ".pdfhref M "                          <> doubleQuotes (literal (toAscii ident))   let bookmark = literal ".pdfhref O " <> literal (tshow level <> " ") <>-                      doubleQuotes (literal $ secnum <>+                      nowrap (doubleQuotes+                              (literal $ secnum <>                                       (if T.null secnum                                           then ""                                           else "  ") <>-                                      escapePDFString (stringify inlines))+                                      (case mbPdfEngine of+                                         Just "groff" -> id+                                         _ -> escapePDFString)+                                        plainContents))   let backlink = nowrap (literal ".pdfhref L -D " <>        doubleQuotes (literal (toAscii ident)) <> space <> literal "\\") <> cr <>        literal " -- "@@ -215,9 +228,9 @@   modify $ \st -> st{ stFirstPara = True }   return $ (literal heading <> space <> literal (tshow level)) $$            contents $$-           bookmark $$-           anchor $$-           tocEntry+           case mbPdfEngine of+             Nothing -> mempty+             Just _ -> bookmark $$ anchor $$ tocEntry blockToMs opts (CodeBlock attr str) = do   hlCode <- highlightCode opts attr str   setFirstPara@@ -328,7 +341,7 @@ bulletListItemToMs opts (Plain first:rest) = do   first' <- blockToMs opts (Plain first)   rest' <- blockListToMs opts rest-  let first'' = literal ".IP \\[bu] 3" $$ first'+  let first'' = literal ".IP \\(bu 3" $$ first'   let rest''  = if null rest                    then empty                    else literal ".RS 3" $$ rest' $$ literal ".RE"@@ -336,7 +349,7 @@ bulletListItemToMs opts (first:rest) = do   first' <- blockToMs opts first   rest' <- blockListToMs opts rest-  return $ literal "\\[bu] .RS 3" $$ first' $$ rest' $$ literal ".RE"+  return $ literal "\\(bu .RS 3" $$ first' $$ rest' $$ literal ".RE"  -- | Convert ordered list item (a list of blocks) to ms. orderedListItemToMs :: PandocMonad m@@ -435,7 +448,7 @@   return $ char '`' <> contents <> char '\'' inlineToMs opts (Quoted DoubleQuote lst) = do   contents <- inlineListToMs opts lst-  return $ literal "\\[lq]" <> contents <> literal "\\[rq]"+  return $ literal "\\(lq" <> contents <> literal "\\(rq" inlineToMs opts (Cite _ lst) =   inlineListToMs opts lst inlineToMs opts (Code attr str) = do@@ -479,17 +492,25 @@ inlineToMs opts (Link _ txt (T.uncons -> Just ('#',ident), _)) = do   -- internal link   contents <- inlineListToMs' opts $ map breakToSpace txt-  return $ literal "\\c" <> cr <> nowrap (literal ".pdfhref L -D " <>-       doubleQuotes (literal (toAscii ident)) <> literal " -A " <>-       doubleQuotes (literal "\\c") <> space <> literal "\\") <> cr <>-       literal " -- " <> doubleQuotes (nowrap contents) <> cr <> literal "\\&"+  return $+    case getPdfEngine opts of+      Just _ -> literal "\\c" <> cr <> nowrap (literal ".pdfhref L -D " <>+            doubleQuotes (literal (toAscii ident)) <> literal " -A " <>+            doubleQuotes (literal "\\c") <> space <> literal "\\") <> cr <>+            literal " -- " <> doubleQuotes (nowrap contents) <> cr <>+            literal "\\&"+      Nothing -> contents inlineToMs opts (Link _ txt (src, _)) = do   -- external link   contents <- inlineListToMs' opts $ map breakToSpace txt-  return $ literal "\\c" <> cr <> nowrap (literal ".pdfhref W -D " <>-       doubleQuotes (literal (escapeUri src)) <> literal " -A " <>-       doubleQuotes (literal "\\c") <> space <> literal "\\") <> cr <>-       literal " -- " <> doubleQuotes (nowrap contents) <> cr <> literal "\\&"+  return $+    case getPdfEngine opts of+      Just _ -> literal "\\c" <> cr <> nowrap (literal ".pdfhref W -D " <>+            doubleQuotes (literal (escapeUri src)) <> literal " -A " <>+            doubleQuotes (literal "\\c") <> space <> literal "\\") <> cr <>+            literal " -- " <> doubleQuotes (nowrap contents) <> cr <>+            literal "\\&"+      Nothing -> contents inlineToMs opts (Image attr alternate (src, _)) = do   let desc = literal "[IMAGE: " <>              literal (escapeStr opts (stringify alternate)) <> char ']'@@ -656,3 +677,7 @@  where   mbW = inPoints opts <$> dimension Width attr   mbH = inPoints opts <$> dimension Height attr++inlinesToPlain :: PandocMonad m => [Inline] -> m Text+inlinesToPlain ils = T.strip <$> writePlain def{ writerWrapText = WrapNone }+                                    (Pandoc nullMeta [Plain ils])
src/Text/Pandoc/Writers/Muse.hs view
@@ -265,12 +265,15 @@   return $ blankline <> attr' $$ nowrap (header' <> contents) <> blankline -- https://www.gnu.org/software/emacs-muse/manual/muse.html#Horizontal-Rules-and-Anchors blockToMuse HorizontalRule = return $ blankline $$ "----" $$ blankline-blockToMuse (Table _ blkCapt specs thead tbody tfoot) =+blockToMuse (Table _ blkCapt specs thead@(TableHead hattr hrows) tbody tfoot) =   if isSimple && numcols > 1     then simpleTable caption headers rows     else do       opts <- asks envOptions-      gridTable opts blocksToDoc True (map (const AlignDefault) aligns) widths headers rows+      let tbody' = case hrows of+                     [] -> tbody+                     _  -> TableBody nullAttr 0 [] hrows : tbody+      gridTable opts blocksToDoc specs (TableHead hattr []) tbody' tfoot   where     (caption, aligns, widths, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot     blocksToDoc opts blocks =@@ -719,7 +722,11 @@                      then mempty                      else literal ("#" <> anchor) <> space   modify $ \st -> st { stUseTags = False }-  return $ anchorDoc <> (if null inlines && not (T.null anchor)-                         then mempty-                         else (if null names then (if hasDir then contents' else "<class>" <> contents' <> "</class>")-                               else "<class name=\"" <> literal (head names) <> "\">" <> contents' <> "</class>"))+  return $ anchorDoc <>+   if null inlines && not (T.null anchor)+      then mempty+      else case names of+             [] | hasDir -> contents'+                | otherwise -> "<class>" <> contents' <> "</class>"+             (n:_) -> "<class name=\"" <> literal n <> "\">" <>+                         contents' <> "</class>"
src/Text/Pandoc/Writers/Native.hs view
@@ -1,6 +1,6 @@ {- |    Module      : Text.Pandoc.Writers.Native-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>
src/Text/Pandoc/Writers/ODT.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE OverloadedStrings   #-} {- |    Module      : Text.Pandoc.Writers.ODT-   Copyright   : Copyright (C) 2008-2023 John MacFarlane+   Copyright   : Copyright (C) 2008-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -24,7 +24,7 @@ import qualified Data.Text as T import qualified Data.Text.Lazy as TL import Data.Time-import System.FilePath (takeDirectory, takeExtension, (<.>))+import System.FilePath (takeDirectory, takeExtension, (<.>), (</>), isAbsolute) import Text.Collate.Lang (Lang (..), renderLang) import Text.Pandoc.Class.PandocMonad (PandocMonad, report, toLang) import qualified Text.Pandoc.Class.PandocMonad as P@@ -34,7 +34,8 @@ import Text.Pandoc.ImageSize import Text.Pandoc.Logging import Text.Pandoc.MIME (extensionFromMimeType, getMimeType)-import Text.Pandoc.Options (WrapOption (..), WriterOptions (..))+import Text.Pandoc.Options (WrapOption (..), WriterOptions (..),+                            HighlightMethod(Skylighting)) import Text.DocLayout import Text.Pandoc.Shared (stringify, tshow) import Text.Pandoc.Version (pandocVersionText)@@ -48,7 +49,7 @@ import Text.Pandoc.XML.Light import Text.TeXMath import qualified Text.XML.Light as XL-import Network.URI (parseRelativeReference, URI(uriPath))+import Network.URI (parseRelativeReference, URI(uriPath), isURI) import Skylighting  newtype ODTState = ODTState { stEntries :: [Entry]@@ -211,7 +212,10 @@                 . maybe id addLang mbLang                 . transformElement (\qn -> qName qn == "styles" &&                                       qPrefix qn == Just "office" )-                     (maybe id addHlStyles (writerHighlightStyle opts))+                     (addListItemStyles .+                      (case writerHighlightMethod opts of+                        Skylighting style -> addHlStyles style+                        _ -> id))                 $ d )         | otherwise = pure e   entries <- mapM goEntry (zEntries arch)@@ -225,6 +229,56 @@    isHlStyle (Elem e) = "Tok" `T.isSuffixOf` (qName (elName e))    isHlStyle _ = False +-- | Ensure the office:styles element contains paragraph styles for+-- list items used by the OpenDocument writer.  This injects only the+-- styles that are missing, so a user-supplied reference.odt may+-- override any of them.+addListItemStyles :: Element -> Element+addListItemStyles el =+  el{ elContent = elContent el ++ map Elem missingStyles }+ where+   existing = [ T.concat [ attrVal a+                         | a <- elAttribs e+                         , qName (attrKey a) == "name"+                         , qPrefix (attrKey a) == Just "style" ]+              | Elem e <- elContent el+              , qName (elName e) == "style"+              , qPrefix (elName e) == Just "style" ]+   missingStyles =+     [ s | s <- listItemStyleElements+         , styleNameOf s `notElem` existing ]+   styleNameOf e = T.concat [ attrVal a+                            | a <- elAttribs e+                            , qName (attrKey a) == "name"+                            , qPrefix (attrKey a) == Just "style" ]++listItemStyleElements :: [Element]+listItemStyleElements =+  [ mkParaStyle "List_20_Bullet" "List Bullet" Nothing+  , mkParaStyle "List_20_Bullet_20_Tight" "List Bullet Tight" (Just tightProps)+  , mkParaStyle "List_20_Number" "List Number" Nothing+  , mkParaStyle "List_20_Number_20_Tight" "List Number Tight" (Just tightProps)+  ]+ where+   styleQN n p = QName n Nothing (Just p)+   mkAttr p n v = Attr (styleQN n p) v+   tightProps =+     Element (styleQN "paragraph-properties" "style")+       [ mkAttr "fo" "margin-top" "0in"+       , mkAttr "fo" "margin-bottom" "0in"+       , mkAttr "style" "contextual-spacing" "false"+       ] [] Nothing+   mkParaStyle name display mbProps =+     Element (styleQN "style" "style")+       [ mkAttr "style" "name" name+       , mkAttr "style" "display-name" display+       , mkAttr "style" "family" "paragraph"+       , mkAttr "style" "parent-style-name" "List"+       , mkAttr "style" "class" "list"+       ]+       (maybe [] (\p -> [Elem p]) mbProps)+       Nothing+ -- top-down search transformElement :: (QName -> Bool)                  -> (Element -> Element)@@ -272,15 +326,23 @@                               Just dim         -> Just $ Inch $ inInch opts dim                               Nothing          -> Nothing        let  newattr = (id', cls, dims)-       entries <- gets stEntries-       let extension = maybe (takeExtension $ takeWhile (/='?') $ T.unpack src) T.unpack-                           (mbMimeType >>= extensionFromMimeType)-       let newsrc = "Pictures/" ++ show (length entries) <.> extension-       let toLazy = B.fromChunks . (:[])-       epochtime <- floor `fmap` lift P.getPOSIXTime-       let entry = toEntry newsrc epochtime $ toLazy img-       modify $ \st -> st{ stEntries = entry : entries }-       return $ Image newattr lab (T.pack newsrc, t))+       src' <- if writerLinkImages opts+                  then+                    case T.unpack src of+                      s | isURI s -> return src+                        | isAbsolute s -> return src+                        | otherwise -> return $ T.pack $ ".." </> s+                  else do+                    entries <- gets stEntries+                    let extension = maybe (takeExtension $ takeWhile (/='?') $ T.unpack src) T.unpack+                                        (mbMimeType >>= extensionFromMimeType)+                    let newsrc = "Pictures/" ++ show (length entries) <.> extension+                    let toLazy = B.fromChunks . (:[])+                    epochtime <- floor `fmap` lift P.getPOSIXTime+                    let entry = toEntry newsrc epochtime $ toLazy img+                    modify $ \st -> st{ stEntries = entry : entries }+                    return $ T.pack newsrc+       return $ Image newattr lab (src', t))    (\e -> do        report $ CouldNotFetchResource src $ T.pack (show e)        return $ Emph lab)
src/Text/Pandoc/Writers/OOXML.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Writers.OOXML-   Copyright   : Copyright (C) 2012-2023 John MacFarlane+   Copyright   : Copyright (C) 2012-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>
src/Text/Pandoc/Writers/OPML.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE CPP               #-} {- |    Module      : Text.Pandoc.Writers.OPML-   Copyright   : Copyright (C) 2013-2023 John MacFarlane+   Copyright   : Copyright (C) 2013-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>
src/Text/Pandoc/Writers/OpenDocument.hs view
@@ -19,10 +19,10 @@ import Control.Monad.State.Strict ( StateT(..), modify, gets, lift ) import Data.Char (chr) import Data.Foldable (find)-import Data.List (sortOn, sortBy, foldl')+import Data.List (sortOn, sortBy)+import qualified Data.List as L import qualified Data.Map as Map-import Data.Maybe (isNothing)-import Data.Ord (comparing)+import Data.Ord (comparing, Down (Down)) import qualified Data.Set as Set import Data.Text (Text) import qualified Data.Text as T@@ -33,7 +33,7 @@ import qualified Text.Pandoc.Builder as B import Text.Pandoc.Logging import Text.Pandoc.Options-import Text.DocLayout+import Text.DocLayout hiding (link) import Text.Pandoc.Shared (linesToPara, tshow, blocksToInlines) import Text.Pandoc.Templates (renderTemplate) import qualified Text.Pandoc.Translations as Term (Term(Figure, Table))@@ -51,6 +51,29 @@ plainToPara (Plain x) = Para x plainToPara x         = x +-- Names of predefined styles in the reference.odt; see data/odt/styles.xml.+defaultBulletListStyleName, defaultNumberedListStyleName :: Text+defaultBulletListStyleName   = "List_20_1"+defaultNumberedListStyleName = "Numbering_20_1"++bulletItemStyleName, bulletItemTightStyleName,+  numberItemStyleName, numberItemTightStyleName :: Text+bulletItemStyleName      = "List_20_Bullet"+bulletItemTightStyleName = "List_20_Bullet_20_Tight"+numberItemStyleName      = "List_20_Number"+numberItemTightStyleName = "List_20_Number_20_Tight"++-- | Predefined inline style names for single-style spans.+wellKnownTextStyle :: Set.Set TextStyle -> Maybe Text+wellKnownTextStyle s = case Set.toList s of+  [Italic] -> Just "Emphasis"+  [Bold]   -> Just "Strong_20_Emphasis"+  [Strike] -> Just "Strikeout"+  [Sub]    -> Just "Subscript"+  [Sup]    -> Just "Superscript"+  [Pre]    -> Just "Source_20_Text"+  _        -> Nothing+ -- -- OpenDocument writer --@@ -66,7 +89,8 @@     WriterState { stNotes          :: [Doc Text]                 , stTableStyles    :: [Doc Text]                 , stParaStyles     :: [Doc Text]-                , stListStyles     :: [(Int, [Doc Text])]+                , stListOverrides  :: Map.Map (ListNumberStyle,ListNumberDelim)+                                        (Text, Doc Text)                 , stTextStyles     :: Map.Map (Set.Set TextStyle)                                         (Text, Doc Text)                 , stTextStyleAttr  :: Set.Set TextStyle@@ -85,7 +109,7 @@     WriterState { stNotes          = []                 , stTableStyles    = []                 , stParaStyles     = []-                , stListStyles     = []+                , stListOverrides  = Map.empty                 , stTextStyles     = Map.empty                 , stTextStyleAttr  = Set.empty                 , stIndentPara     = 0@@ -115,20 +139,12 @@ addTextStyle attrs i = modify $ \s ->   s { stTextStyles = Map.insert attrs i (stTextStyles s) } -addTextStyleAttr :: PandocMonad m => TextStyle -> OD m ()-addTextStyleAttr t = modify $ \s ->-  s { stTextStyleAttr = Set.insert t (stTextStyleAttr s) }- increaseIndent :: PandocMonad m => OD m () increaseIndent = modify $ \s -> s { stIndentPara = 1 + stIndentPara s }  resetIndent :: PandocMonad m => OD m () resetIndent = modify $ \s -> s { stIndentPara = stIndentPara s - 1 } -inTightList :: PandocMonad m => OD m a -> OD m a-inTightList  f = modify (\s -> s { stTight = True  }) >> f >>= \r ->-                 modify (\s -> s { stTight = False }) >> return r- setInDefinitionList :: PandocMonad m => Bool -> OD m () setInDefinitionList b = modify $  \s -> s { stInDefinition = b } @@ -150,35 +166,42 @@ inSpanTags :: Text -> Doc Text -> Doc Text inSpanTags s = inTags False "text:span" [("text:style-name",s)] -withTextStyle :: PandocMonad m => TextStyle -> OD m a -> OD m a-withTextStyle s f = do+withAlteredTextStyles :: PandocMonad m+                       => (Set.Set TextStyle -> Set.Set TextStyle) -> OD m a -> OD m a+withAlteredTextStyles f action = do   oldTextStyleAttr <- gets stTextStyleAttr-  addTextStyleAttr s-  res <- f+  modify $ \st -> st{ stTextStyleAttr = f oldTextStyleAttr }+  res <- action   modify $ \st -> st{ stTextStyleAttr = oldTextStyleAttr }   return res +withTextStyle :: PandocMonad m => TextStyle -> OD m a -> OD m a+withTextStyle s = withAlteredTextStyles (Set.insert s)+ inTextStyle :: PandocMonad m => Doc Text -> OD m (Doc Text) inTextStyle d = do   at <- gets stTextStyleAttr   if Set.null at      then return d-     else do-       styles <- gets stTextStyles-       case Map.lookup at styles of-            Just (styleName, _) -> return $-              inTags False "text:span" [("text:style-name",styleName)] d-            Nothing -> do-              let styleName = "T" <> tshow (Map.size styles + 1)-              addTextStyle at (styleName,-                     inTags False "style:style"-                       [("style:name", styleName)-                       ,("style:family", "text")]-                       $ selfClosingTag "style:text-properties"-                          (sortOn fst . Map.toList-                                $ foldl' textStyleAttr mempty (Set.toList at)))-              return $ inTags False-                  "text:span" [("text:style-name",styleName)] d+     else case wellKnownTextStyle at of+       Just styleName -> return $+         inTags False "text:span" [("text:style-name", styleName)] d+       Nothing -> do+         styles <- gets stTextStyles+         case Map.lookup at styles of+              Just (styleName, _) -> return $+                inTags False "text:span" [("text:style-name",styleName)] d+              Nothing -> do+                let styleName = "T" <> tshow (Map.size styles + 1)+                addTextStyle at (styleName,+                       inTags False "style:style"+                         [("style:name", styleName)+                         ,("style:family", "text")]+                         $ selfClosingTag "style:text-properties"+                            (sortOn fst . Map.toList+                                  $ L.foldl' textStyleAttr mempty (Set.toList at)))+                return $ inTags False+                    "text:span" [("text:style-name",styleName)] d  formulaStyles :: [Doc Text] formulaStyles = [formulaStyle InlineMath, formulaStyle DisplayMath]@@ -261,12 +284,10 @@            b <- blocksToOpenDocument opts blocks            return (b, m)   let styles   = stTableStyles s ++ stParaStyles s ++ formulaStyles ++-                     map snd (sortBy (flip (comparing fst)) (+                     map snd (sortBy (comparing (Down . fst)) (                         Map.elems (stTextStyles s)))-      listStyle (n,l) = inTags True "text:list-style"-                          [("style:name", "L" <> tshow n)] (vcat l)-  let listStyles  = map listStyle (stListStyles s)-  let automaticStyles = vcat $ reverse $ styles ++ listStyles+  let listStyles  = map snd (Map.elems (stListOverrides s))+  let automaticStyles = vcat $ reverse styles ++ listStyles   let context = defField "body" body               . defField "toc" (writerTableOfContents opts)               . defField "toc-depth" (tshow $ writerTOCDepth opts)@@ -286,53 +307,101 @@ withParagraphStyle _ _ [] = return empty  inPreformattedTags :: PandocMonad m => [Doc Text] -> OD m (Doc Text)-inPreformattedTags s = do-  n <- paraStyle [("style:parent-style-name","Preformatted_20_Text")]-  return $ inParagraphTagsWithStyle ("P" <> tshow n) $ hcat s+inPreformattedTags s =+  return $ inParagraphTagsWithStyle "Preformatted_20_Text" $ hcat s +-- | Get the list-style name to use for an ordered list with the given+-- numbering style and delimiter, registering an override automatic style+-- if needed.  Lists with default style/delimiter use the predefined+-- @Numbering_20_1@ style and no override is generated.+orderedListStyleName :: PandocMonad m+                     => ListNumberStyle -> ListNumberDelim -> OD m Text+orderedListStyleName ns nd+  | (ns == DefaultStyle || ns == Decimal) &&+    (nd == DefaultDelim || nd == Period) =+      return defaultNumberedListStyleName+  | otherwise = do+      overrides <- gets stListOverrides+      case Map.lookup (ns, nd) overrides of+        Just (name, _) -> return name+        Nothing -> do+          let name = "Pandoc_5f_Numbering_5f_" <>+                       tshow (Map.size overrides + 1)+              doc = inTags True "text:list-style"+                      [("style:name", name)]+                      (vcat (map (orderedListLevel ns nd) [1..10]))+          modify $ \s -> s { stListOverrides =+                               Map.insert (ns, nd) (name, doc)+                                          (stListOverrides s) }+          return name++orderedListLevel :: ListNumberStyle -> ListNumberDelim -> Int -> Doc Text+orderedListLevel ns nd lvl =+    let suffix = case nd of+                   OneParen  -> [("style:num-suffix", ")")]+                   TwoParens -> [("style:num-prefix", "(")+                                ,("style:num-suffix", ")")]+                   _         -> [("style:num-suffix", ".")]+        format = case ns of+                   UpperAlpha -> "A"+                   LowerAlpha -> "a"+                   UpperRoman -> "I"+                   LowerRoman -> "i"+                   _          -> "1"+    in inTags True "text:list-level-style-number"+              ([ ("text:level"      , tshow lvl)+               , ("text:style-name" , "Numbering_20_Symbols")+               , ("style:num-format", format)+               ] ++ suffix)+              (selfClosingTag "style:list-level-properties"+                 [ ("text:space-before",+                      T.pack (printf "%.4fin" (0.1972 * fromIntegral (lvl - 1) :: Double)))+                 , ("text:min-label-width", "0.1965in")+                 , ("text:min-label-distance", "0.1in")+                 ])+ orderedListToOpenDocument :: PandocMonad m-                          => WriterOptions -> Int -> [[Block]] -> OD m (Doc Text)-orderedListToOpenDocument o pn bs =+                          => WriterOptions -> Text -> [[Block]]+                          -> OD m (Doc Text)+orderedListToOpenDocument o paraName bs =     vcat . map (inTagsIndented "text:list-item") <$>-    mapM (orderedItemToOpenDocument o pn . map plainToPara) bs+    mapM (orderedItemToOpenDocument o paraName . map plainToPara) bs  orderedItemToOpenDocument :: PandocMonad m-                          => WriterOptions -> Int -> [Block] -> OD m (Doc Text)-orderedItemToOpenDocument  o n bs = vcat <$> mapM go bs- where go (OrderedList a l) = newLevel a l-       go (Para          l) = inParagraphTagsWithStyle ("P" <> tshow n) <$>+                          => WriterOptions -> Text -> [Block]+                          -> OD m (Doc Text)+orderedItemToOpenDocument  o paraName bs = vcat <$> mapM go bs+ where go (OrderedList a l) = orderedList a l+       go (Para          l) = inParagraphTagsWithStyle paraName <$>                                 inlinesToOpenDocument o l        go b                 = blockToOpenDocument o b-       newLevel a l = do-         nn <- length <$> gets stParaStyles-         ls <- head   <$> gets stListStyles-         modify $ \s -> s { stListStyles = orderedListLevelStyle a ls :-                                 drop 1 (stListStyles s) }-         inTagsIndented "text:list" <$> orderedListToOpenDocument o nn l+       orderedList a@(_,ns,nd) l = do+         lstName <- orderedListStyleName ns nd+         let pn = if isTightList l then numberItemTightStyleName+                                   else numberItemStyleName+         let listAttrs = ("text:style-name", lstName) : startValueAttr a+         inTags True "text:list" listAttrs <$>+           orderedListToOpenDocument o pn l +-- | Generate a @text:start-value@ attribute when the start value is not 1.+startValueAttr :: ListAttributes -> [(Text, Text)]+startValueAttr (s,_,_) | s /= 1 = [("text:start-value", tshow s)]+startValueAttr _                = []+ isTightList :: [[Block]] -> Bool isTightList []          = False isTightList (b:_)     | Plain {} : _ <- b = True     | otherwise         = False -newOrderedListStyle :: PandocMonad m-                    => Bool -> ListAttributes -> OD m (Int,Int)-newOrderedListStyle b a = do-  ln <- (+) 1 . length  <$> gets stListStyles-  let nbs = orderedListLevelStyle a (ln, [])-  pn <- if b then inTightList (paraListStyle ln) else paraListStyle ln-  modify $ \s -> s { stListStyles = nbs : stListStyles s }-  return (ln,pn)- bulletListToOpenDocument :: PandocMonad m                          => WriterOptions -> [[Block]] -> OD m (Doc Text) bulletListToOpenDocument o b = do-  ln <- (+) 1 . length <$> gets stListStyles-  (pn,ns) <- if isTightList b then inTightList (bulletListStyle ln) else bulletListStyle ln-  modify $ \s -> s { stListStyles = ns : stListStyles s }-  is <- listItemsToOpenDocument ("P" <> tshow pn) o b-  return $ inTags True "text:list" [("text:style-name", "L" <> tshow ln)] is+  let pn = if isTightList b then bulletItemTightStyleName+                            else bulletItemStyleName+  is <- listItemsToOpenDocument pn o b+  return $ inTags True "text:list"+             [("text:style-name", defaultBulletListStyleName)] is  listItemsToOpenDocument :: PandocMonad m                         => Text -> WriterOptions -> [[Block]] -> OD m (Doc Text)@@ -351,16 +420,18 @@   return $ t' $$ d'  inBlockQuote :: PandocMonad m-             => WriterOptions -> Int -> [Block] -> OD m (Doc Text)-inBlockQuote  o i (b:bs)+             => WriterOptions -> Text -> [Block] -> OD m (Doc Text)+inBlockQuote  o sty (b:bs)     | BlockQuote l <- b = do increaseIndent                              ni <- paraStyle                                    [("style:parent-style-name","Quotations")]-                             go =<< inBlockQuote o ni (map plainToPara l)-    | Para       l <- b = go =<< inParagraphTagsWithStyle ("P" <> tshow i) <$> inlinesToOpenDocument o l+                             inner <- inBlockQuote o ni (map plainToPara l)+                             resetIndent+                             go inner+    | Para       l <- b = go =<< inParagraphTagsWithStyle sty <$> inlinesToOpenDocument o l     | otherwise         = go =<< blockToOpenDocument o b-    where go  block  = ($$) block <$> inBlockQuote o i bs-inBlockQuote     _ _ [] =  resetIndent >> return empty+    where go  block  = ($$) block <$> inBlockQuote o sty bs+inBlockQuote     _ _ [] = return empty  -- | Convert a list of Pandoc blocks to OpenDocument. blocksToOpenDocument :: PandocMonad m => WriterOptions -> [Block] -> OD m (Doc Text)@@ -387,29 +458,31 @@     OrderedList  a b -> setFirstPara >> orderedList a b     CodeBlock attrs s -> do       setFirstPara-      if isNothing (writerHighlightStyle o)-         then unhighlighted s-         else case highlight (writerSyntaxMap o) formatOpenDocument attrs s of+      case writerHighlightMethod o of+        Skylighting {} ->+          case highlight (writerSyntaxMap o) formatOpenDocument attrs s of                 Right h  -> return $ flush . vcat $ map (inTags True "text:p"                                           [("text:style-name",                                             "Preformatted_20_Text")] . hcat) h                 Left msg -> do                   unless (T.null msg) $ report $ CouldNotHighlight msg                   unhighlighted s-    Table a bc s th tb tf -> setFirstPara >> table (Ann.toTable a bc s th tb tf)+        _ -> unhighlighted s+    Table a bc s th tb tf -> setFirstPara >>+                              table o (Ann.toTable a bc s th tb tf)     HorizontalRule   -> setFirstPara >> return (selfClosingTag "text:p"                          [ ("text:style-name", "Horizontal_20_Line") ])     b@(RawBlock f s) -> if f == Format "opendocument"                         then return $ text $ T.unpack s                         else empty <$ report (BlockNotRendered b)-    Figure a capt b  -> figure a capt b+    Figure a capt b  -> figure o a capt b     where       defList       b = do setInDefinitionList True                            r <- vcat  <$> mapM (deflistItemToOpenDocument o) b                            setInDefinitionList False                            return r       unhighlighted s = flush . vcat <$>-            (mapM (inPreformattedTags . (:[])) (map preformatted (T.lines s)))+            (mapM ((inPreformattedTags . (:[])) . preformatted) (T.lines s))       mkDiv    attr s = do         let (ident,_,kvs) = attr             i = withLangFromAttr attr $@@ -420,15 +493,19 @@         if T.null ident           then i           else fmap mkBookmarkedDiv i-      mkBlockQuote  b = do increaseIndent-                           i <- paraStyle-                                 [("style:parent-style-name","Quotations")]-                           inBlockQuote o i (map plainToPara b)-      orderedList a b = do (ln,pn) <- newOrderedListStyle (isTightList b) a-                           inTags True "text:list" [ ("text:style-name", "L" <> tshow ln)]-                                      <$> orderedListToOpenDocument o pn b-      table :: PandocMonad m => Ann.Table -> OD m (Doc Text)-      table (Ann.Table (ident, _, _) (Caption _ c) colspecs thead tbodies _) = do+      mkBlockQuote  b = do sty <- paraStyle+                                    [("style:parent-style-name","Quotations")]+                           inBlockQuote o sty (map plainToPara b)+      orderedList a@(_,ns,nd) b = do+        lstName <- orderedListStyleName ns nd+        let pn = if isTightList b then numberItemTightStyleName+                                  else numberItemStyleName+        let listAttrs = ("text:style-name", lstName) : startValueAttr a+        inTags True "text:list" listAttrs <$>+          orderedListToOpenDocument o pn b+      table :: PandocMonad m => WriterOptions -> Ann.Table -> OD m (Doc Text)+      table opts+          (Ann.Table (ident, _, _) (Caption _ c) colspecs thead tbodies tfoot) = do         tn <- length <$> gets stTableStyles         pn <- length <$> gets stParaStyles         let  genIds      = map chr [65..]@@ -454,12 +531,16 @@                                 else unNumberedCaption "TableCaption"         th <- colHeadsToOpenDocument o (map fst paraHStyles) thead         tr <- mapM (tableBodyToOpenDocument o (map fst paraHStyles) (map fst paraStyles)) tbodies+        tf <- tableFootToOpenDocument o (map fst paraStyles) tfoot         let tableDoc = inTags True "table:table" [                             ("table:name"      , name)                           , ("table:style-name", name)-                          ] (vcat columns $$ th $$ vcat tr)-        return $ captionDoc $$ tableDoc-      figure (ident, _, _) (Caption _ longcapt) body =+                          ] (vcat columns $$ th $$ vcat tr $$ tf)+        return $+          case writerTableCaptionPosition opts of+            CaptionAbove -> captionDoc $$ tableDoc+            CaptionBelow -> tableDoc $$ captionDoc+      figure opts (ident, _, _) (Caption _ longcapt) body =         case blocksToInlines longcapt of           [] ->             withParagraphStyle o "Figure" body@@ -470,7 +551,10 @@                           if isEnabled Ext_native_numbering o                           then numberedFigureCaption ident                           else unNumberedCaption "FigureCaption"-            return $ imageDoc $$ captionDoc+            return $+              case writerFigureCaptionPosition opts of+                CaptionAbove -> captionDoc $$ imageDoc+                CaptionBelow -> imageDoc $$ captionDoc   numberedTableCaption :: PandocMonad m => Text -> Doc Text -> OD m (Doc Text)@@ -510,19 +594,34 @@ colHeadsToOpenDocument o ns (Ann.TableHead _ hs) =   case hs of     [] -> return empty-    (x:_) ->-        let (Ann.HeaderRow _ _ c) = x-        in inTagsIndented "table:table-header-rows" .-        inTagsIndented "table:table-row" .-        vcat <$> mapM (tableItemToOpenDocument o "TableHeaderRowCell") (zip ns c)+    xs -> inTagsIndented "table:table-header-rows" <$>+      tableHeaderRowsToOpenDocument o ns "TableHeaderRowCell" xs +tableHeaderRowsToOpenDocument :: PandocMonad m+                              => WriterOptions -> [Text] -> Text -> [Ann.HeaderRow]+                              -> OD m (Doc Text)+tableHeaderRowsToOpenDocument o ns s headerRows =+  vcat <$> mapM headerRowToOpenDocument headerRows+  where+    headerRowToOpenDocument (Ann.HeaderRow _ _ c) =+      inTagsIndented "table:table-row" .+      vcat <$> mapM (tableItemToOpenDocument o s) (zip ns c)+ tableBodyToOpenDocument:: PandocMonad m                        => WriterOptions -> [Text] -> [Text] -> Ann.TableBody                        -> OD m (Doc Text)-tableBodyToOpenDocument o headns bodyns tb =-    let (Ann.TableBody _ _ _ r) = tb-    in vcat <$> mapM (tableRowToOpenDocument o headns bodyns) r+tableBodyToOpenDocument o headns bodyns tb = do+    let (Ann.TableBody _ _ hs r) = tb+    tableRowHeaders <- tableHeaderRowsToOpenDocument o headns "TableRowCell" hs+    tableRows <- mapM (tableRowToOpenDocument o headns bodyns) r+    return $ tableRowHeaders $$ vcat tableRows +tableFootToOpenDocument :: PandocMonad m+                        => WriterOptions -> [Text] -> Ann.TableFoot+                        -> OD m (Doc Text)+tableFootToOpenDocument o ns (Ann.TableFoot _ r) =+  tableHeaderRowsToOpenDocument o ns "TableRowCell" r+ tableRowToOpenDocument :: PandocMonad m                        => WriterOptions -> [Text] -> [Text] -> Ann.BodyRow                        -> OD m (Doc Text)@@ -563,14 +662,9 @@       aa = alignAttrib align       a = [ ("table:style-name" , s )           , ("office:value-type", "string" ) ] ++ csa ++ rsa-  itemParaStyle <- case aa of-                     [] -> return 0-                     _  -> paraStyleFromParent n aa-  let itemParaStyle' = case itemParaStyle of-                         0 -> n-                         x -> "P" <> tshow x+  itemParaStyle <- paraStyleFromParent n aa   inTags True "table:table-cell" a <$>-    withParagraphStyle o itemParaStyle' (map plainToPara i)+    withParagraphStyle o itemParaStyle (map plainToPara i)  -- | Convert a list of inline elements to OpenDocument. inlinesToOpenDocument :: PandocMonad m => WriterOptions -> [Inline] -> OD m (Doc Text)@@ -619,14 +713,14 @@     Subscript   l -> withTextStyle Sub    $ inlinesToOpenDocument o l     SmallCaps   l -> withTextStyle SmallC $ inlinesToOpenDocument o l     Quoted    t l -> inQuotes t <$> inlinesToOpenDocument o l-    Code      attrs s -> if isNothing (writerHighlightStyle o)-      then unhighlighted s-      else case highlight (writerSyntaxMap o)-                  formatOpenDocument attrs s of+    Code      attrs s -> case writerHighlightMethod o of+      Skylighting {} ->+        case highlight (writerSyntaxMap o) formatOpenDocument attrs s of                 Right h  -> inlinedCode $ mconcat $ mconcat h                 Left msg -> do                   unless (T.null msg) $ report $ CouldNotHighlight msg                   unhighlighted s+      _ -> unhighlighted s     Math      t s -> lift (texMathToInlines t s) >>=                          inlinesToOpenDocument o     Cite      _ l -> inlinesToOpenDocument o l@@ -643,7 +737,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 })@@ -660,8 +754,12 @@                                                  , ("xlink:show"   , "embed" )                                                  , ("xlink:actuate", "onLoad")]       mkSpan attr xs =  do-        let (ident,_,_) = attr-            i = withLangFromAttr attr (inlinesToOpenDocument o xs)+        let (ident,_,kvs) = attr+            i = maybe id (\sty ->+                           fmap (inTags False "text:span"+                                  [ ("text:style-name", sty) ]))+                  (lookup "custom-style" kvs) .+                 withLangFromAttr attr $ inlinesToOpenDocument o xs             mkBookmarkedSpan b =               if isEmpty b                 then selfClosingBookmark ident@@ -676,7 +774,8 @@                          , ("text:note-class", "footnote"     )] $                          inTagsSimple "text:note-citation" (text . show $ n + 1) <>                          inTagsSimple "text:note-body" t-        nn <- footNote <$> withParagraphStyle o "Footnote" l+        nn <- footNote <$> withAlteredTextStyles (const mempty)+                            (withParagraphStyle o "Footnote" l)         addNote nn         return nn @@ -728,55 +827,6 @@             then linkOrReference             else link -bulletListStyle :: PandocMonad m => Int -> OD m (Int,(Int,[Doc Text]))-bulletListStyle l = do-  let doStyles  i = inTags True "text:list-level-style-bullet"-                    [ ("text:level"      , tshow (i + 1))-                    , ("text:style-name" , "Bullet_20_Symbols"  )-                    , ("style:num-suffix", "."                  )-                    , ("text:bullet-char", T.singleton (bulletList !! i))-                    ] (listLevelStyle (1 + i))-      bulletList  = map chr $ cycle [8226,9702,9642]-      listElStyle = map doStyles [0..9]-  pn <- paraListStyle l-  return (pn, (l, listElStyle))--orderedListLevelStyle :: ListAttributes -> (Int, [Doc Text]) -> (Int,[Doc Text])-orderedListLevelStyle (s,n, d) (l,ls) =-    let suffix    = case d of-                      OneParen  -> [("style:num-suffix", ")")]-                      TwoParens -> [("style:num-prefix", "(")-                                   ,("style:num-suffix", ")")]-                      _         -> [("style:num-suffix", ".")]-        format    = case n of-                      UpperAlpha -> "A"-                      LowerAlpha -> "a"-                      UpperRoman -> "I"-                      LowerRoman -> "i"-                      _          -> "1"-        listStyle = inTags True "text:list-level-style-number"-                    ([ ("text:level"      , tshow $ 1 + length ls )-                     , ("text:style-name" , "Numbering_20_Symbols")-                     , ("style:num-format", format                )-                     , ("text:start-value", tshow s               )-                     ] ++ suffix) (listLevelStyle (1 + length ls))-    in  (l, ls ++ [listStyle])--listLevelStyle :: Int -> Doc Text-listLevelStyle i =-    let indent = tshow (0.25 + (0.25 * fromIntegral i :: Double)) in-    inTags True "style:list-level-properties"-                       [ ("text:list-level-position-and-space-mode",-                          "label-alignment")-                       , ("fo:text-align", "right")-                       ] $-       selfClosingTag "style:list-level-label-alignment"-                      [ ("text:label-followed-by", "listtab")-                      , ("text:list-tab-stop-position", indent <> "in")-                      , ("fo:text-indent", "-0.25in")-                      , ("fo:margin-left", indent <> "in")-                      ]- tableStyle :: Int -> Double -> [(Char,Double)] -> Doc Text tableStyle num textWidth wcs =     let tableId        = "Table" <> tshow (num + 1)@@ -814,15 +864,17 @@         columnStyles   = map colStyle wcs     in cellStyles $$ table $$ vcat columnStyles -paraStyle :: PandocMonad m => [(Text,Text)] -> OD m Int+-- | Generate (or reuse) a paragraph style with the given attributes.+-- When the only attribute is @style:parent-style-name@ and no+-- indent/tight overrides are active, the parent name is returned+-- directly (no @Pn@ automatic style is created), so that the+-- predefined style passes through unchanged.+paraStyle :: PandocMonad m => [(Text,Text)] -> OD m Text paraStyle attrs = do-  pn <- (+)   1 . length       <$> gets stParaStyles   i  <- (*) (0.5 :: Double) . fromIntegral <$> gets stIndentPara   b  <- gets stInDefinition   t  <- gets stTight-  let styleAttr = [ ("style:name"             , "P" <> tshow pn)-                  , ("style:family"           , "paragraph"   )]-      indentVal = flip (<>) "in" . tshow $ if b then max 0.5 i else i+  let indentVal = flip (<>) "in" . tshow $ if b then max 0.5 i else i       tight     = if t then [ ("fo:margin-top"          , "0in"    )                             , ("fo:margin-bottom"       , "0in"    )]                        else []@@ -833,31 +885,32 @@                            , ("style:auto-text-indent" , "false"  )]                       else []       attributes = indent <> tight-      paraProps = if null attributes-                     then mempty-                     else selfClosingTag-                             "style:paragraph-properties" attributes-  addParaStyle $ inTags True "style:style" (styleAttr <> attrs) paraProps-  return pn--paraStyleFromParent :: PandocMonad m => Text -> [(Text,Text)] -> OD m Int-paraStyleFromParent parent attrs = do-  pn <- (+) 1 . length  <$> gets stParaStyles-  let styleAttr = [ ("style:name"             , "P" <> tshow pn)-                  , ("style:family"           , "paragraph")-                  , ("style:parent-style-name", parent)]-      paraProps = if null attrs-                     then mempty-                     else selfClosingTag-                          "style:paragraph-properties" attrs-  addParaStyle $ inTags True "style:style" styleAttr paraProps-  return pn-+  case (attributes, attrs) of+    ([], [("style:parent-style-name", parent)]) -> return parent+    _ -> do+      pn <- (+) 1 . length <$> gets stParaStyles+      let name      = "P" <> tshow pn+          styleAttr = [ ("style:name"  , name)+                      , ("style:family", "paragraph") ]+          paraProps = if null attributes+                         then mempty+                         else selfClosingTag+                                 "style:paragraph-properties" attributes+      addParaStyle $ inTags True "style:style" (styleAttr <> attrs) paraProps+      return name -paraListStyle :: PandocMonad m => Int -> OD m Int-paraListStyle l = paraStyle-  [("style:parent-style-name","Text_20_body")-  ,("style:list-style-name", "L" <> tshow l)]+paraStyleFromParent :: PandocMonad m => Text -> [(Text,Text)] -> OD m Text+paraStyleFromParent parent attrs+  | null attrs = return parent+  | otherwise  = do+      pn <- (+) 1 . length <$> gets stParaStyles+      let name      = "P" <> tshow pn+          styleAttr = [ ("style:name"             , name)+                      , ("style:family"           , "paragraph")+                      , ("style:parent-style-name", parent)]+          paraProps = selfClosingTag "style:paragraph-properties" attrs+      addParaStyle $ inTags True "style:style" styleAttr paraProps+      return name  paraTableStyles :: Text -> Int -> [Alignment] -> [(Text, Doc Text)] paraTableStyles _ _ [] = []
src/Text/Pandoc/Writers/Org.hs view
@@ -3,11 +3,11 @@ {- |    Module      : Text.Pandoc.Writers.Org    Copyright   : © 2010-2015 Puneeth Chaganti <punchagan@gmail.com>-                   2010-2023 John MacFarlane <jgm@berkeley.edu>-                   2016-2023 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+                   2010-2025 John MacFarlane <jgm@berkeley.edu>+                   2016-2025 Albert Krewinkel <albert+pandoc@tarleb.com>    License     : GNU GPL, version 2 or above -   Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>    Stability   : alpha    Portability : portable @@ -71,6 +71,17 @@   let main = body $+$ notes   let context = defField "body" main               . defField "math" hasMath+              . defField "options"+                         (M.fromList+                          ((if isEnabled Ext_smart_quotes opts+                            then (("'", "t"):)+                            else id) .+                           (if not (isEnabled Ext_special_strings opts)+                            then (("-", "nil"):)+                            else id)+                           $ ([] :: [(Text, Text)])))+              . defField "option-special-strings"+                         (isEnabled Ext_special_strings opts)               $ metadata   return $ render colwidth $     case writerTemplate opts of@@ -89,20 +100,28 @@   let marker = "[fn:" ++ show num ++ "] "   return $ hang (length marker) (text marker) contents +-- | Replace Unicode characters with their ASCII representation+replaceSpecialStrings :: Text -> Text+replaceSpecialStrings =+  let expand c = case c of+        '\x00ad' -> "\\-"+        '\x2013' -> "--"+        '\x2014' -> "---"+        '\x2019' -> "'"+        '\x2026' -> "..."+        _        -> T.singleton c+  in T.concatMap expand+ -- | Escape special characters for Org. escapeString :: Text -> Doc Text escapeString t   | T.all isAlphaNum t = literal t   | otherwise = mconcat $ map escChar (T.unpack t)   where-   escChar '\x2013' = "--"-   escChar '\x2014' = "---"-   escChar '\x2019' = "'"-   escChar '\x2026' = "..."-   escChar c-     -- escape special chars with ZERO WIDTH SPACE as org manual suggests-     | c == '*' || c == '#' || c == '|' = afterBreak "\x200B" <> char c-     | otherwise = char c+    -- escape special chars with ZERO WIDTH SPACE as org manual suggests+   escChar c = if c == '*' || c == '#' || c == '|'+     then afterBreak "\x200B" <> char c+     else char c  isRawFormat :: Format -> Bool isRawFormat f =@@ -488,10 +507,18 @@ inlineToOrg (SmallCaps lst) = inlineListToOrg lst inlineToOrg (Quoted SingleQuote lst) = do   contents <- inlineListToOrg lst-  return $ "'" <> contents <> "'"+  opts <- gets stOptions+  return $+    if isEnabled Ext_smart opts || isEnabled Ext_smart_quotes opts+    then "'" <> contents <> "'"+    else "‘" <> contents <> "’" inlineToOrg (Quoted DoubleQuote lst) = do   contents <- inlineListToOrg lst-  return $ "\"" <> contents <> "\""+  opts <- gets stOptions+  return $+    if isEnabled Ext_smart opts || isEnabled Ext_smart_quotes opts+    then "\"" <> contents <> "\""+    else "“" <> contents <> "”" inlineToOrg (Cite cs lst) = do   opts <- gets stOptions   if isEnabled Ext_citations opts@@ -522,7 +549,12 @@        return $ "[cite" <> sty <> ":" <> citeItems <> "]"      else inlineListToOrg lst inlineToOrg (Code _ str) = return $ "=" <> literal str <> "="-inlineToOrg (Str str) = return $ escapeString str+inlineToOrg (Str str) = do+  opts <- gets stOptions+  let str' = if isEnabled Ext_smart opts || isEnabled Ext_special_strings opts+             then replaceSpecialStrings str+             else str+  return $ escapeString str' inlineToOrg (Math t str) = do   modify $ \st -> st{ stHasMath = True }   return $ if t == InlineMath@@ -547,7 +579,7 @@   case txt of         [Str x] | escapeURI x == src ->  -- autolink              return $ "[[" <> literal (orgPath x) <> "]]"-        _ -> do contents <- inlineListToOrg txt+        _ -> do contents <- nowrap <$> inlineListToOrg txt                 return $ "[[" <> literal (orgPath src) <> "][" <> contents <> "]]" inlineToOrg (Image _ _ (source, _)) =   return $ "[[" <> literal (orgPath source) <> "]]"
src/Text/Pandoc/Writers/Powerpoint/Output.hs view
@@ -914,6 +914,8 @@                  Just Svg  -> Just ".svg"                  Just Emf  -> Just ".emf"                  Just Tiff -> Just ".tiff"+                 Just Webp -> Just ".webp"+                 Just Avif -> Just ".avif"                  Nothing   -> Nothing    let newGlobalId = fromMaybe (maxGlobalId + 1) (M.lookup fp globalIds)@@ -1058,7 +1060,8 @@        mknode "p:sp" [] [ mknode "p:nvSpPr" []                           [ mknode "p:cNvPr" [("id","1"), ("name","TextBox 3")] ()                           , mknode "p:cNvSpPr" [("txBox", "1")] ()-                          , mknode "p:nvPr" [] ()+                          , mknode "p:nvPr" []+                            [mknode "p:ph" [("idx", "1")] ()]                           ]                         , mknode "p:spPr" []                           [ mknode "a:xfrm" []@@ -1414,7 +1417,7 @@ graphicToElement :: PandocMonad m => Integer -> Graphic -> P m Element graphicToElement tableWidth (Tbl widths tblPr hdrCells rows) = do   let totalWidth = sum widths-  let colWidths = if any (== 0.0) widths+  let colWidths = if 0.0 `elem` widths                   then if null hdrCells                       then case rows of                          r@(_:_) : _ -> replicate (length r) $@@ -1751,7 +1754,9 @@   , Just cSld <- findChild (elemName ns "p" "cSld") layout   , Just spTree <- findChild (elemName ns "p" "spTree") cSld = do       let combinedAuthorElems = intercalate [Break] authorsElems-          subtitleAndAuthorElems = intercalate [Break, Break] [subtitleElems, combinedAuthorElems]+          subtitleAndAuthorElems = intercalate [Break, Break] $+                                    filter (not . null)+                                     [subtitleElems, combinedAuthorElems]       (titleId, titleElement) <- nonBodyTextToElement layout [PHType "ctrTitle"] titleElems       (subtitleId, subtitleElement) <- nonBodyTextToElement layout [PHType "subTitle"] subtitleAndAuthorElems       (dateId, dateElement) <- nonBodyTextToElement layout [PHType "dt"] dateElems@@ -2439,8 +2444,11 @@   P m Element presentationToSldIdLst minimumSlideRId (Presentation _ slides) = do   ids <- mapM (slideToSldIdElement minimumSlideRId) slides-  return $ mknode "p:sldIdLst" [] ids+  return $ mkNodeSldIdLst ids +mkNodeSldIdLst :: [Element] -> Element+mkNodeSldIdLst = mknode "p:sldIdLst" []+ presentationToPresentationElement ::   PandocMonad m =>   PresentationRIdUpdateData ->@@ -2454,10 +2462,9 @@   sldIdLst <- presentationToSldIdLst minSlideRId pres    let modifySldIdLst :: Content -> Content-      modifySldIdLst (Elem e) = case elName e of-        (QName "sldIdLst" _ _) -> Elem sldIdLst-        _                      -> Elem e-      modifySldIdLst ct = ct+      modifySldIdLst ct = if isSldIdLst ct+                          then Elem sldIdLst+                          else ct        notesMasterRId = maxSlideRId @@ -2483,15 +2490,9 @@       removeUnwantedMaster :: [Content] -> [Content]       removeUnwantedMaster = concatMap removeUnwantedMaster' -      insertNotesMaster' :: Content -> [Content]-      insertNotesMaster' (Elem e) = case elName e of-        (QName "sldMasterIdLst" _ _) -> [Elem e, Elem notesMasterElem]-        _                            -> [Elem e]-      insertNotesMaster' ct = [ct]-       insertNotesMaster :: [Content] -> [Content]       insertNotesMaster = if presHasSpeakerNotes pres-                          then concatMap insertNotesMaster'+                          then insertAfterSldMasterIdLst notesMasterElem                           else id        updateRIds :: Content -> Content@@ -2511,10 +2512,33 @@         let newValue = updatePresentationRId presentationUpdateRIdData oldValue         pure attr {attrVal = "rId" <> T.pack (show newValue)} +      -- if there is no sldIdLst in the presentation.xml file, add an empty one+      -- after the sldMasterIdLst so modifySldIdLst can replace it.++      insertSldIdListIfMissing :: [Content] -> [Content]+      insertSldIdListIfMissing contentList = if any isSldIdLst contentList+                                             then contentList+                                             else insertAfterSldMasterIdLst (mkNodeSldIdLst []) contentList++      insertAfterSldMasterIdLst' :: Content -> Content -> [Content]+      insertAfterSldMasterIdLst' newElement ct = if isElemName "sldMasterIdLst" ct+                                                 then [ct, newElement]+                                                 else [ct]++      insertAfterSldMasterIdLst :: Element -> [Content] -> [Content]+      insertAfterSldMasterIdLst newElement = concatMap $ insertAfterSldMasterIdLst' $ Elem newElement++      isElemName :: T.Text -> Content -> Bool+      isElemName name (Elem e) = qName (elName e) == name+      isElemName _ _ = False++      isSldIdLst :: Content -> Bool+      isSldIdLst = isElemName "sldIdLst"+       newContent = insertNotesMaster $                    removeUnwantedMaster $                    (modifySldIdLst . updateRIds) <$>-                   elContent element+                   insertSldIdListIfMissing (elContent element)    return $ element{elContent = newContent} @@ -2665,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"@@ -2684,7 +2712,7 @@                        relativePaths   speakerNotesOverrides <- mapMaybe pathToOverride <$> getSpeakerNotesFilePaths   return $ ContentTypes-    (defaults <> mediaDefaults)+    (defaults <> mediaDefaults <> fontDefaults)     (inheritedOverrides <> createdOverrides <> slideOverrides <> speakerNotesOverrides)  presML :: T.Text
src/Text/Pandoc/Writers/Powerpoint/Presentation.hs view
@@ -176,11 +176,6 @@ runPres env st p = (pres, reverse $ stLog finalSt)   where (pres, finalSt) = runState (runReaderT p env) st --- GHC 7.8 will still complain about concat <$> mapM unless we specify--- Functor. We can get rid of this when we stop supporting GHC 7.8.-concatMapM        :: (Monad m) => (a -> m [b]) -> [a] -> m [b]-concatMapM f xs   =  liftM concat (mapM f xs)- type Pixels = Integer  data Presentation = Presentation DocProps [Slide]@@ -348,7 +343,7 @@ --------------------------------------------------  inlinesToParElems :: [Inline] -> Pres [ParaElem]-inlinesToParElems = concatMapM inlineToParElems+inlinesToParElems = fmap mconcat . mapM inlineToParElems  inlineToParElems :: Inline -> Pres [ParaElem] inlineToParElems (Str s) = do@@ -460,15 +455,17 @@                                     , pPropIndent = Just 0                                     }                 , envRunProps = (envRunProps r){rPropCode = True}}) $ do-    mbSty <- writerHighlightStyle <$> asks envOpts+    highlightOpt <- writerHighlightMethod <$> asks envOpts     synMap <- writerSyntaxMap <$> asks envOpts-    case mbSty of-      Just sty ->-        case highlight synMap (formatSourceLines sty) attr str of-          Right pElems -> do pPropsNew <- asks envParaProps-                             return [Paragraph pPropsNew pElems]-          Left _ -> blockToParagraphs $ Para [Str str]-      Nothing -> blockToParagraphs $ Para [Str str]+    let highlightWithStyle style = do+          case highlight synMap (formatSourceLines style) attr str of+            Right pElems -> do pPropsNew <- asks envParaProps+                               return [Paragraph pPropsNew pElems]+            Left _ -> blockToParagraphs $ Para [Str str]+    case highlightOpt of+      Skylighting sty -> highlightWithStyle sty+      DefaultHighlighting -> highlightWithStyle defaultStyle+      _ -> blockToParagraphs $ Para [Str str] -- We can't yet do incremental lists, but we should render a -- (BlockQuote List) as a list to maintain compatibility with other -- formats.@@ -482,7 +479,7 @@                                                  , pPropIndent = Just 0                                                  }                 , envRunProps = (envRunProps r){rPropForceSize = Just blockQuoteSize}})$-  concatMapM blockToParagraphs blks+  mconcat <$> mapM blockToParagraphs blks -- TODO: work out the format blockToParagraphs blk@(RawBlock _ _) = do addLogMessage $ BlockNotRendered blk                                           return []@@ -506,7 +503,7 @@                                            , pPropIndent = Nothing                                            , pPropIncremental = incremental                                            }}) $-    concatMapM multiParList blksLst+    mconcat <$> mapM multiParList blksLst blockToParagraphs (OrderedList listAttr blksLst) = do   pProps <- asks envParaProps   incremental <- listShouldBeIncremental@@ -516,7 +513,7 @@                                            , pPropIndent = Nothing                                            , pPropIncremental = incremental                                            }}) $-    concatMapM multiParList blksLst+    mconcat <$> mapM multiParList blksLst blockToParagraphs (DefinitionList entries) = do   incremental <- listShouldBeIncremental   let go :: ([Inline], [[Block]]) -> Pres [Paragraph]@@ -524,11 +521,12 @@         term <-blockToParagraphs $ Para [Strong ils]         -- For now, we'll treat each definition term as a         -- blockquote. We can extend this further later.-        definition <- concatMapM (blockToParagraphs . BlockQuote) blksLst+        definition <-+          mconcat <$> mapM (blockToParagraphs . BlockQuote) blksLst         return $ term ++ definition   local (\env -> env {envParaProps =                        (envParaProps env) {pPropIncremental = incremental}})-    $ concatMapM go entries+    $ mconcat <$> mapM go entries blockToParagraphs (Div (_, classes, _) blks) = let   hasIncremental = "incremental" `elem` classes   hasNonIncremental = "nonincremental" `elem` classes@@ -536,7 +534,7 @@                    | hasNonIncremental -> Just InNonIncremental                    | otherwise -> Nothing   addIncremental env = env { envInIncrementalDiv = incremental }-  in local addIncremental (concatMapM blockToParagraphs blks)+  in local addIncremental (mconcat <$> mapM blockToParagraphs blks) blockToParagraphs (Figure attr capt blks) = -- This never seems to be used:   blockToParagraphs (Shared.figureDiv attr capt blks) blockToParagraphs hr@HorizontalRule = notRendered hr@@ -561,7 +559,7 @@                   , pPropLevel = level + 1                   }                 })-        $ concatMapM blockToParagraphs bs+        $ mconcat <$> mapM blockToParagraphs bs   return $ p ++ ps  cellToParagraphs :: Alignment -> SimpleCell -> Pres [Paragraph]@@ -725,6 +723,7 @@   , "columns" `elem` classes   , Div (_, clsL, _) blksL : Div (_, clsR, _) blksR : remaining <- divBlks   , "column" `elem` clsL, "column" `elem` clsR = do+      -- At least 2 column elements       mapM_ (addLogMessage . BlockNotRendered) (blks ++ remaining)       let mkTwoColumn left right = do             blksL' <- join . take 1 <$> splitBlocks left@@ -753,6 +752,16 @@       if (any null [blksL1, blksL2]) && (any null [blksR1, blksR2])       then mkTwoColumn blksL blksR       else mkComparison blksL1 blksL2 blksR1 blksR2+  | Div (_, classes, _) divBlks <- blk+  , "columns" `elem` classes+  , Div (_, cls, _) columnBlks : remaining <- divBlks+  , "column" `elem` cls = do+      -- Only 1 column element.+      mapM_ (addLogMessage . BlockNotRendered) (blks ++ remaining)+      clBlks' <- join . take 1 <$> splitBlocks columnBlks+      shapes <- blocksToShapes clBlks'+      sldId <- asks envCurSlideId+      return $ Slide sldId (ContentSlide [] shapes) spkNotes Nothing bodyBlocksToSlide _ (blk : blks) spkNotes = do       sldId <- asks envCurSlideId       inNoteSlide <- asks envInNoteSlide@@ -811,7 +820,7 @@ blockToSpeakerNotes :: Block -> Pres SpeakerNotes blockToSpeakerNotes (Div (_, ["notes"], _) blks) =   local (\env -> env{envInSpeakerNotes=True}) $-  SpeakerNotes <$> concatMapM blockToParagraphs blks+  SpeakerNotes . mconcat <$> mapM blockToParagraphs blks blockToSpeakerNotes _ = return mempty  handleSpeakerNotes :: Block -> Pres ()@@ -878,6 +887,12 @@   subtitle <- inlinesToParElems $ lookupMetaInlines "subtitle" meta   authors <- mapM inlinesToParElems $ docAuthors meta   date <- inlinesToParElems $ docDate meta+  -- Get speaker notes from metadata "notes" field+  let notesBlocks = lookupMetaBlocks "notes" meta+  speakerNotes <- if null notesBlocks+                  then return mempty+                  else local (\env -> env{envInSpeakerNotes=True}) $+                       SpeakerNotes . mconcat <$> mapM blockToParagraphs notesBlocks   if null title && null subtitle && null authors && null date     then return Nothing     else return $@@ -885,7 +900,7 @@          Slide          metadataSlideId          (MetadataSlide title subtitle authors date)-         mempty+         speakerNotes          Nothing  addSpeakerNotesToMetaSlide :: Slide -> [Block] -> Pres (Slide, [Block])
src/Text/Pandoc/Writers/RST.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE ViewPatterns      #-} {- |    Module      : Text.Pandoc.Writers.RST-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -20,7 +20,8 @@                   GeneralCategory(                         ClosePunctuation, OpenPunctuation, InitialQuote,                          FinalQuote, DashPunctuation, OtherPunctuation))-import Data.List (transpose, intersperse, foldl')+import Data.List (transpose, intersperse)+import qualified Data.List as L import qualified Data.List.NonEmpty as NE import Data.Maybe (fromMaybe) import qualified Data.Text as T@@ -251,15 +252,20 @@   let admonition = case classes of                         (cl:_)                           | cl `elem` admonitions-                          -> ".. " <> literal cl <> "::"-                        cls -> ".. container::" <> space <>+                          -> blankline <> ".. " <> literal cl <> "::"+                        cls -> blankline <> ".. container::" <> space <>                                    literal (T.unwords (filter (/= "container") cls))+  -- if contents start with block quote, we need to insert+  -- an empty comment to fix the indentation point (#10236)+  let contents' = case bs of+                    BlockQuote{}:_-> ".." $+$ contents+                    _ -> contents   return $ blankline $$            admonition $$            (if T.null ident                then blankline                else "   :name: " <> literal ident $$ blankline) $$-           nest 3 contents $$+           nest 3 contents' $$            blankline blockToRST (Plain inlines) = inlineListToRST inlines blockToRST (Para inlines)@@ -318,13 +324,14 @@                      c `notElem` ["sourceCode","literate","numberLines",                                   "number-lines","example"]] of              []       -> "::"-             (lang:_) -> (".. code:: " <> literal lang) $$ numberlines)+             (lang:_) -> (blankline <> ".. code:: " <> literal lang) $$ numberlines)           $+$ nest 3 (literal str) $$ blankline blockToRST (BlockQuote blocks) = do   contents <- blockListToRST blocks   return $ nest 3 contents <> blankline-blockToRST (Table _attrs blkCapt specs thead tbody tfoot) = do-  let (caption, aligns, widths, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot+blockToRST (Table _attrs blkCapt specs thead@(TableHead _ theadRows) tbody tfoot@(TableFoot _ tfootRows)) = do+  let (caption, aligns, widths, headers, rows) =+        toLegacyTable blkCapt specs thead tbody tfoot   caption' <- inlineListToRST caption   let blocksToDoc opts bs = do          oldOpts <- gets stOptions@@ -333,12 +340,13 @@          modify $ \st -> st{ stOptions = oldOpts }          return result   opts <- gets stOptions-  let renderGrid = gridTable opts blocksToDoc (all null headers)-                    (map (const AlignDefault) aligns) widths-                    headers rows-      isSimple = all (== 0) widths && length widths > 1+  let specs' = map (\(_,width) -> (AlignDefault, width)) specs+      renderGrid = gridTable opts blocksToDoc specs' thead tbody tfoot+      rowHasRowSpan (Row _ cells) = any cellHasRowSpan cells+      cellHasRowSpan (Cell _ _ rowSpan _ _) = rowSpan > 1+      isSimple = all (== 0) widths && length widths > 1 && not (any rowHasRowSpan $ theadRows ++ tableBodiesToRows tbody ++ tfootRows)       renderSimple = do-        tbl' <- simpleTable opts blocksToDoc headers rows+        tbl' <- simpleTable opts blocksToDoc thead tbody tfoot         if offset tbl' > writerColumns opts           then renderGrid           else return tbl'@@ -351,9 +359,9 @@         | otherwise = renderGrid   tbl <- rendered   return $ blankline $$-           (if null caption+           (if null caption || isList                then tbl-               else (".. table:: " <> caption') $$ blankline $$ nest 3 tbl) $$+               else (blankline <> ".. table:: " <> caption') $$ blankline $$ nest 3 tbl) $$            blankline blockToRST (BulletList items) = do   contents <- mapM bulletListItemToRST items@@ -421,7 +429,12 @@ bulletListItemToRST :: PandocMonad m => [Block] -> RST m (Doc Text) bulletListItemToRST items = do   contents <- blockListToRST items-  return $ hang 3 "-  " contents $$+  -- if a list item starts with block quote, we need to insert+  -- an empty comment to fix the indentation point (#10236)+  let contents' = case items of+                    BlockQuote{}:_-> ".." $+$ contents+                    _ -> contents+  return $ hang 2 "- " contents' $$       if null items || (endsWithPlain items && not (endsWithList items))          then cr          else blankline@@ -434,7 +447,12 @@ orderedListItemToRST marker items = do   contents <- blockListToRST items   let marker' = marker <> " "-  return $ hang (T.length marker') (literal marker') contents $$+  -- if a list item starts with block quote, we need to insert+  -- an empty comment to fix the indentation point (#10236)+  let contents' = case items of+                    BlockQuote{}:_-> ".." $+$ contents+                    _ -> contents+  return $ hang (T.length marker') (literal marker') contents' $$       if null items || (endsWithPlain items && not (endsWithList items))          then cr          else blankline@@ -450,7 +468,12 @@ definitionListItemToRST (label, defs) = do   label' <- inlineListToRST label   contents <- liftM vcat $ mapM blockListToRST defs-  return $ nowrap label' $$ nest 3 (nestle contents) $$+  -- if definition list starts with block quote, we need to insert+  -- an empty comment to fix the indentation point (#10236)+  let contents' = case defs of+                    (BlockQuote{}:_):_ -> ".." $+$ contents+                    _ -> contents+  return $ nowrap label' $$ nest 3 (nestle contents') $$       if isTightList defs          then cr          else blankline@@ -547,24 +570,8 @@         toColumns :: Int -> Double -> Int         toColumns t p = round (p * fromIntegral t)         listTableContent :: PandocMonad m => [[[Block]]] -> RST m (Doc Text)-        listTableContent = joinTable joinDocsM joinDocsM .-                           mapTable blockListToRST-        -- joinDocsM adapts joinDocs in order to work in the `RST m` monad-        joinDocsM :: PandocMonad m => [RST m (Doc Text)] -> RST m (Doc Text)-        joinDocsM = fmap joinDocs . sequence-        -- joinDocs will be used to join cells and to join rows-        joinDocs :: [Doc Text] -> Doc Text-        joinDocs items = blankline $$-                         (chomp . vcat . map formatItem) items $$-                         blankline-        formatItem :: Doc Text -> Doc Text-        formatItem i = hang 3 "- " (i <> cr)-        -- apply a function to all table cells changing their type-        mapTable :: (a -> b) -> [[a]] -> [[b]]-        mapTable = map . map-        -- function hor to join cells and function ver to join rows-        joinTable :: ([a] -> a) -> ([a] -> a) -> [[a]] -> a-        joinTable hor ver = ver . map hor+        listTableContent = fmap vcat .+          mapM (fmap (hang 2 (text "* ") . vcat) . mapM bulletListItemToRST)  transformInlines :: [Inline] -> [Inline] transformInlines =  insertBS .@@ -668,7 +675,7 @@   | null contents = [outer]   | otherwise     = combineAll contents   where contents = dropInlineParent outer-        combineAll = foldl' combine []+        combineAll = L.foldl' combine []          combine :: [Inline] -> Inline -> [Inline]         combine f i =@@ -914,25 +921,70 @@ simpleTable :: PandocMonad m             => WriterOptions             -> (WriterOptions -> [Block] -> m (Doc Text))-            -> [[Block]]-            -> [[[Block]]]+            -> TableHead+            -> [TableBody]+            -> TableFoot             -> m (Doc Text)-simpleTable opts blocksToDoc headers rows = do-  -- can't have empty cells in first column:-  let fixEmpties (d:ds) = if isEmpty d-                             then literal "\\ " : ds-                             else d : ds-      fixEmpties [] = []-  headerDocs <- if all null headers+simpleTable opts blocksToDoc (TableHead _ headers) tbody (TableFoot _ footers) = do+  headerDocs <- if allRowsEmpty headers                    then return []-                   else fixEmpties <$> mapM (blocksToDoc opts) headers-  rowDocs <- mapM (fmap fixEmpties . mapM (blocksToDoc opts)) rows-  let numChars = maybe 0 maximum . NE.nonEmpty . map offset-  let colWidths = map numChars $ transpose (headerDocs : rowDocs)-  let toRow = mconcat . intersperse (lblock 1 " ") . zipWith lblock colWidths+                   else fixEmpties <$> mapM rowToDoc headers+  rowDocs <- fixEmpties <$> mapM rowToDoc ((tableBodiesToRows tbody) ++ footers)+  let numChars = maybe 0 maximum . NE.nonEmpty . map (offset . fst)+  let colWidths = map numChars $ transpose (headerDocs ++ rowDocs)   let hline = nowrap $ hsep (map (\n -> literal (T.replicate n "=")) colWidths)-  let hdr = if all null headers+  let hdr = if allRowsEmpty headers                then mempty-               else hline $$ toRow headerDocs-  let bdy = vcat $ map toRow rowDocs+               else hline $$ mapToRow colWidths headerDocs+  let bdy = mapToRow colWidths rowDocs   return $ hdr $$ hline $$ bdy $$ hline+  where+    -- can't have empty cells in first column:+    fixEmpties (d:ds) = fixEmpties' d : ds+    fixEmpties [] = []++    fixEmpties' ((d, colSpan):ds) = if isEmpty d+                                     then (literal "\\ ", colSpan) : ds+                                     else (d, colSpan) : ds+    fixEmpties' [] = []++    rowToDoc (Row _ cells) = concat <$> mapM cellToDocs cells++    cellToDocs (Cell _ _ _ colSpan blocks) = applyColSpan colSpan <$> (blocksToDoc opts) blocks++    applyColSpan col@(ColSpan colSpan) doc+      | colSpan > 1 =+          -- Fill up columns for the col spans by adding empty docs without a ColSpan.+          let emptyDoc = (literal "", Nothing)+          in  (doc, Just col) : replicate (colSpan - 1) emptyDoc+      | otherwise = [(doc, Just col)]++    mapToRow colWidths = vcat . concatMap (toRow colWidths)++    toRow colWidths rowDocsWithColSpans =+      let (rowDocs, colSpans) = unzip rowDocsWithColSpans+          row = intersperseDivider $ zipWith lblock colWidths rowDocs+          colSpanRow = intersperseDivider $ writeColSpans colSpans colWidths+      in  if any (maybe False (> 1)) colSpans+           then [row, colSpanRow]+           else [row] -- Don't write out col spans if they are all just 1.++    intersperseDivider = mconcat . intersperse (lblock 1 " ")++    -- Write col span dashes to match the length of the col widths.+    writeColSpans [] _ = []+    writeColSpans _ [] = []+    writeColSpans (Nothing : remainingColSpans) colWidths = writeColSpans remainingColSpans colWidths+    writeColSpans (Just (ColSpan colSpan) : remainingColSpans) colWidths =+      let (colWidths', remainingColWidths) = splitAt colSpan colWidths+      in  writeColSpanDashes colWidths' : writeColSpans remainingColSpans remainingColWidths++    writeColSpanDashes colWidths =+      let colWidthsLength = length colWidths+          colWidthsSum = sum colWidths+          dashLength = if colWidthsLength > 1+            -- Offset by 1 for the white spaces between columns so that the col+            -- span dashes align with the end of the columns correctly.+            then colWidthsSum + colWidthsLength - 1+            else colWidthsSum+      in  literal $ T.replicate dashLength "-"
src/Text/Pandoc/Writers/RTF.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE OverloadedStrings   #-} {- |    Module      : Text.Pandoc.Writers.RTF-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -281,8 +281,9 @@                  else sizes'   columns <- T.concat <$>      zipWithM (tableItemToRTF indent) aligns cols-  let rightEdges = tail $ scanl (\sofar new -> sofar + floor (new * totalTwips))-                                (0 :: Integer) sizes+  let rightEdges = drop 1 $+                    scanl (\sofar new -> sofar + floor (new * totalTwips))+                          (0 :: Integer) sizes   let cellDefs = map (\edge -> (if header                                    then "\\clbrdrb\\brdrs"                                    else "") <> "\\cellx" <> tshow edge)
src/Text/Pandoc/Writers/Roff.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Writers.Roff-   Copyright   : Copyright (C) 2007-2023 John MacFarlane+   Copyright   : Copyright (C) 2007-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -26,13 +26,12 @@ import Data.Text (Text) import qualified Data.Text as Text import Data.String-import Data.Maybe (fromMaybe, isJust, catMaybes)+import Data.Maybe (fromMaybe) import Text.Pandoc.Class.PandocMonad (PandocMonad) import Text.Pandoc.Definition import Text.DocLayout import Text.Printf (printf)-import Text.Pandoc.RoffChar (standardEscapes,-                              characterCodes, combiningAccents)+import Text.Pandoc.RoffChar (standardEscapes, characterCodes)  data WriterState = WriterState { stHasInlineMath :: Bool                                , stFirstPara     :: Bool@@ -68,36 +67,37 @@                 | AsciiOnly        -- ^ escape everything                 deriving Show -combiningAccentsMap :: Map.Map Char Text-combiningAccentsMap = Map.fromList combiningAccents- essentialEscapes :: Map.Map Char Text essentialEscapes = Map.fromList standardEscapes --- | Escape special characters for roff.-escapeString :: EscapeMode -> Text -> Text-escapeString e = Text.concat . escapeString' e . Text.unpack+-- | Escape special characters for roff. If the first parameter is+-- True, escape @-@ as @\-@, as required by current versions of groff man;+-- otherwise leave it unescaped, as neededfor ms.+escapeString :: Bool -> EscapeMode -> Text -> Text+escapeString escapeHyphen e = Text.concat . escapeString' e . Text.unpack   where     escapeString' _ [] = []     escapeString' escapeMode ('\n':'.':xs) =       "\n\\&." : escapeString' escapeMode xs+    -- see #10533; we need to escape hyphens as \- in man but not in ms:+    escapeString' escapeMode ('-':xs) | escapeHyphen =+      "\\-" : escapeString' escapeMode xs     escapeString' escapeMode (x:xs) =       case Map.lookup x essentialEscapes of         Just s  -> s : escapeString' escapeMode xs         Nothing           | isAscii x -> Text.singleton x : escapeString' escapeMode xs           | otherwise ->-              case escapeMode of-                AllowUTF8 -> Text.singleton x : escapeString' escapeMode xs+              (case escapeMode of+                AllowUTF8 -> Text.singleton x                 AsciiOnly ->-                  let accents = catMaybes $ takeWhile isJust-                        (map (`Map.lookup` combiningAccentsMap) xs)-                      rest = drop (length accents) xs-                      s = case Map.lookup x characterCodeMap of-                            Just t  -> "\\[" <> Text.unwords (t:accents) <> "]"-                            Nothing -> "\\[" <> Text.unwords-                              (Text.pack (printf "u%04X" (ord x)) : accents) <> "]"-                  in  s : escapeString' escapeMode rest+                   case Map.lookup x characterCodeMap of+                      Just t+                        | Text.length t == 2 -> "\\(" <> t -- see #10716+                        | otherwise -> "\\C'" <> t <> "'"+                      Nothing ->+                        "\\C'" <> Text.pack (printf "u%04X" (ord x)) <> "'")+               : escapeString' escapeMode xs  characterCodeMap :: Map.Map Char Text characterCodeMap = Map.fromList characterCodes
src/Text/Pandoc/Writers/Shared.hs view
@@ -5,7 +5,7 @@ {-# LANGUAGE LambdaCase #-} {- |    Module      : Text.Pandoc.Writers.Shared-   Copyright   : Copyright (C) 2013-2023 John MacFarlane+   Copyright   : Copyright (C) 2013-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -38,23 +38,34 @@                      , stripLeadingTrailingSpace                      , toSubscript                      , toSuperscript+                     , toSubscriptInline+                     , toSuperscriptInline                      , toTableOfContents                      , endsWithPlain                      , toLegacyTable                      , splitSentences                      , ensureValidXmlIdentifiers+                     , removeLinks                      , setupTranslations                      , isOrderedListMarker+                     , toTaskListItem+                     , delimited+                     , allRowsEmpty+                     , tableBodiesToRows+                     , insertCurrentSpansAtColumn+                     , takePreviousSpansAtColumn+                     , decrementTrailingRowSpans                      ) where-import Safe (lastMay)+import Safe (lastMay, maximumMay) import qualified Data.ByteString.Lazy as BL-import Control.Monad (zipWithM)+import Control.Monad (MonadPlus, mzero) import Data.Either (isRight) import Data.Aeson (ToJSON (..), encode) import Data.Char (chr, ord, isSpace, isLetter, isUpper)-import Data.List (groupBy, intersperse, transpose, foldl')-import Data.List.NonEmpty (NonEmpty(..), nonEmpty)+import Data.List (groupBy, intersperse, transpose, zipWith4)+import qualified Data.List as L+import Data.List.NonEmpty (NonEmpty((:|))) import Data.Text.Conversions (FromText(..)) import qualified Data.Map as M import qualified Data.Text as T@@ -69,7 +80,7 @@ import Text.Pandoc.Shared (stringify, makeSections, blocksToInlines) import Text.Pandoc.Walk (Walkable(..)) import qualified Text.Pandoc.UTF8 as UTF8-import Text.Pandoc.XML (escapeStringForXML)+import Text.Pandoc.XML (escapeStringForXML, rdfaAttributes, html5Attributes) import Text.DocTemplates (Context(..), Val(..), TemplateTarget,                           ToContext(..), FromContext(..)) import Text.Pandoc.Chunks (tocToList, toTOCTree)@@ -77,7 +88,11 @@ import Text.Pandoc.Class (PandocMonad, toLang) import Text.Pandoc.Translations (setTranslations) import Data.Maybe (fromMaybe)+import qualified Text.Pandoc.Writers.AnnotatedTable as Ann+import qualified Data.Set as Set +-- import Debug.Trace+ -- | Create template Context from a 'Meta' and an association list -- of variables, specified at the command line or in the writer. -- Variables overwrite metadata fields with the same names.@@ -192,9 +207,18 @@   ,if null classes       then empty       else "class=" <> doubleQuotes (text $ T.unpack (T.unwords classes))-  ,hsep (map (\(k,v) -> text (T.unpack k) <> "=" <>+  ,hsep (map (\(k,v) -> formatKey k <> "=" <>                 doubleQuotes (text $ T.unpack (escapeStringForXML v))) kvs)   ])+ where+   formatKey x = text . T.unpack $+        if (x `Set.member` (html5Attributes <> rdfaAttributes)+            && x /= "label") -- #10048+             || T.any (== ':') x -- e.g. epub: namespace+             || "data-" `T.isPrefixOf` x+             || "aria-" `T.isPrefixOf` x+           then x+           else "data-" <> x  addSpaceIfNotEmpty :: HasChars a => Doc a -> Doc a addSpaceIfNotEmpty f = if isEmpty f then f else " " <> f@@ -278,122 +302,305 @@   _       -> T.singleton c  -- | Writes a grid table.-gridTable :: (Monad m, HasChars a)-          => WriterOptions-          -> (WriterOptions -> [Block] -> m (Doc a)) -- ^ format Doc writer-          -> Bool             -- ^ headless-          -> [Alignment]      -- ^ column alignments-          -> [Double]         -- ^ column widths-          -> [[Block]]        -- ^ table header row-          -> [[[Block]]]      -- ^ table body rows-          -> m (Doc a)-gridTable opts blocksToDoc headless aligns widths headers rows = do-  -- the number of columns will be used in case of even widths-  let numcols = maximum (length aligns :| length widths :-                           map length (headers:rows))-  let officialWidthsInChars :: [Double] -> [Int]-      officialWidthsInChars widths' = map (-                        (max 1) .-                        (\x -> x - 3) . floor .-                        (fromIntegral (writerColumns opts) *)-                        ) widths'-  -- handleGivenWidths wraps the given blocks in order for them to fit-  -- in cells with given widths. the returned content can be-  -- concatenated with borders and frames-  let handleGivenWidthsInChars widthsInChars' = do-        -- replace page width (in columns) in the options with a-        -- given width if smaller (adjusting by two)-        let useWidth w = opts{writerColumns = min (w - 2) (writerColumns opts)}-        -- prepare options to use with header and row cells-        let columnOptions = map useWidth widthsInChars'-        rawHeaders' <- zipWithM blocksToDoc columnOptions headers-        rawRows' <- mapM-             (\cs -> zipWithM blocksToDoc columnOptions cs)-             rows-        return (widthsInChars', rawHeaders', rawRows')-  let handleGivenWidths widths' = handleGivenWidthsInChars-                                     (officialWidthsInChars widths')-  -- handleFullWidths tries to wrap cells to the page width or even-  -- more in cases where `--wrap=none`. thus the content here is left-  -- as wide as possible-  let handleFullWidths widths' = do-        rawHeaders' <- mapM (blocksToDoc opts) headers-        rawRows' <- mapM (mapM (blocksToDoc opts)) rows-        let numChars = maybe 0 maximum . nonEmpty . map offset-        let minWidthsInChars =-                map numChars $ transpose (rawHeaders' : rawRows')-        let widthsInChars' = zipWith max-                              minWidthsInChars-                              (officialWidthsInChars widths')-        return (widthsInChars', rawHeaders', rawRows')-  -- handleZeroWidths calls handleFullWidths to check whether a wide-  -- table would fit in the page. if the produced table is too wide,-  -- it calculates even widths and passes the content to-  -- handleGivenWidths-  let handleZeroWidths widths' = do-        (widthsInChars', rawHeaders', rawRows') <- handleFullWidths widths'-        if foldl' (+) 0 widthsInChars' > writerColumns opts-           then do -- use even widths except for thin columns-             let evenCols  = max 5-                              (((writerColumns opts - 1) `div` numcols) - 3)-             let (numToExpand, colsToExpand) =-                   foldr (\w (n, tot) -> if w < evenCols-                                            then (n, tot + (evenCols - w))-                                            else (n + 1, tot))-                                   (0,0) widthsInChars'-             let expandAllowance = colsToExpand `div` numToExpand-             let newWidthsInChars = map (\w -> if w < evenCols-                                                  then w-                                                  else min-                                                       (evenCols + expandAllowance)-                                                       w)-                                        widthsInChars'-             handleGivenWidthsInChars newWidthsInChars-           else return (widthsInChars', rawHeaders', rawRows')-  -- render the contents of header and row cells differently depending-  -- on command line options, widths given in this specific table, and-  -- cells' contents-  let handleWidths-        | writerWrapText opts == WrapNone    = handleFullWidths widths-        | all (== 0) widths                  = handleZeroWidths widths-        | otherwise                          = handleGivenWidths widths-  (widthsInChars, rawHeaders, rawRows) <- handleWidths-  let hpipeBlocks blocks = hcat [beg, middle, end]-        where sep'    = vfill " | "-              beg     = vfill "| "-              end     = vfill " |"-              middle  = chomp $ hcat $ intersperse sep' blocks-  let makeRow = hpipeBlocks . zipWith lblock widthsInChars-  let head' = makeRow rawHeaders-  let rows' = map (makeRow . map chomp) rawRows-  let borderpart ch align widthInChars =-           (if align == AlignLeft || align == AlignCenter-               then char ':'-               else char ch) <>-           text (replicate widthInChars ch) <>-           (if align == AlignRight || align == AlignCenter-               then char ':'-               else char ch)-  let border ch aligns' widthsInChars' =-        char '+' <>-        hcat (intersperse (char '+') (zipWith (borderpart ch)-                aligns' widthsInChars')) <> char '+'-  let body = vcat $ intersperse (border '-' (repeat AlignDefault) widthsInChars)-                    rows'-  let head'' = if headless-                  then empty-                  else head' $$ border '=' aligns widthsInChars-  if headless-     then return $-           border '-' aligns widthsInChars $$-           body $$-           border '-' (repeat AlignDefault) widthsInChars-     else return $-           border '-' (repeat AlignDefault) widthsInChars $$-           head'' $$-           body $$-           border '-' (repeat AlignDefault) widthsInChars+gridTable :: Monad m+           => WriterOptions+           -> (WriterOptions -> [Block] -> m (Doc Text)) -- ^ format Doc writer+           -> [ColSpec]+           -> TableHead+           -> [TableBody]+           -> TableFoot+           -> m (Doc Text)+gridTable opts blocksToDoc colspecs' thead' tbodies' tfoot' = do+  let Ann.Table _ _ colspecs thead tbodies tfoot =+        Ann.toTable mempty (Caption Nothing mempty)+                    colspecs' thead' tbodies' tfoot'+  let renderRows = fmap addDummies . mapM (gridRow opts blocksToDoc)+  let getHeadCells (Ann.HeaderRow _ _ cells) = cells+  let getHeadRows (Ann.TableHead _ rs) = map getHeadCells rs+  headCells <- renderRows (getHeadRows thead)+  let getFootRows (Ann.TableFoot _ xs) = map getHeadCells xs+  footCells <- renderRows (getFootRows tfoot)+  -- We don't distinguish between row head and regular cells here:+  let getBodyCells (Ann.BodyRow _ _ rhcells cells) = rhcells ++ cells+  let getBody (Ann.TableBody _ _ hs xs) = map getHeadCells hs <> map getBodyCells xs+  bodyCells <- mapM (renderRows . getBody) tbodies+  let rows = (setTopBorder SingleLine . setBottomBorder DoubleHeaderLine) headCells +++             (setTopBorder (if null headCells+                               then SingleHeaderLine+                               else SingleLine) . setBottomBorder SingleLine)+                   (mconcat bodyCells) +++             (setTopBorder DoubleLine . setBottomBorder DoubleLine) footCells+  pure $ gridRows $ redoWidths opts colspecs rows +data ColWidthInfo =+  ColWidthInfo+  { colWidthSpecified :: Int+  , colWidthFull :: Int+  , colWidthMin :: Int+  , colWidthUsed :: Int }+  deriving (Show, Ord, Eq)++-- Returns (current widths, full widths, min widths)+extractColWidths :: WriterOptions -> [[RenderedCell Text]] -> [ColWidthInfo]+extractColWidths opts rows =+  zipWith4 ColWidthInfo specifiedwidths fullwidths minwidths currentwidths+ where+   getWidths calcOffset =+     map (fromMaybe 0 . maximumMay) (transpose (map (concatMap (getCellWidths calcOffset)) rows))+   getCellWidths calcOffset c = replicate (cellColSpan c)+                                 (calcOffset c `div` (cellColSpan c) ++                                  calcOffset c `rem` (cellColSpan c))+   fullwidths = getWidths (max 1 . offset . cellContents)+   minwidths =+     case writerWrapText opts of+       WrapNone -> fullwidths+       _ -> getWidths (minOffset . cellContents)+   specifiedwidths = getWidths cellWidth+   currentwidths = zipWith (\specw minw -> if specw == 0+                                              then 0+                                              else max specw minw)+                           specifiedwidths minwidths++resetWidths :: [Int] -> [RenderedCell Text] -> [RenderedCell Text]+resetWidths _ [] = []+resetWidths [] cs = cs+resetWidths (w:ws) (c:cs) =+  case cellColSpan c of+    1 -> c{ cellWidth = w } : resetWidths ws cs+    n | n < 1 -> c : resetWidths ws cs+      | otherwise -> c{ cellWidth = w + sum (take (n - 1) ws) + (3 * (n-1)) }+                               : resetWidths (drop (n - 1) ws) cs++redoWidths :: WriterOptions -> [ColSpec] -> [[RenderedCell Text]] -> [[RenderedCell Text]]+redoWidths _ _ [] = []+redoWidths opts colspecs rows = map (resetWidths newwidths) rows+ where+  numcols = length colspecs+  widthInfos = extractColWidths opts rows+  colsAvailable = writerColumns opts - (3 * numcols) - 1+  -- now, we need to change colWidthUsed 0 to an appropriate number;+  -- either the full width if it fits easily, or an appropriate fraction+  -- of the remaining width.  This must be done recursively, because+  -- once we decide that the full width can fit, that may leave less+  -- space for the remaining columns with default width to fill.+  recalculateWidths finalRun numRuns infos =+    let numUnassigned = length (filter ((== 0) . colWidthUsed) infos)+        unusedCols = colsAvailable - sum (map colWidthUsed infos)+        defwidth = if numUnassigned == 0+                      then 0+                      else unusedCols `div` numUnassigned+        infos' = map (\info -> if colWidthUsed info == 0+                                  then if finalRun+                                          then info{ colWidthUsed =+                                                      max (colWidthMin info) defwidth }+                                          else if colWidthFull info <= defwidth+                                               then info{ colWidthUsed = colWidthFull info }+                                               else info+                                  else info) infos+     in if finalRun || numRuns > 4+           then infos'+           else if infos == infos'+                 then recalculateWidths True (numRuns + 1) infos+                       -- run again, filling in unassigned widths with a fraction of the+                       -- remaining width+                 else recalculateWidths False (numRuns + 1) infos'+                       -- run again, filling in unassigned widths only if the full with+                       -- would be less than the fraction of remaining width+  newwidths = map colWidthUsed $ recalculateWidths False (1 :: Int) widthInfos++makeDummy :: RenderedCell Text -> RenderedCell Text+makeDummy c =+    RenderedCell{ cellColNum = cellColNum c,+                  cellColSpan = cellColSpan c,+                  cellColSpecs = cellColSpecs c,+                  cellAlign = AlignDefault,+                  cellRowSpan = cellRowSpan c - 1,+                  cellWidth = cellWidth c,+                  cellContents = mempty,+                  cellBottomBorder = NoLine,+                  cellTopBorder = NoLine }++addDummies :: [[RenderedCell Text]] -> [[RenderedCell Text]]+addDummies = reverse . L.foldl' go []+ where+   go [] cs = [cs]+   go (prevRow:rs) cs = addDummiesToRow prevRow cs : prevRow : rs+   addDummiesToRow [] cs = cs+   addDummiesToRow ds [] = map makeDummy ds+   addDummiesToRow (d:ds) (c:cs) =+     if cellColNum d < cellColNum c+        then makeDummy d : addDummiesToRow ds (c:cs)+        else c : addDummiesToRow+                   (dropWhile (\x ->+                       cellColNum x < cellColNum c + cellColSpan c) (d:ds))+                   cs+++setTopBorder :: LineStyle -> [[RenderedCell Text]] -> [[RenderedCell Text]]+setTopBorder _ [] = []+setTopBorder sty (cs:rest) = (map (\c -> c{ cellTopBorder = sty }) cs) : rest++setBottomBorder :: LineStyle -> [[RenderedCell Text]] -> [[RenderedCell Text]]+setBottomBorder _ [] = []+setBottomBorder sty [cs] = [map (\c -> c{ cellBottomBorder = sty }) cs]+setBottomBorder sty (c:cs) = c : setBottomBorder sty cs++gridRows :: [[RenderedCell Text]] -> Doc Text+gridRows [] = mempty+gridRows (x:xs) =+  (case x of+     [] -> mempty+     (c:_) | isHeaderStyle (cellTopBorder c)+            -> formatHeaderLine (cellTopBorder c) (x:xs)+           | otherwise+            -> formatBorder cellTopBorder False x)+  $$+  vcat (zipWith (rowAndBottom (x:xs)) (x:xs) (xs ++ [[]]))+ where+  -- generate wrapped contents. include pipe borders, bottom and left++  renderCellContents c =+    -- we don't use cblock or lblock because the content might+    -- be interpreted as an indented code block...even though it+    -- would look better to right-align right-aligned cells...+    -- (TODO: change this on parsing side?)+    lblock (cellWidth c) (cellContents c)++  formatRow cs = vfill "| " <>+   hcat (intersperse (vfill " | ") (map renderCellContents cs)) <> vfill " |"++  rowAndBottom allRows thisRow nextRow =+    let isLastRow = null nextRow+        border1 = case thisRow of+                     [] -> mempty+                     (c:_) -> if isHeaderStyle (cellBottomBorder c)+                                 then formatHeaderLine (cellBottomBorder c) allRows+                                 else formatBorder cellBottomBorder False thisRow+        border2 = case nextRow of+                     [] -> mempty+                     (c:_) -> if isHeaderStyle (cellTopBorder c)+                                 then formatHeaderLine (cellTopBorder c) allRows+                                 else formatBorder cellTopBorder False nextRow+        combinedBorder = if isLastRow+                            then border1+                            else literal $ combineBorders+                                  (render Nothing border1) (render Nothing border2)+    in formatRow thisRow $$ combinedBorder++combineBorders :: Text -> Text -> Text+combineBorders t1 t2 =+  if T.null t1+     then t2+     else T.zipWith go t1 t2+ where+   go '+' _ = '+'+   go _ '+' = '+'+   go ':' _ = ':'+   go _ ':' = ':'+   go '|' '-' = '+'+   go '-' '|' = '+'+   go '|' '=' = '+'+   go '=' '|' = '+'+   go '=' _ = '='+   go _ '=' = '='+   go ' ' d = d+   go c _   = c++formatHeaderLine :: Show a => LineStyle -> [[RenderedCell a]] -> Doc Text+formatHeaderLine lineStyle rows =+  literal $ L.foldl'+    (\t row -> combineBorders t (render Nothing $ formatBorder (const lineStyle) True row))+    mempty rows++formatBorder :: Show a => (RenderedCell a -> LineStyle) -> Bool+             -> [RenderedCell a] -> Doc Text+formatBorder borderStyle alignMarkers cs =+  borderParts <> if lastBorderStyle == NoLine+                            then char '|'+                            else char '+'+ where+   (lastBorderStyle, borderParts) = L.foldl' addBorder (NoLine, mempty) cs+   addBorder (prevBorderStyle, accum) c =+     (borderStyle c, accum <> char junctionChar <> toBorderSection c)+      where junctionChar = case (borderStyle c, prevBorderStyle) of+                               (NoLine, NoLine) -> '|'+                               _ -> '+'+   toBorderSection c =+       text $ leftalign : replicate (cellWidth c) lineChar ++ [rightalign]+     where+       lineChar = case borderStyle c of+                     NoLine -> ' '+                     SingleLine -> '-'+                     SingleHeaderLine -> '-'+                     DoubleLine -> '='+                     DoubleHeaderLine -> '='+       (leftalign, rightalign) =+           case cellAlign c of+             _ | not alignMarkers -> (lineChar,lineChar)+             AlignLeft -> (':',lineChar)+             AlignCenter -> (':',':')+             AlignRight -> (lineChar,':')+             AlignDefault -> (lineChar,lineChar)++data LineStyle = NoLine+               | SingleLine+               | DoubleLine+               | SingleHeaderLine+               | DoubleHeaderLine+    deriving (Show, Ord, Eq)++isHeaderStyle :: LineStyle -> Bool+isHeaderStyle SingleHeaderLine = True+isHeaderStyle DoubleHeaderLine = True+isHeaderStyle _ = False++data RenderedCell a =+  RenderedCell{ cellColNum :: Int+              , cellColSpan :: Int+              , cellColSpecs :: NonEmpty ColSpec+              , cellAlign :: Alignment+              , cellRowSpan :: Int+              , cellWidth :: Int+              , cellContents :: Doc a+              , cellBottomBorder :: LineStyle+              , cellTopBorder :: LineStyle+              }+  deriving (Show)++getColWidth :: ColSpec -> Double+getColWidth (_, ColWidth n) = n+getColWidth (_, ColWidthDefault) = 0 -- TODO?++toCharWidth :: WriterOptions -> Double -> Int+toCharWidth opts width =+  max 0 (floor (width * fromIntegral (writerColumns opts)) - 3)++gridRow :: (Monad m, HasChars a)+        => WriterOptions+        -> (WriterOptions -> [Block] -> m (Doc a)) -- ^ format Doc writer+        -> [Ann.Cell]+        -> m [RenderedCell a]+gridRow opts blocksToDoc = mapM renderCell+ where+  renderer = blocksToDoc opts+  renderCell (Ann.Cell cellcolspecs (Ann.ColNumber colnum)+               (Cell _ _ (RowSpan rowspan) _ blocks)) = do+    let ((align,_):|_) = cellcolspecs+    let width = toCharWidth opts $ sum (fmap getColWidth cellcolspecs)+    rendered <- renderer blocks+    pure $ RenderedCell{ cellColNum = colnum,+                         cellColSpan = length cellcolspecs,+                         cellColSpecs = cellcolspecs,+                         cellAlign = align,+                         cellRowSpan = rowspan,+                         cellWidth = width,+                         cellContents = rendered,+                         cellBottomBorder = if rowspan < 2+                                               then SingleLine+                                               else NoLine,+                         cellTopBorder = SingleLine }++ -- | Retrieve the metadata value for a given @key@ -- and convert to Bool. lookupMetaBool :: Text -> Meta -> Bool@@ -407,6 +614,8 @@  -- | Retrieve the metadata value for a given @key@ -- and extract blocks.+--+-- Note that an empty list is returned for maps, lists, and booleans. lookupMetaBlocks :: Text -> Meta -> [Block] lookupMetaBlocks key meta =   case lookupMeta key meta of@@ -417,6 +626,8 @@  -- | Retrieve the metadata value for a given @key@ -- and extract inlines.+--+-- Note that an empty list is returned for maps and lists. lookupMetaInlines :: Text -> Meta -> [Inline] lookupMetaInlines key meta =   case lookupMeta key meta of@@ -428,6 +639,8 @@  -- | Retrieve the metadata value for a given @key@ -- and convert to String.+--+-- Note that an empty list is returned for maps, lists, and booleans. lookupMetaString :: Text -> Meta -> Text lookupMetaString key meta =   case lookupMeta key meta of@@ -469,6 +682,22 @@   | isSpace c = Just c   | otherwise = Nothing +toSubscriptInline :: Inline -> Maybe Inline+toSubscriptInline Space = Just Space+toSubscriptInline (Span attr ils) = Span attr <$> traverse toSubscriptInline ils+toSubscriptInline (Str s) = Str . T.pack <$> traverse toSubscript (T.unpack s)+toSubscriptInline LineBreak = Just LineBreak+toSubscriptInline SoftBreak = Just SoftBreak+toSubscriptInline _ = Nothing++toSuperscriptInline :: Inline -> Maybe Inline+toSuperscriptInline Space = Just Space+toSuperscriptInline (Span attr ils) = Span attr <$> traverse toSuperscriptInline ils+toSuperscriptInline (Str s) = Str . T.pack <$> traverse toSuperscript (T.unpack s)+toSuperscriptInline LineBreak = Just LineBreak+toSuperscriptInline SoftBreak = Just SoftBreak+toSuperscriptInline _ = Nothing+ -- | Construct table of contents (as a bullet list) from document body. toTableOfContents :: WriterOptions                   -> [Block]@@ -622,6 +851,14 @@   goBlock (Div attr bs) = Div (f attr) bs   goBlock x = x +-- | Convert links to spans; most useful when writing elements that must not+-- contain links, e.g. to avoid nested links.+removeLinks :: [Inline] -> [Inline]+removeLinks = walk go+ where+  go (Link attr ils _) = Span attr ils+  go x = x+ -- | Set translations based on the `lang` in metadata. setupTranslations :: PandocMonad m => Meta -> m () setupTranslations meta = do@@ -636,3 +873,95 @@ isOrderedListMarker xs = not (T.null xs) && (T.last xs `elem` ['.',')']) &&               isRight (runParser (anyOrderedListMarker >> eof)                        defaultParserState "" xs)++toTaskListItem :: MonadPlus m => [Block] -> m (Bool, [Block])+toTaskListItem (Plain (Str "☐":Space:ils):xs) = pure (False, Plain ils:xs)+toTaskListItem (Plain (Str "☒":Space:ils):xs) = pure (True, Plain ils:xs)+toTaskListItem (Para  (Str "☐":Space:ils):xs) = pure (False, Para ils:xs)+toTaskListItem (Para  (Str "☒":Space:ils):xs) = pure (True, Para ils:xs)+toTaskListItem _                              = mzero++-- | Add an opener and closer to a Doc. If the Doc begins or ends+-- with whitespace, export this outside the opener or closer.+-- This is used for formats, like Markdown, which don't allow spaces+-- after opening or before closing delimiters.+delimited :: Doc Text -> Doc Text -> Doc Text -> Doc Text+delimited opener closer content =+  mconcat initialWS <> opener <> mconcat middle <> closer <> mconcat finalWS+ where+  contents = toList content+  (initialWS, rest) = span isWS contents+  (reverseFinalWS, reverseMiddle) = span isWS (reverse rest)+  finalWS = reverse reverseFinalWS+  middle = reverse reverseMiddle+  isWS NewLine = True+  isWS CarriageReturn = True+  isWS BreakingSpace = True+  isWS BlankLines{} = True+  isWS _ = False+  toList (Concat (Concat a b) c) = toList (Concat a (Concat b c))+  toList (Concat a b) = a : toList b+  toList x = [x]++-- | Determine whether all rows and their cells are empty.+allRowsEmpty :: [Row] -> Bool+allRowsEmpty = all isEmptyRow+ where+  isEmptyRow (Row _ cells) = all isEmptyCell cells+  isEmptyCell (Cell _ _ _ _ blocks) = null blocks++-- | Concatenates the header and body Rows of a List of TableBody into a flat+-- List of Rows.+tableBodiesToRows :: [TableBody] -> [Row]+tableBodiesToRows = concatMap tableBodyToRows+  where+    tableBodyToRows (TableBody _ _ headerRows bodyRows) = headerRows ++ bodyRows++-- | Insert the current span information of a table cell to keep track of it in+-- subsequent rows.+--+-- If 'RowSpan' @> 1@, the current span information will be inserted. Otherwise+-- the previous span information will be left unchanged.+--+-- Use 'takePreviousSpansAtColumn' to take previous span information at+-- subsequent rows. Use 'decrementTrailingRowSpans' to handle previous trailing+-- spans at the end of a row.+--+-- For writers that need to manually apply the 'RowSpan' of cells over multiple+-- rows or otherwise have to keep track of it.+insertCurrentSpansAtColumn :: Int -> M.Map Int (RowSpan, ColSpan) -> RowSpan -> ColSpan -> M.Map Int (RowSpan, ColSpan)+insertCurrentSpansAtColumn columnPosition previousSpans (RowSpan rowSpan) colSpan =+  if (rowSpan > 1)+    then M.insert columnPosition (RowSpan rowSpan - 1, colSpan) previousSpans -- Minus its own row.+    else previousSpans++-- | Take previous span information at a column position that was added with+-- 'insertCurrentSpansAtColumn' if available.+--+-- If the previous 'RowSpan' @>= 1@, this will return 'Just' the previous+-- 'ColSpan' and an adjusted span information where that 'RowSpan' is either+-- decremented or deleted if it would fall to 0. Otherwise this will return+-- 'Nothing'.+takePreviousSpansAtColumn :: Int -> M.Map Int (RowSpan, ColSpan) -> Maybe (ColSpan, M.Map Int (RowSpan, ColSpan))+takePreviousSpansAtColumn columnPosition previousSpans+  | Just previous@(RowSpan previousRowSpan, previousColSpan) <- M.lookup columnPosition previousSpans+  , previousRowSpan >= 1 = Just (previousColSpan, decrementPreviousRowSpans previous)+  | otherwise = Nothing+ where+  decrementPreviousRowSpans (RowSpan previousRowSpan, previousColSpan) =+    if previousRowSpan > 1+      then M.insert columnPosition (RowSpan previousRowSpan - 1, previousColSpan) previousSpans+      else M.delete columnPosition previousSpans++-- | Decrement all previously tracked trailing 'RowSpan' elements at or after a+-- column position.+--+-- For handling previous row spans that are next to the end of a row's cells+-- that were previously added with 'insertCurrentSpansAtColumn'.+decrementTrailingRowSpans :: Int -> M.Map Int (RowSpan, ColSpan) -> M.Map Int (RowSpan, ColSpan)+decrementTrailingRowSpans columnPosition = M.mapWithKey decrementTrailing+  where+    decrementTrailing previousColumnPosition previousSpan@(RowSpan rowSpan, colSpan) =+      if previousColumnPosition >= columnPosition && rowSpan >= 1+        then (RowSpan rowSpan - 1, colSpan)+        else previousSpan
src/Text/Pandoc/Writers/TEI.hs view
@@ -1,15 +1,15 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE PatternGuards     #-} {- |-   Module      : Text.Pandoc.Writers.Docbook-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Module      : Text.Pandoc.Writers.TEI+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>    Stability   : alpha    Portability : portable -Conversion of 'Pandoc' documents to Docbook XML.+Conversion of 'Pandoc' documents to TEI XML -} module Text.Pandoc.Writers.TEI (writeTEI) where import Data.Text (Text)@@ -27,7 +27,7 @@ import Text.Pandoc.Writers.Shared import Text.Pandoc.XML --- | Convert Pandoc document to string in Docbook format.+-- | Convert Pandoc document to string in TEI XML format. writeTEI :: PandocMonad m => WriterOptions -> Pandoc -> m Text writeTEI opts doc = do   let Pandoc meta blocks = ensureValidXmlIdentifiers doc@@ -138,9 +138,9 @@ blockToTEI opts (CodeBlock (_,classes,_) str) =   return $ literal ("<ab type='codeblock " <> lang <> "'>") <> cr <>      flush (literal (escapeStringForXML str) <> cr <> text "</ab>")-    where lang  = if null langs-                     then ""-                     else escapeStringForXML (head langs)+    where lang  = case langs of+                    [] -> ""+                    (l:_) -> escapeStringForXML l           syntaxMap = writerSyntaxMap opts           isLang l    = T.toLower l `elem` map T.toLower (languages syntaxMap)           langsFrom s = if isLang s
src/Text/Pandoc/Writers/Texinfo.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Writers.Texinfo-   Copyright   : Copyright (C) 2008-2023 John MacFarlane+   Copyright   : Copyright (C) 2008-2024 John MacFarlane                                2012 Peter Wang    License     : GNU GPL, version 2 or above @@ -12,21 +12,23 @@ Conversion of 'Pandoc' format into Texinfo. -} module Text.Pandoc.Writers.Texinfo ( writeTexinfo ) where-import Control.Monad (zipWithM)+import Control.Monad (zipWithM, unless) import Control.Monad.Except (throwError) import Control.Monad.State.Strict     ( StateT, MonadState(get), gets, modify, evalStateT ) import Data.Char (chr, ord, isAlphaNum)-import Data.List (maximumBy, transpose, foldl')+import Data.List (maximumBy, transpose)+import qualified Data.List as L import Data.List.NonEmpty (nonEmpty) import Data.Ord (comparing)-import qualified Data.Set as Set+import qualified Data.Map as M import Data.Text (Text) import qualified Data.Text as T import Network.URI (unEscapeString) import System.FilePath import Text.Pandoc.Class.PandocMonad (PandocMonad, report) import Text.Pandoc.Definition+import Text.Pandoc.Walk (walkM) import Text.Pandoc.Error import Text.Pandoc.ImageSize import Text.Pandoc.Logging@@ -40,11 +42,26 @@  data WriterState =   WriterState { stStrikeout   :: Bool  -- document contains strikeout-              , stEscapeComma :: Bool -- in a context where we need @comma-              , stIdentifiers :: Set.Set Text -- header ids used already+              , stContext     :: Context+              , stNodes       :: M.Map Text Int -- maps node to number of duplicates+              , stHeadings    :: M.Map Text Text -- header ids to node texts               , stOptions     :: WriterOptions -- writer options               } +data Context = NormalContext | NodeContext+  deriving (Eq, Show)++withContext :: PandocMonad m => Context -> TI m a -> TI m a+withContext context pa = do+  oldContext <- gets stContext+  modify $ \s -> s{ stContext = context }+  res <- pa+  modify $ \s -> s{ stContext = oldContext }+  pure res++disallowedInNode :: Char -> Bool+disallowedInNode c = c `elem` ['.',':',',','(',')']+ {- TODO:  - internal cross references a la HTML  - generated .texi files don't work when run through texi2dvi@@ -56,16 +73,36 @@ writeTexinfo :: PandocMonad m => WriterOptions -> Pandoc -> m Text writeTexinfo options document =   evalStateT (pandocToTexinfo options $ wrapTop document)-  WriterState { stStrikeout = False, stEscapeComma = False,-                stIdentifiers = Set.empty, stOptions = options}+  WriterState { stStrikeout = False,+                stContext = NormalContext,+                stNodes = mempty,+                stHeadings = mempty,+                stOptions = options}  -- | Add a "Top" node around the document, needed by Texinfo. wrapTop :: Pandoc -> Pandoc wrapTop (Pandoc meta blocks) =   Pandoc meta (Header 0 nullAttr (docTitle meta) : blocks) +addNodeText :: PandocMonad m => Block -> TI m Block+addNodeText (Header lev (ident,_,_) ils) | lev >= 1 && lev <= 4 = do+  node <- render Nothing <$> withContext NodeContext (inlineListToTexinfo ils)+  nodes <- gets stNodes+  node' <- case M.lookup node nodes of+                Just i -> do+                  modify $ \st -> st{ stNodes = M.adjust (+ 1) node nodes }+                  pure $ node <> " " <> tshow (i + 1)+                Nothing -> do+                  modify $ \st -> st{ stNodes = M.insert node 1 nodes }+                  pure node+  unless (T.null ident) $+    modify $ \st -> st{ stHeadings = M.insert ident node' (stHeadings st) }+  pure $ Header lev (ident,[],[("node", node')]) ils+addNodeText x = pure  x+ pandocToTexinfo :: PandocMonad m => WriterOptions -> Pandoc -> TI m Text-pandocToTexinfo options (Pandoc meta blocks) = do+pandocToTexinfo options (Pandoc meta blocks') = do+  blocks <- walkM addNodeText blocks'   let titlePage = not $ all null                       $ docTitle meta : docDate meta : docAuthors meta   let colwidth = if writerWrapText options == WrapAuto@@ -87,32 +124,44 @@        Just tpl -> renderTemplate tpl context  -- | Escape things as needed for Texinfo.-stringToTexinfo :: Text -> Text+stringToTexinfo :: PandocMonad m => Text -> TI m Text stringToTexinfo t-  | T.all isAlphaNum t = t-  | otherwise = T.concatMap escChar t-  where escChar '{'      = "@{"-        escChar '}'      = "@}"-        escChar '@'      = "@@"-        escChar '\160'   = "@ "-        escChar '\x2014' = "---"-        escChar '\x2013' = "--"-        escChar '\x2026' = "@dots{}"-        escChar '\x2019' = "'"-        escChar c        = T.singleton c--escapeCommas :: PandocMonad m => TI m (Doc Text) -> TI m (Doc Text)-escapeCommas parser = do-  oldEscapeComma <- gets stEscapeComma-  modify $ \st -> st{ stEscapeComma = True }-  res <- parser-  modify $ \st -> st{ stEscapeComma = oldEscapeComma }-  return res+  | T.all isAlphaNum t = pure t+  | otherwise = do+      context <- gets stContext+      let escChar '{'      = "@{"+          escChar '}'      = "@}"+          escChar '@'      = "@@"+          escChar '\160'   = "@ "+          escChar '\x2014' = "---"+          escChar '\x2013' = "--"+          escChar '\x2026' = "@dots{}"+          escChar '\x2019' = "'"+          escChar ',' | context == NodeContext = ""+          escChar ':' | context == NodeContext = ""+          escChar '.' | context == NodeContext = ""+          escChar '(' | context == NodeContext = ""+          escChar ')' | context == NodeContext = ""+          escChar c        = T.singleton c+      pure $ T.concatMap escChar t  -- | Puts contents into Texinfo command. inCmd :: Text -> Doc Text -> Doc Text inCmd cmd contents = char '@' <> literal cmd <> braces contents +isCodeOrBreak :: Inline -> Bool+isCodeOrBreak (Code{}) = True+isCodeOrBreak LineBreak = True+isCodeOrBreak _ = False++isCode :: Inline -> Bool+isCode (Code{}) = True+isCode _ = False++codeToStr :: Inline -> Inline+codeToStr (Code _ s) = Str s+codeToStr x = x+ -- | Convert Pandoc block element to Texinfo. blockToTexinfo :: PandocMonad m                => Block     -- ^ Block to convert@@ -123,8 +172,12 @@ blockToTexinfo (Plain lst) =   inlineListToTexinfo lst -blockToTexinfo (Para lst) =-  inlineListToTexinfo lst    -- this is handled differently from Plain in blockListToTexinfo+-- this is handled differently from Plain in blockListToTexinfo+blockToTexinfo (Para lst)+  | all isCodeOrBreak lst+      = (\xs -> "@example" $$ vcat xs $$ "@end example")+          <$> mapM (inlineToTexinfo . codeToStr) (filter isCode lst)+  | otherwise = inlineListToTexinfo lst  blockToTexinfo (LineBlock lns) =   blockToTexinfo $ linesToPara lns@@ -197,22 +250,12 @@   return $ text "@node Top" $$            text "@top " <> txt <> blankline -blockToTexinfo (Header level (ident,_,_) lst)-  | level < 1 || level > 4 = blockToTexinfo (Para lst)-  | otherwise = do-    node <- inlineListForNode lst+blockToTexinfo (Header level (_,_,[("node",node)]) lst) = do     txt <- inlineListToTexinfo lst-    idsUsed <- gets stIdentifiers-    opts <- gets stOptions-    let id' = if T.null ident-                 then uniqueIdent (writerExtensions opts) lst idsUsed-                 else ident-    modify $ \st -> st{ stIdentifiers = Set.insert id' idsUsed }     sec <- seccmd level     return $ if (level > 0) && (level <= 4)-                then blankline <> text "@node " <> node $$-                     literal sec <> txt $$-                     text "@anchor" <> braces (literal $ "#" <> id')+                then blankline <> text "@node " <> literal node $$+                     literal sec <> txt                 else txt     where       seccmd :: PandocMonad m => Int -> TI m Text@@ -222,6 +265,9 @@       seccmd 4 = return "@subsubsection "       seccmd _ = throwError $ PandocSomeError "illegal seccmd level" +-- non-node header:+blockToTexinfo (Header _ _ lst) = blockToTexinfo (Para lst)+ blockToTexinfo (Table _ blkCapt specs thead tbody tfoot) = do   let (caption, aligns, widths, heads, rows) = toLegacyTable blkCapt specs thead tbody tfoot   headers <- if all null heads@@ -302,7 +348,7 @@                      -> [[Block]]                      -> TI m (Doc Text) tableAnyRowToTexinfo itemtype aligns cols =-  (literal itemtype $$) . foldl' (\row item -> row $$+  (literal itemtype $$) . L.foldl' (\row item -> row $$   (if isEmpty row then empty else text " @tab ") <> item) empty <$> zipWithM alignedBlock aligns cols  alignedBlock :: PandocMonad m@@ -359,19 +405,23 @@ collectNodes _ [] = [] collectNodes level (x:xs) =   case x of-    (Header hl _ _) | hl < level -> []-                    | hl == level -> x : collectNodes level xs-                    | otherwise -> collectNodes level xs+    (Header hl _ _)+      | hl < level -> []+      | hl == level -> x : collectNodes level xs+      | otherwise -> collectNodes level xs     _ ->       collectNodes level xs  makeMenuLine :: PandocMonad m              => Block              -> TI m (Doc Text)-makeMenuLine (Header _ _ lst) = do-  txt <- inlineListForNode lst-  return $ text "* " <> txt <> text "::"-makeMenuLine _ = throwError $ PandocSomeError "makeMenuLine called with non-Header block"+makeMenuLine (Header _ (_,_,[("node", node)]) lst) = do+  txt <- withContext NodeContext $ inlineListToTexinfo lst+  pure $ nowrap $ text "* " <>+    if render Nothing txt == node+       then literal node <> "::"+       else txt <> ": " <> literal node <> "."+makeMenuLine _ = throwError $ PandocSomeError "makeMenuLine called with non-node"  listItemToTexinfo :: PandocMonad m                   => [Block]@@ -401,17 +451,6 @@                     -> TI m (Doc Text) inlineListToTexinfo lst = hcat <$> mapM inlineToTexinfo lst --- | Convert list of inline elements to Texinfo acceptable for a node name.-inlineListForNode :: PandocMonad m-                  => [Inline]  -- ^ Inlines to convert-                  -> TI m (Doc Text)-inlineListForNode = return . literal . stringToTexinfo .-                    T.filter (not . disallowedInNode) . stringify---- periods, commas, colons, and parentheses are disallowed in node names-disallowedInNode :: Char -> Bool-disallowedInNode c = c `elem` (".,:()" :: String)- -- | Convert inline element to Texinfo inlineToTexinfo :: PandocMonad m                 => Inline    -- ^ Inline to convert@@ -446,11 +485,13 @@ inlineToTexinfo (SmallCaps lst) =   inCmd "sc" <$> inlineListToTexinfo lst -inlineToTexinfo (Code (_, cls , _) str) | T.pack "variable" `elem` cls  =-  return $ literal $ "@code{@var{" <> stringToTexinfo str <> "}}"+inlineToTexinfo (Code (_, cls , _) str) | T.pack "variable" `elem` cls  = do+  code <- stringToTexinfo str+  return $ literal $ "@code{@var{" <> code <> "}}" -inlineToTexinfo (Code _ str) =-  return $ literal $ "@code{" <> stringToTexinfo str <> "}"+inlineToTexinfo (Code _ str) = do+  code <- stringToTexinfo str+  return $ literal $ "@code{" <> code <> "}"  inlineToTexinfo (Quoted SingleQuote lst) = do   contents <- inlineListToTexinfo lst@@ -462,7 +503,7 @@  inlineToTexinfo (Cite _ lst) =   inlineListToTexinfo lst-inlineToTexinfo (Str str) = return $ literal (stringToTexinfo str)+inlineToTexinfo (Str str) = literal <$> stringToTexinfo str inlineToTexinfo (Math _ str) = return $ inCmd "math" $ literal str inlineToTexinfo il@(RawInline f str)   | f == "latex" || f == "tex" =@@ -481,21 +522,28 @@ inlineToTexinfo Space = return space  inlineToTexinfo (Link _ txt (src, _))-  | Just ('#', _) <- T.uncons src = do-      contents <- escapeCommas $ inlineListToTexinfo txt-      return $ text "@ref" <>-        braces (literal (stringToTexinfo src) <> text "," <> contents)+  | Just ('#', ident) <- T.uncons src = do+      headings <- gets stHeadings+      target <- case M.lookup ident headings of+                  Nothing -> literal <$> stringToTexinfo+                                    (T.filter (not . disallowedInNode) src)+                  Just node -> pure $ literal node+      contents <- withContext NodeContext $ inlineListToTexinfo txt+      return $ text "@ref"+        <> braces (target <> if contents == target+                                then mempty+                                else text ",," <> contents)   | otherwise = case txt of       [Str x] | escapeURI x == src ->  -- autolink                   return $ literal $ "@url{" <> x <> "}"       _ -> do-        contents <- escapeCommas $ inlineListToTexinfo txt-        let src1 = stringToTexinfo src+        contents <- withContext NodeContext $ inlineListToTexinfo txt+        src1 <- stringToTexinfo src         return $ literal ("@uref{" <> src1 <> ",") <> contents <>                  char '}'  inlineToTexinfo (Image attr alternate (source, _)) = do-  content <- escapeCommas $ inlineListToTexinfo alternate+  content <- withContext NodeContext $ inlineListToTexinfo alternate   opts <- gets stOptions   let showDim dim = case dimension dim attr of                       (Just (Pixel a))   -> showInInch opts (Pixel a) <> "in"
src/Text/Pandoc/Writers/Textile.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Writers.Textile-   Copyright   : Copyright (C) 2010-2023 John MacFarlane+   Copyright   : Copyright (C) 2010-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -337,14 +337,10 @@                   -> TW m Text tableRowToTextile opts alignStrings rownum cols' = do   let celltype = if rownum == 0 then "th" else "td"-  let rowclass = case rownum of-                      0 -> "header"-                      x | x `rem` 2 == 1 -> "odd"-                      _ -> "even"   cols'' <- zipWithM             (\alignment item -> tableItemToTextile opts celltype alignment item)             alignStrings cols'-  return $ "<tr class=\"" <> rowclass <> "\">\n" <> T.unlines cols'' <> "</tr>"+  return $ "<tr>\n" <> T.unlines cols'' <> "</tr>"  alignmentToText :: Alignment -> Text alignmentToText alignment = case alignment of
src/Text/Pandoc/Writers/Typst.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE OverloadedStrings   #-} {-# LANGUAGE BangPatterns        #-}+{-# LANGUAGE LambdaCase          #-} {-# LANGUAGE ScopedTypeVariables #-} {- |    Module      : Text.Pandoc.Writers.Typst@@ -17,32 +18,48 @@     writeTypst   ) where import Text.Pandoc.Definition-import Text.Pandoc.Class ( PandocMonad)-import Text.Pandoc.Options ( WriterOptions(..), WrapOption(..), isEnabled )+import Text.Pandoc.Class ( PandocMonad, report, runPure, fetchItem )+import Text.Pandoc.ImageSize ( dimension, Dimension(Pixel), Direction(..),+                               showInInch )+import Text.Pandoc.Options ( WriterOptions(..), WrapOption(..), isEnabled,+                             CaptionPosition(..), HighlightMethod(..) ) import Data.Text (Text) import Data.List (intercalate, intersperse)+import Data.Bifunctor (first, second) import Network.URI (unEscapeString) import qualified Data.Text as T+import Control.Monad (unless) import Control.Monad.State ( StateT, evalStateT, gets, modify )-import Text.Pandoc.Writers.Shared ( metaToContext, defField, resetField,-                                    lookupMetaString,-                                    isOrderedListMarker )-import Text.Pandoc.Shared (isTightList, orderedListMarkers, tshow)+import Text.Pandoc.Writers.Shared ( lookupMetaInlines, lookupMetaString,+                                    metaToContext, defField, resetField,+                                    setupTranslations )+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 import Text.DocLayout 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 (isAlphaNum)+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 writeTypst options document =   evalStateT (pandocToTypst options document)     WriterState{ stOptions = options,-                 stEscapeContext = NormalContext }+                 stEscapeContext = NormalContext,+                 stHighlighting = False }  data EscapeContext = NormalContext | TermContext   deriving (Show, Eq)@@ -50,7 +67,9 @@ data WriterState =   WriterState {     stOptions :: WriterOptions,-    stEscapeContext :: EscapeContext }+    stEscapeContext :: EscapeContext,+    stHighlighting :: Bool+    }  type TW m = StateT WriterState m @@ -60,15 +79,28 @@   let colwidth = if writerWrapText options == WrapAuto                     then Just $ writerColumns options                     else Nothing+  setupTranslations meta   metadata <- metaToContext options               blocksToTypst               (fmap chomp . inlinesToTypst)               meta   main <- blocksToTypst blocks+  abstractTitle <- translateTerm Abstract+  let toPosition :: CaptionPosition -> Text+      toPosition CaptionAbove = "top"+      toPosition CaptionBelow = "bottom"+  let nociteIds = query (\case+                           Cite cs _ -> map citationId cs+                           _         -> [])+                  $ lookupMetaInlines "nocite" meta+  hasHighlighting <- gets stHighlighting+   let context = defField "body" main               $ defField "toc" (writerTableOfContents options)               $ (if isEnabled Ext_citations options                     then defField "citations" True+                       . defField "nocite-ids" (filter (/= "*") nociteIds)+                       . defField "full-bibliography" ("*" `elem` nociteIds)                     else id)               $ (case lookupMetaString "lang" meta of                     "" -> id@@ -78,16 +110,70 @@                         Right l ->                           resetField "lang" (langLanguage l) .                           maybe id (resetField "region") (langRegion l))+              $ defField "csl" (lookupMetaString "citation-style" meta) -- #10661+              $ defField "smart" (isEnabled Ext_smart options)+              $ defField "abstract-title" abstractTitle               $ defField "toc-depth" (tshow $ writerTOCDepth options)+              $ (if hasHighlighting+                    then case writerHighlightMethod options of+                           Skylighting sty ->+                              defField "highlighting-definitions"+                                (T.stripEnd $ styleToTypst sty)+                           _ -> id+                    else id)+              $ defField "figure-caption-position"+                   (toPosition $ writerFigureCaptionPosition options)+              $ defField "table-caption-position"+                   (toPosition $ writerTableCaptionPosition options)+              $ defField "page-numbering" ("1" :: Text)               $ (if writerNumberSections options-                    then defField "numbering" ("1.1.1.1.1" :: Text)+                    then defField "section-numbering" ("1.1.1.1.1" :: Text)                     else id)-              $ metadata+              metadata   return $ render colwidth $     case writerTemplate options of        Nothing  -> main        Just tpl -> renderTemplate tpl context +pickTypstAttrs :: [(Text, Text)] -> ([(Text, Text)],[(Text, Text)])+pickTypstAttrs = foldr go ([],[])+  where+    go (k,v) =+      case T.splitOn ":" k of+        ["typst", "text", x] -> second ((x,v):)+        ["typst", x] -> first ((x,v):)+        _ -> id++formatTypstProp :: (Text, Text) -> Text+formatTypstProp (k,v) = k <> ": " <> v++toTypstPropsListSep :: [(Text, Text)] -> Doc Text+toTypstPropsListSep = hsep . intersperse "," . map (literal . formatTypstProp)++toTypstPropsListTerm :: [(Text, Text)] -> Doc Text+toTypstPropsListTerm [] = ""+toTypstPropsListTerm typstAttrs = toTypstPropsListSep typstAttrs <> ","++toTypstPropsListParens :: [(Text, Text)] -> Doc Text+toTypstPropsListParens [] = ""+toTypstPropsListParens typstAttrs = parens $ toTypstPropsListSep typstAttrs++toTypstTextElement :: [(Text, Text)] -> Doc Text -> Doc Text+toTypstTextElement [] content = content+toTypstTextElement typstTextAttrs content = "#text" <> toTypstPropsListParens typstTextAttrs <> brackets content++toTypstSetText :: [(Text, Text)] -> Doc Text+toTypstSetText [] = ""+toTypstSetText typstTextAttrs = "set text" <> parens (toTypstPropsListSep typstTextAttrs) <> ";"++toTypstPoundSetText :: [(Text, Text)] -> Doc Text+toTypstPoundSetText [] = mempty+toTypstPoundSetText typstTextAttrs = "#" <> toTypstSetText typstTextAttrs++toTypstBracesSetText :: [(Text, Text)] -> Doc Text -> Doc Text+toTypstBracesSetText [] x = "#" <> x+toTypstBracesSetText typstTextAttrs x = "#" <> braces (toTypstSetText typstTextAttrs <> x)+ blocksToTypst :: PandocMonad m => [Block] -> TW m (Doc Text) blocksToTypst blocks = vcat <$> mapM blockToTypst blocks @@ -95,7 +181,8 @@ blockToTypst block =   case block of     Plain inlines -> inlinesToTypst inlines-    Para inlines -> ($$ blankline) <$> inlinesToTypst inlines+    Para inlines -> do+      ($$ blankline) <$> inlinesToTypst inlines     Header level (ident,cls,_) inlines -> do       contents <- inlinesToTypst inlines       let lab = toLabel FreestandingLabel ident@@ -115,7 +202,7 @@       case fmt of         Format "typst" -> return $ literal str         _ -> return mempty-    CodeBlock (_,cls,_) code -> do+    CodeBlock (ident,cls,kvs) code -> do       let go :: Char -> (Int, Int) -> (Int, Int)           go '`' (longest, current) =             let !new = current + 1 in (max longest new, new)@@ -125,7 +212,19 @@       let lang = case cls of                    (cl:_) -> literal cl                    _ -> mempty-      return $ fence <> lang <> cr <> literal code <> cr <> fence <> blankline+      opts <-  gets stOptions+      case writerHighlightMethod opts of+        Skylighting _ ->+          case highlight (writerSyntaxMap opts) formatTypstBlock+                (ident,cls ++ ["default"],kvs) code of+            Left msg -> do+              unless (T.null msg) $ report $ CouldNotHighlight msg+              return $ fence <> lang <> cr <> literal code <> cr <> fence <> blankline+            Right h -> do+              modify (\s -> s{ stHighlighting = True })+              return (literal h)+        NoHighlighting -> return $ fence <> cr <> literal code <> cr <> fence <> blankline+        _ -> return $ fence <> lang <> cr <> literal code <> cr <> fence <> blankline     LineBlock lns -> do       contents <- inlinesToTypst (intercalate [LineBreak] lns)       return $ contents <> blankline@@ -144,8 +243,9 @@                                   parens (                                     "numbering: " <>                                     doubleQuoted-                                      (head (orderedListMarkers-                                             (1, sty, delim))) <>+                                     (case orderedListMarkers (1, sty, delim) of+                                          (m:_) -> m+                                          [] -> "1.") <>                                     ", start: " <>                                       text (show start) )) $$                                x $$@@ -163,13 +263,14 @@                    else vsep items') $$ blankline     DefinitionList items ->       ($$ blankline) . vsep <$> mapM defListItemToTypst items-    Table (ident,_,_) (Caption _ caption) colspecs thead tbodies tfoot -> do+    Table (ident,tabclasses,tabkvs) (Caption _ caption) colspecs thead tbodies tfoot -> do       let lab = toLabel FreestandingLabel ident       capt' <- if null caption                   then return mempty                   else do                     captcontents <- blocksToTypst caption                     return $ ", caption: " <> brackets captcontents+      let typstFigureKind = literal (", kind: " <> fromMaybe "table" (lookup "typst:figure:kind" tabkvs))       let numcols = length colspecs       let (aligns, widths) = unzip colspecs       let commaSep = hcat . intersperse ", "@@ -185,26 +286,40 @@           formatalign AlignCenter = "center,"           formatalign AlignDefault = "auto,"       let alignarray = parens $ mconcat $ map formatalign aligns-      let fromCell (Cell _attr alignment rowspan colspan bs) = do-            let cellattrs =++      let fromCell (Cell (_,_,kvs) alignment rowspan colspan bs) = do+            let (typstAttrs, typstTextAttrs) = pickTypstAttrs kvs+            let valign =+                  (case lookup "align" typstAttrs of+                    Just va -> [va]+                    _ -> [])+            let typstAttrs2 = filter ((/="align") . fst) typstAttrs+            let halign =                   (case alignment of-                     AlignDefault -> []-                     AlignLeft -> [ "align: left" ]-                     AlignRight -> [ "align: right" ]-                     AlignCenter -> [ "align: center" ]) +++                    AlignDefault -> []+                    AlignLeft -> [ "left" ]+                    AlignRight -> [ "right" ]+                    AlignCenter -> [ "center" ])+            let cellaligns = valign ++ halign+            let cellattrs =+                  (case cellaligns of+                    [] -> []+                    _ -> [ "align: " <> T.intercalate " + " cellaligns ]) ++                   (case rowspan of                      RowSpan 1 -> []                      RowSpan n -> [ "rowspan: " <> tshow n ]) ++                   (case colspan of                      ColSpan 1 -> []-                     ColSpan n -> [ "colspan: " <> tshow n ])+                     ColSpan n -> [ "colspan: " <> tshow n ]) +++                  map formatTypstProp typstAttrs2             cellContents <- blocksToTypst bs+            let contents2 = brackets (toTypstPoundSetText typstTextAttrs $$ cellContents)             pure $ if null cellattrs-                      then brackets cellContents+                      then contents2                       else "table.cell" <>                             parens                              (literal (T.intercalate ", " cellattrs)) <>-                            brackets cellContents+                            contents2       let fromRow (Row _ cs) =             (<> ",") . commaSep <$> mapM fromCell cs       let fromHead (TableHead _attr headRows) =@@ -223,35 +338,41 @@             hrows <- mapM fromRow headRows             brows <- mapM fromRow bodyRows             pure $ vcat (hrows ++ ["table.hline()," | not (null hrows)] ++ brows)+      let (typstAttrs, typstTextAttrs) = pickTypstAttrs tabkvs       header <- fromHead thead       footer <- fromFoot tfoot       body <- vcat <$> mapM fromTableBody tbodies-      return $-        "#figure("-        $$-        nest 2-         ("align(center)[#table("-          $$ nest 2-             (  "columns: " <> columns <> ","-             $$ "align: " <> alignarray <> ","-             $$ header-             $$ body-             $$ footer-             )-          $$ ")]"-          $$ capt'-          $$ ", kind: table"-          $$ ")")-        $$ lab-        $$ blankline+      let table = "table("+            $$ nest 2+                (  "columns: " <> columns <> ","+                $$ "align: " <> alignarray <> ","+                $$ toTypstPropsListTerm typstAttrs+                $$ header+                $$ body+                $$ footer+            )+            $$ ")"+      return $ if "typst:no-figure" `elem` tabclasses+        then toTypstBracesSetText typstTextAttrs table+        else "#figure("+            $$+            nest 2+            ("align(center)[" <> toTypstPoundSetText typstTextAttrs <> "#" <> table <> "]"+              $$ capt'+              $$ typstFigureKind+              $$ ")")+            $$ lab+          $$ blankline     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 (_,_,kvs) _ (src, _)]]-                       -> pure $ mkImage False src kvs-                     [Plain [Image (_,_,kvs) _ (src, _)]]-                       -> pure $ mkImage False src kvs+                     [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 <> ",")@@ -261,10 +382,22 @@                           $$ ")" $$ lab $$ blankline     Div (ident,_,_) (Header lev ("",cls,kvs) ils:rest) ->       blocksToTypst (Header lev (ident,cls,kvs) ils:rest)-    Div (ident,_,_) blocks -> do+    Div (ident,_,kvs) blocks -> do       let lab = toLabel FreestandingLabel ident+      let (typstAttrs,typstTextAttrs) = pickTypstAttrs kvs+      -- Handle lang attribute for Div elements+      let langAttrs = case lookup "lang" kvs of+                        Nothing -> []+                        Just lang -> case parseLang lang of+                                       Left _ -> []+                                       Right l -> [("lang",+                                                    tshow (langLanguage l))]+      let allTypstTextAttrs = typstTextAttrs ++ langAttrs       contents <- blocksToTypst blocks-      return $ "#block[" $$ contents $$ ("]" <+> lab)+      return $ "#block" <> toTypstPropsListParens typstAttrs <> "["+        $$ toTypstPoundSetText allTypstTextAttrs+        $$ contents+        $$ ("]" <+> lab)  defListItemToTypst :: PandocMonad m => ([Inline], [[Block]]) -> TW m (Doc Text) defListItemToTypst (term, defns) = do@@ -273,7 +406,7 @@   modify $ \st -> st{ stEscapeContext = NormalContext }   defns' <- mapM blocksToTypst defns   return $ nowrap ("/ " <> term' <> ": " <> "#block[") $$-            chomp (vcat defns') $$ "]"+            chomp (vsep defns') $$ "]"  listItemToTypst :: PandocMonad m => Int -> Doc Text -> [Block] -> TW m (Doc Text) listItemToTypst ind marker blocks = do@@ -281,14 +414,37 @@   return $ hang ind (marker <> space) contents  inlinesToTypst :: PandocMonad m => [Inline] -> TW m (Doc Text)-inlinesToTypst ils = hcat <$> mapM inlineToTypst ils+inlinesToTypst (i@(Span (ident,_,_) _):is) | not (T.null ident) =+  -- insert a zero-width space U+200B before the label+  -- because a typst label refers to preceding element (see #11568)+  ("\x200B" <>) . hcat <$> mapM inlineToTypst (escapeParens (i:is))+inlinesToTypst ils = hcat <$> mapM inlineToTypst (escapeParens ils) +-- Add an escape before a parenthesis right after a non-space element.+-- Otherwise we risk `#emph[test](3)` which will error. See #11210.+escapeParens :: [Inline] -> [Inline]+escapeParens [] = []+escapeParens (s : x : xs)+  | isSpacey s+    = s : x : escapeParens xs+escapeParens (Str t : xs)+  | Just ('(',_) <- T.uncons t+    = RawInline (Format "typst") "\\" : Str t : escapeParens xs+escapeParens (x : xs) = x : escapeParens xs++isSpacey :: Inline -> Bool+isSpacey Space = True+isSpacey SoftBreak = True+isSpacey LineBreak = True+isSpacey _ = False+ inlineToTypst :: PandocMonad m => Inline -> TW m (Doc Text) inlineToTypst inline =   case inline of     Str txt -> do+      opts <-  gets stOptions       context <- gets stEscapeContext-      return $ escapeTypst context txt+      return $ escapeTypst (isEnabled Ext_smart opts) context txt     Space -> return space     SoftBreak -> do       wrapText <- gets $ writerWrapText . stOptions@@ -296,22 +452,38 @@         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           Left il -> inlineToTypst il           Right r ->-            case mathType of-              InlineMath -> return $ "$" <> literal r <> "$"-              DisplayMath -> return $ "$ " <> literal r <> " $"-    Code (_,cls,_) code -> return $-      case cls of-        (lang:_) -> "#raw(lang:" <> doubleQuoted lang <>-                        ", " <> doubleQuoted code <> ")" <> endCode-        _ | T.any (=='`') code -> "#raw(" <> doubleQuoted code <> ")"-                                     <> endCode-          | otherwise -> "`" <> literal code <> "`"+            (case extractLabel str of -- #10805+              Nothing -> id+              Just lab -> (<> (toLabel FreestandingLabel lab))) <$>+             case mathType of+               InlineMath -> return $ "$" <> literal r <> "$"+               DisplayMath -> return $ "$ " <> literal r <> " $"+    Code (ident,cls,kvs) code -> do+      opts <- gets stOptions+      let defaultHighlightedCode =+            case cls of+              (lang:_) | writerHighlightMethod opts /= NoHighlighting+                       -> "#raw(lang:" <> doubleQuoted lang <>+                              ", " <> doubleQuoted code <> ")"+              _ | T.any (=='`') code -> "#raw(" <> doubleQuoted code <> ")"+                | otherwise -> "`" <> literal code <> "`"+      case writerHighlightMethod opts of+        Skylighting _ ->+          case highlight (writerSyntaxMap opts) formatTypstInline+                (ident,cls ++ ["default"],kvs) code of+            Left msg -> do+              unless (T.null msg) $ report $ CouldNotHighlight msg+              return defaultHighlightedCode+            Right h -> do+              modify (\s -> s{ stHighlighting = True })+              return (literal h)+        _ -> return defaultHighlightedCode     RawInline fmt str ->       case fmt of         Format "typst" -> return $ literal str@@ -323,15 +495,27 @@     Superscript inlines -> textstyle "#super" inlines     Subscript inlines -> textstyle "#sub" inlines     SmallCaps inlines -> textstyle "#smallcaps" inlines-    Span (ident,_,_) inlines -> do+    Span (ident,cls,kvs) inlines -> do       let lab = toLabel FreestandingLabel ident-      (<> lab) <$> inlinesToTypst inlines+      let (_, typstTextAttrs) = pickTypstAttrs kvs+      contents <- inlinesToTypst inlines+      let addHl x = "#highlight" <> brackets x+      return $ (if "mark" `elem` cls+                   then addHl+                   else id)+               (toTypstTextElement typstTextAttrs contents) <> lab     Quoted quoteType inlines -> do-      let q = case quoteType of-                   DoubleQuote -> literal "\""-                   SingleQuote -> literal "'"+      opts <- gets stOptions+      let smart = isEnabled Ext_smart opts       contents <- inlinesToTypst inlines-      return $ q <> contents <> q+      return $+        case quoteType of+           DoubleQuote+             | smart -> "\"" <> contents <> "\""+             | otherwise -> "“" <> contents <> "”"+           SingleQuote+             | smart -> "'" <> contents <> "'"+             | otherwise -> "‘" <> contents <> "’"     Cite citations inlines -> do       opts <-  gets stOptions       if isEnabled Ext_citations opts@@ -345,7 +529,6 @@           -> if T.all isIdentChar ident                 then pure $ literal $ "@" <> ident                 else pure $ "#ref" <> parens (toLabel ArgumentLabel ident)-                            <> endCode         _ -> do           contents <- inlinesToTypst inlines           let dest = case T.uncons src of@@ -354,55 +537,112 @@           pure $ "#link" <> parens dest <>                     (if inlines == [Str src]                           then mempty-                          else nowrap $ brackets contents) <> endCode-    Image (_,_,kvs) _inlines (src,_tit) -> pure $ mkImage True src kvs+                          else nowrap $ brackets contents)+    Image attr inlines (src,_tit) -> do+      opts <-  gets stOptions+      pure $ mkImage opts True src attr (getAlt attr inlines)     Note blocks -> do       contents <- blocksToTypst blocks-      return $ "#footnote" <> brackets (chomp contents) <> endCode+      return $ "#footnote" <> brackets (chomp contents)  -- see #9104; need box or image is treated as block-level-mkImage :: Bool -> Text -> [(Text, Text)] -> Doc Text-mkImage useBox src kvs+mkImage :: WriterOptions -> Bool -> Text -> Attr -> Maybe Text -> Doc Text+mkImage opts useBox src attr mbAlt   | useBox = "#box" <> parens coreImage   | otherwise = coreImage  where   src' = T.pack $ unEscapeString $ T.unpack src -- #9389-  toDimAttr k =-     case lookup k kvs of-       Just v -> ", " <> literal k <> ": " <> literal v-       Nothing -> mempty-  dimAttrs = mconcat $ map toDimAttr ["height", "width"]-  coreImage = "image" <> parens (doubleQuoted src' <> dimAttrs)+  showDim (Pixel a) = literal (showInInch opts (Pixel a) <> "in")+  showDim dim = text (show dim)+  dimAttrs =+     (case dimension Height attr of+        Nothing -> mempty+        Just dim -> ", height: " <> showDim dim) <>+     (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'+  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 =-  (<> endCode) . (s <>) . brackets . addEscape <$> inlinesToTypst inlines- where-   addEscape =-     case inlines of-       (Str t : _)-         | isOrderedListMarker t -> ("\\" <>)-         | Just (c, _) <- T.uncons t-         , needsEscapeAtLineStart c -> ("\\" <>)-       _ -> id+textstyle s inlines = do+  (s <>) . brackets . fixInitialAfterBreakEscape+    <$> inlinesToTypst inlines -escapeTypst :: EscapeContext -> Text -> Doc Text-escapeTypst context t =+fixInitialAfterBreakEscape :: Doc Text -> Doc Text+fixInitialAfterBreakEscape (Concat x y) =+  Concat (fixInitialAfterBreakEscape x) y+-- make an initial AfterBreak escape unconditional (it will be rendered+-- in a block [..] and there won't be an actual break to trigger it, but+-- typst still needs the escape)+fixInitialAfterBreakEscape (AfterBreak "\\") = Text 1 "\\"+fixInitialAfterBreakEscape x = x++isOrderedListMarker :: Text -> Bool+isOrderedListMarker t = not (T.null ds) && rest == "."+  where (ds, rest) = T.span isDigit t++escapeTypst :: Bool -> EscapeContext -> Text -> Doc Text+escapeTypst smart context t =   (case T.uncons t of-    Just (c, _)-      | needsEscapeAtLineStart c+    Just (c, rest)+      | c == ';' -> char '\\' -- see #9252+      | c == '.'+      , not (T.null rest) -> char '\\' -- see #11511+      | needsEscapeAtLineStart c || isOrderedListMarker t         -> afterBreak "\\"     _ -> mempty) <>-  (literal (T.replace "//" "\\/\\/"-    (if T.any needsEscape t-        then T.concatMap escapeChar t-        else t)))+   literal (snd $ T.foldl' go ('\n', mempty) t)   where+    go (lastc, t') c+      | needsEscape c = (c, t' <> escapeChar c)+      | c == '-', lastc == '-', smart = (c, t' <> T.pack ['\\',c])+      | c == '/', lastc == '/' = (c, t' <> T.pack ['\\',c])+      | 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+    needsEscape '"' = smart     needsEscape '[' = True     needsEscape ']' = True     needsEscape '#' = True@@ -411,8 +651,6 @@     needsEscape '@' = True     needsEscape '$' = True     needsEscape '\\' = True-    needsEscape '\'' = True-    needsEscape '"' = True     needsEscape '`' = True     needsEscape '_' = True     needsEscape '*' = True@@ -445,7 +683,7 @@    ident' = T.pack $ unEscapeString $ T.unpack ident  isIdentChar :: Char -> Bool-isIdentChar c = isAlphaNum c || c == '_' || c == '-' || c == '.' || c == ':'+isIdentChar c = isXIDContinue c || c == '_' || c == '-' || c == '.' || c == ':'  toCite :: PandocMonad m => Citation -> TW m (Doc Text) toCite cite = do@@ -457,8 +695,7 @@      then do        suppl <- case citationSuffix cite of                   [] -> pure mempty-                  suff -> (<> endCode) . brackets-                            <$> inlinesToTypst (eatComma suff)+                  suff -> brackets <$> inlinesToTypst (eatComma suff)        pure $ "@" <> literal ident' <> suppl      else do        let label = if T.all isIdentChar ident'@@ -472,7 +709,10 @@                   [] -> pure mempty                   suff -> (", supplement: " <>) . brackets                              <$> inlinesToTypst (eatComma suff)-       pure $ "#cite" <> parens (label <> form <> suppl) <> endCode+       pure $ (if citationMode cite == SuppressAuthor  -- see #11044+                  then parens+                  else id)+            $ "#cite" <> parens (label <> form <> suppl)  doubleQuoted :: Text -> Doc Text doubleQuoted = doubleQuotes . literal . escape@@ -482,5 +722,9 @@   escapeChar '"' = "\\\""   escapeChar c = T.singleton c -endCode :: Doc Text-endCode = beforeNonBlank ";"+extractLabel :: Text -> Maybe Text+extractLabel = go . T.unpack+ where+   go [] = Nothing+   go ('\\':'l':'a':'b':'e':'l':'{':xs) = Just (T.pack (takeWhile (/='}') xs))+   go (_:xs) = go xs
+ src/Text/Pandoc/Writers/Vimdoc.hs view
@@ -0,0 +1,615 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MultiWayIf #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE Strict #-}++module Text.Pandoc.Writers.Vimdoc (writeVimdoc) where++import Control.Applicative (optional, (<|>))+import Control.Monad (forM)+import Control.Monad.Reader (MonadReader (..), ReaderT (..), asks)+import Control.Monad.State (MonadState (..), StateT, evalStateT, gets, modify)+import Data.Default (Default (..))+import Data.List (intercalate, intersperse, transpose)+import Data.List.NonEmpty (NonEmpty (..), nonEmpty)+import Data.Maybe (fromMaybe)+import Data.Text (Text)+import qualified Data.Text as T+import Text.DocLayout hiding (char, link, text)+import Text.Pandoc.Class.PandocMonad ( report, PandocMonad )+import Text.Pandoc.Definition+import Text.Pandoc.Error (PandocError)+import Text.Pandoc.Logging (LogMessage (..))+import Text.Pandoc.Options (WrapOption (..), WriterOptions (..))+import Text.Pandoc.Parsing.General (many1Till, many1TillChar, readWith)+import Text.Pandoc.Shared (capitalize, onlySimpleTableCells, orderedListMarkers, isTightList, makeSections, removeFormatting, tshow)+import Text.Pandoc.Templates (renderTemplate)+import Text.Pandoc.URI (escapeURI, isURI)+import Text.Pandoc.Writers.Shared (defField, metaToContext, toLegacyTable)+import Text.Parsec (anyChar, char, eof, string, try)+import Text.Read (readMaybe)+import Text.Pandoc.Chunks (toTOCTree, SecInfo (..))+import Data.Tree (Tree(..))+import Data.Functor ((<&>))+import Data.Sequence (Seq, (|>), (<|))+import qualified Data.Sequence as Seq+import Data.Foldable (toList)++data WriterState = WriterState+  { indentLevel :: Int -- How much to indent the block. Inlines shouldn't+                       -- be concerned with indent level (I guess?)+  , shiftWidth :: Int -- spaces per indentation level+  , writerOptions :: WriterOptions+  , vimdocPrefix :: Maybe Text+  }++instance Default WriterState where+  def =+    WriterState+      { indentLevel = 0+      , shiftWidth = 4+      , writerOptions = def+      , vimdocPrefix = Nothing+      }++indent :: (Monad m) => Int -> (VW m a) -> (VW m a)+indent n = local (\s -> s{indentLevel = indentLevel s + n})++type VW m = StateT (Seq (Doc Text)) (ReaderT WriterState m)++runRR :: (Monad m) => Seq (Doc Text) -> WriterState -> VW m a -> m a+runRR footnotes opts action = runReaderT (evalStateT action footnotes) opts++docShiftWidth :: Meta -> Maybe Int+docShiftWidth meta = case lookupMeta "shiftwidth" meta of+  Just (MetaInlines [Str sw]) -> readMaybe (T.unpack sw)+  Just (MetaString sw) -> readMaybe (T.unpack sw)+  _ -> Nothing++docVimdocPrefix :: Meta -> Maybe Text+docVimdocPrefix meta = case lookupMeta "vimdoc-prefix" meta of+  Just (MetaInlines [Str pref]) -> Just pref+  Just (MetaString pref) -> Just pref+  _ -> Nothing++{- | Build a vim modeline+>>> makeModeLine def+"vim:tw=72:sw=4:ts=4:ft=help:norl:et:"+-}+makeModeLine :: WriterState -> Text+makeModeLine ws =+  T.pack . intercalate ":" $+    [ "vim"+    , "tw=" <> show tw+    , "sw=" <> show sw+    , "ts=" <> show sw+    , "ft=help"+    , "norl" -- left-to-right text+    , "et:" -- expandtab and finishing ":"+    ]+ where+  tw = writerColumns . writerOptions $ ws+  sw = shiftWidth ws++-- | Build a single formatted TOC line+tocEntryToLine :: (PandocMonad m) => SecInfo -> VW m Text+tocEntryToLine secinfo = do+  rightRef <- mkVimdocRef (secId secinfo)+  let numberStr = case secNumber secinfo of+        Nothing -> ""+        Just x | '.' `T.elem` x -> x <> " "+        Just x -> x <> ". "+  title <- inlineListToVimdoc $ removeFormatting (secTitle secinfo)+  let titlePlain = render Nothing (title <> " ")++  -- length sub 2 because vertical bars are concealed+  let rightRefLen = max 0 (T.length rightRef - 2)+  let numberLen = T.length numberStr+  let leftLen = numberLen + T.length titlePlain+  let padForRight = 1+  textWidth <- asks (writerColumns . writerOptions)+  il <- asks indentLevel++  -- positive when we lack space (i.e. content is too long)+  let lack = (il + leftLen + padForRight + rightRefLen) - textWidth++  -- when lacking, truncate title reserving 3+ chars for ellipsis+  let finalTitle =+        if lack >= 0+          then+            let trunc = T.dropEnd (lack + 3) titlePlain+                stripped = T.stripEnd trunc+                ellipsis =+                  T.replicate (3 + T.length trunc - T.length stripped) "."+             in stripped <> ellipsis+          else titlePlain++  -- Negative lack means we have an excess of space, so we fill it with dots+  let dots = T.replicate (negate lack) "."++  pure . T.concat $ [numberStr, finalTitle, dots, " ", rightRef]++vimdocTOC :: (PandocMonad m) => WriterState -> [Block] -> VW m (Doc Text)+vimdocTOC (WriterState{writerOptions = opts}) blocks = do+  let (Node _ subtrees) =+        toTOCTree $ makeSections (writerNumberSections opts) Nothing blocks+  let tocDepth = writerTOCDepth opts+  let isBelowTocDepth (Node sec _) = secLevel sec <= tocDepth++  let makeItem :: (PandocMonad m) => Tree SecInfo -> VW m (Doc Text)+      makeItem (Node secinfo xs) = do+        line <- tocEntryToLine secinfo+        -- When unnumbered, indent constantly by two,+        -- otherwise indent by (length of marker + 1)+        let markerLen = 1 + maybe 1 T.length (secNumber secinfo)+        childItems <-+          indent markerLen $+            traverse makeItem (filter isBelowTocDepth xs)+        pure (literal line $$ nest markerLen (vcat childItems))++  items <- traverse makeItem (filter isBelowTocDepth subtrees)+  pure $ vcat items++writeVimdoc :: (PandocMonad m) => WriterOptions -> Pandoc -> m Text+writeVimdoc opts document@(Pandoc meta _) =+  let+    sw = fromMaybe (shiftWidth def) $ docShiftWidth meta+    vp = docVimdocPrefix meta+    footnotes = Seq.empty+    initialEnv = def{shiftWidth = sw, writerOptions = opts, vimdocPrefix = vp}+   in+    runRR footnotes initialEnv $ pandocToVimdoc document++pandocToVimdoc :: (PandocMonad m) => Pandoc -> VW m Text+pandocToVimdoc (Pandoc meta body) = do+  st <- ask+  let opts = writerOptions st++  metadata <- metaToContext opts blockListToVimdoc inlineListToVimdoc meta+  main <- do+    body' <- blockListToVimdoc body+    footnotes <- get+    rule <- blockToVimdoc HorizontalRule+    let footnotes' = if Seq.null footnotes+          then Empty+          else vsep (toList $ rule <| footnotes)+    pure $ body' <> blankline <> footnotes'++  title <- inlineListToVimdoc $ docTitle meta+  authors <- traverse inlineListToVimdoc $ docAuthors meta+  let authors' = mconcat $ intersperse ("," <> space) (fmap nowrap authors)+  let tw = writerColumns . writerOptions $ st++  let combinedTitle =+        render (Just tw) . cblock tw $+            (title <> space)+              <> (if null authors' then "" else "by" <> space <> authors')++  -- This is placed here because I couldn't find a way to right-align text+  -- inside template to the width specified by a variable+  let toc_reminder =+        render Nothing . rblock tw $+          ("Type |gO| to see the table of contents." :: Doc Text)++  toc <- render (Just tw) <$> vimdocTOC st body++  let modeline = makeModeLine st+  let context =+        defField "body" main+          . defField "toc" (if writerTableOfContents opts then toc else "")+          . defField "modeline" modeline+          . defField "combined-title" combinedTitle+          . defField "toc-reminder" toc_reminder+          $ metadata++  pure $+    case writerTemplate opts of+      Just tpl -> render (Just tw) $ renderTemplate tpl context+      Nothing -> render (Just tw) main++blockListToVimdoc :: (PandocMonad m) => [Block] -> VW m (Doc Text)+blockListToVimdoc blocks = vcat <$> mapM blockToVimdoc blocks++blockToVimdoc :: (PandocMonad m) => Block -> VW m (Doc Text)++blockToVimdoc (Plain inlines) = inlineListToVimdoc inlines++blockToVimdoc (Para inlines) = do+  contents <- inlineListToVimdoc inlines+  pure $ contents <> blankline++blockToVimdoc (LineBlock inliness) = vcat <$> mapM inlineListToVimdoc inliness++blockToVimdoc (CodeBlock (_, cls, _) code) = do+  sw <- asks shiftWidth+  let lang = case cls of+        (lang' : _) -> lang'+        _ -> ""+  -- NOTE: No blankline after the codeblock because closing `<` is concealed+  pure . vcat $+    [ ">" <> literal lang+    , nest sw (literal code)+    , flush "<"+    ]++blockToVimdoc block@(RawBlock format raw) = case format of+  "vimdoc" -> pure $ literal raw+  _ -> "" <$ report (BlockNotRendered block)++blockToVimdoc (BlockQuote blocks) = do+  content <- blockListToVimdoc blocks+  pure $ nest 2 content <> blankline++blockToVimdoc (OrderedList listAttr items) = do+  let itemSpacer = if isTightList items then empty else blankline+  let itemsWithMarkers = zip (orderedListMarkers listAttr) items+  items' <- forM itemsWithMarkers $ \(marker, blocks) -> do+    let markerLen = T.length marker++    item' <- indent (markerLen + 1) $ blockListToVimdoc blocks+    pure $ literal marker <> space <> nest (markerLen + 1) item' <> itemSpacer+  pure $ vcat items' <> blankline++blockToVimdoc (BulletList items) = do+  let itemSpacer = if isTightList items then empty else blankline+  items' <- forM items $ \blocks -> do+    let marker = "-"+    item <- indent 2 $ blockListToVimdoc blocks+    pure $ marker <> " " <> nest 2 item <> itemSpacer+  pure $ vcat items' <> blankline++blockToVimdoc (DefinitionList items) = do+  sw <- asks shiftWidth+  let sepAll = if all (isTightList . snd) items then vcat else vsep+  items' <- forM items $ \(term, definitions) -> do+    let sepCur = if isTightList definitions then vcat else vsep+    labeledTerm <- mkVimdocDefinitionTerm term+    definitions' <- indent sw $ traverse blockListToVimdoc definitions+    pure $ labeledTerm <> cr <> nest sw (sepCur definitions')+  pure $ sepAll items' <> blankline++blockToVimdoc (Header level (ref, _, _) inlines) = do+  tw <- asks (writerColumns . writerOptions)+  let rule = case level of+        1 -> T.replicate tw "="+        2 -> T.replicate tw "-"+        _ -> ""+  title <- fmap (render Nothing) . inlineListToVimdoc $ case level of+    3 -> capitalize inlines+    _ -> inlines++  label <- mkVimdocTag ref+  -- One manual space that ensures that even if spaceLeft is 0, title and ref+  -- don't touch each other+  let label' = " " <> label+  -- (+ 2) due to stars concealment+  let spaceLeft = tw - T.length title + 2++  pure $ vcat+      [ blankline+      , literal rule+      , literal $ title <> T.justifyRight spaceLeft ' ' label'+      , blankline+      ]++blockToVimdoc HorizontalRule = do+  tw <- asks (writerColumns . writerOptions)+  pure $ literal (T.replicate (tw `div` 2) " *") <> blankline++-- Based on blockToMarkdown' from Text.Pandoc.Writers.Markdown+blockToVimdoc t@(Table (_, _, _) blkCapt specs thead tbody tfoot) = do+  let isColRowSpans (Cell _ _ rs cs _) = rs > 1 || cs > 1+  let rowHasColRowSpans (Row _ cs) = any isColRowSpans cs+  let tbodyHasColRowSpans (TableBody _ _ rhs rs) =+        any rowHasColRowSpans rhs || any rowHasColRowSpans rs+  let theadHasColRowSpans (TableHead _ rs) = any rowHasColRowSpans rs+  let tfootHasColRowSpans (TableFoot _ rs) = any rowHasColRowSpans rs+  let hasColRowSpans =+        theadHasColRowSpans thead+          || any tbodyHasColRowSpans tbody+          || tfootHasColRowSpans tfoot+  let (caption, aligns, widths, headers, rows) =+        toLegacyTable blkCapt specs thead tbody tfoot+  let numcols =+        maximum $+          length aligns :| length widths : map length (headers : rows)+  caption' <- inlineListToVimdoc caption+  let caption''+        | null caption = blankline+        | otherwise = blankline $$ caption' $$ blankline+  let hasSimpleCells = onlySimpleTableCells $ headers : rows+  let isSimple = hasSimpleCells && all (== 0) widths && not hasColRowSpans+  let isPlainBlock (Plain _) = True+      isPlainBlock _ = False+  let hasBlocks = not (all (all (all isPlainBlock)) $ headers : rows)+  let padRow r = r ++ replicate x empty+       where+        x = numcols - length r+  let aligns' = aligns ++ replicate x AlignDefault+       where+        x = numcols - length aligns+  let widths' = widths ++ replicate x 0.0+       where+        x = numcols - length widths+  sw <- asks shiftWidth+  rawHeaders <- padRow <$> mapM blockListToVimdoc headers+  rawRows <- mapM (fmap padRow . mapM blockListToVimdoc) rows+  let hasHeader = all null headers+  if+    | isSimple -> do+        -- Simple table+        tbl <-+          indent sw $+            vimdocTable False hasHeader aligns' widths' rawHeaders rawRows+        pure $ nest sw (tbl $$ caption'') $$ blankline+    | not (hasBlocks || hasColRowSpans) -> do+        -- Multiline table+        tbl <-+          indent sw $+            vimdocTable True hasHeader aligns' widths' rawHeaders rawRows+        pure $ nest sw (tbl $$ caption'') $$ blankline+    | otherwise -> ("[TABLE]" $$ caption'') <$ report (BlockNotRendered t)++blockToVimdoc (Figure _ _ blocks) = blockListToVimdoc blocks++blockToVimdoc (Div _ blocks) = blockListToVimdoc blocks++{- | Create a vimdoc tag. Tag is prefixed with "$vimdocPrefix-" if vimdocPrefix+is a Just value.+>>> runReader (mkVimdocTag "abc") def+"*abc*"+>>> runReader (mkVimdocTag "abc") (def{vimdocPrefix = Just "myCoolProject"})+"*myCoolProject-abc*"+-}+mkVimdocTag :: (Monad m) => Text -> VW m Text+mkVimdocTag tag = do+  asks vimdocPrefix <&> \case+    _ | T.null tag -> ""+    Nothing -> "*" <> tag <> "*"+    Just pref' -> "*" <> pref' <> "-" <> tag <> "*"++{- | Create a hotlink for a tag, ie. a followable vimdoc link. Tag is prefixed+ - with "$vimdocPrefix-" if vimdocPrefix is a Just value+>>> runReader (mkVimdocRef "abc") def+"|abc|"+>>> runReader (mkVimdocRef "abc") (def{vimdocPrefix = Just "myCoolProject"})+"|myCoolProject-abc|"+-}+mkVimdocRef :: (Monad m) => Text -> VW m Text+mkVimdocRef ref =+  asks vimdocPrefix <&> \case+    _ | T.null ref -> ""+    Nothing -> "|" <> ref <> "|"+    Just pref' -> "|" <> pref' <> "-" <> ref <> "|"++mkVimdocDefinitionTerm ::+  (PandocMonad m) =>+  [Inline] ->+  VW m (Doc Text)+mkVimdocDefinitionTerm inlines = do+  il <- asks indentLevel+  tw <- asks (writerColumns . writerOptions)+  label <- case inlines of+    -- NOTE: commands in vim are unique, so they get no prefix+    [Code (ref, _, _) code]+      | T.isPrefixOf ":" code ->+          pure . Just $ "*" <> ref <> "*"+    [Code (ref, _, _) _] | not (T.null ref) -> Just <$> mkVimdocTag ref+    [Span (ref, _, _) _] | not (T.null ref) -> Just <$> mkVimdocTag ref+    _ -> pure Nothing++  term <- case inlines of+    [Code _ code] | T.isPrefixOf ":" code -> pure $ literal code+    _ -> inlineListToVimdoc inlines+  let termLen = offset term+  let labelLen = maybe 0 T.length label++  if il + termLen + labelLen > tw+    then+      pure . mconcat $+        [ case label of+            Nothing -> empty+            -- (+2) due to stars concealment+            Just l -> flush (rblock (tw + 2) $ literal l) <> cr+        , term+        ]+    else+      pure . mconcat $+        [ -- Since we calculated that label fits on the same line as+          -- term and since label actually must exceed textwidth to align+          -- properly, we disable wrapping.+          -- vvvvvvvv+          nowrap term+        , case label of+            Nothing -> empty+            -- (+2) due to stars concealment+            Just l -> rblock (tw - termLen - il + 2) (literal l)+        ]++-- | Write a vimdoc table+vimdocTable ::+  (Monad m) =>+  -- | whether this is a multiline table+  Bool ->+  -- | whether the table has a header+  Bool ->+  -- | column alignments+  [Alignment] ->+  -- | column widths+  [Double] ->+  -- | table header cells+  [Doc Text] ->+  -- | table body rows+  [[Doc Text]] ->+  VW m (Doc Text)+vimdocTable multiline headless aligns widths rawHeaders rawRows = do+  let isSimple = all (== 0) widths+  let alignHeader alignment = case alignment of+        AlignLeft -> lblock+        AlignCenter -> cblock+        AlignRight -> rblock+        AlignDefault -> lblock+  -- Number of characters per column necessary to output every cell+  -- without requiring a line break.+  -- The @+2@ is needed for specifying the alignment.+  let numChars = (+ 2) . maybe 0 maximum . nonEmpty . map offset+  -- Number of characters per column necessary to output every cell+  -- without requiring a line break *inside a word*.+  -- The @+2@ is needed for specifying the alignment.+  let minNumChars = (+ 2) . maybe 0 maximum . nonEmpty . map minOffset+  let columns = transpose (rawHeaders : rawRows)++  il <- asks indentLevel++  -- x = (2 * length columns)         -- spaces for specifying the alignment+  -- y = (length columns - 1)         -- spaces between the columns+  -- x + y = (3 * length columns - 1) -- total needed correction+  tw <- asks (writerColumns . writerOptions)+  let tw' = tw - il - 3 * length columns + 1+  wrap <- asks (writerWrapText . writerOptions)++  -- minimal column width without wrapping a single word+  let relWidth w col =+        max+          (floor $ fromIntegral (tw' - 1) * w)+          ( if wrap == WrapAuto+              then minNumChars col+              else numChars col+          )+  let widthsInChars+        | isSimple = map numChars columns+        | otherwise = zipWith relWidth widths columns+  let makeRow =+        hcat+          . intersperse (lblock 1 (literal " "))+          . zipWith3 alignHeader aligns widthsInChars+  let rows' = map makeRow rawRows+  -- TODO: reduce tw in case head is not empty+  let head' = makeRow rawHeaders <> " ~"+  let head'' =+        if headless+          then empty+          else head'+  let body =+        if multiline+          then+            vsep rows'+              $$ if length rows' < 2+                then blankline+                else empty+          else vcat rows'+  return $+    blankline+      $$ head''+      $$ (if multiline then blankline else empty)+      $$ body++-- | Replace Unicode characters with their ASCII representation+replaceSpecialStrings :: Text -> Text+replaceSpecialStrings =+  let expand c = case c of+        '\x00ad' -> ""+        '\x2013' -> "--"+        '\x2014' -> "---"+        '\x2019' -> "'"+        '\x2026' -> "..."+        _        -> T.singleton c+  in T.concatMap expand++inlineListToVimdoc :: (PandocMonad m) => [Inline] -> VW m (Doc Text)+inlineListToVimdoc inlines = hcat <$> mapM inlineToVimdoc inlines++inlineToVimdoc :: (PandocMonad m) => Inline -> VW m (Doc Text)++inlineToVimdoc (Str str) = pure . literal $ replaceSpecialStrings str++-- Neither `:h help-writing`, nor neovim's grammar.js for vimdoc and+-- highlights.scm say anything about styling text, so we strip all the+-- formatting+inlineToVimdoc (Emph inlines) = inlineListToVimdoc inlines+inlineToVimdoc (Underline inlines) = inlineListToVimdoc inlines+inlineToVimdoc (Strong inlines) = inlineListToVimdoc inlines+inlineToVimdoc (Strikeout inlines) = inlineListToVimdoc inlines+inlineToVimdoc (Superscript inlines) = inlineListToVimdoc inlines+inlineToVimdoc (Subscript inlines) = inlineListToVimdoc inlines+inlineToVimdoc (SmallCaps inlines) = inlineListToVimdoc inlines++inlineToVimdoc (Quoted typ inlines) =+  let quote = case typ of SingleQuote -> "'"; DoubleQuote -> "\""+   in inlineListToVimdoc inlines >>= \text -> pure (quote <> text <> quote)++inlineToVimdoc (Cite _citations inlines) = inlineListToVimdoc inlines++inlineToVimdoc (Code (_, cls, _) code) = do+  let hasNoLang = null cls+  pure . literal $ case T.words code of+    [":help", ref] | hasNoLang -> "|" <> ref <> "|"+    [":h", ref]    | hasNoLang -> "|" <> ref <> "|"+    _                          -> "`" <> code <> "`"++inlineToVimdoc Space = pure space+inlineToVimdoc SoftBreak =+  asks (writerWrapText . writerOptions) >>= \case+    WrapAuto -> pure space+    WrapNone -> pure " "+    WrapPreserve -> pure "\n"++inlineToVimdoc LineBreak = pure "\n"++inlineToVimdoc (Math _ math) = pure . literal $ "`$" <> math <> "$`"++inlineToVimdoc inline@(RawInline (Format format) text) = case format of+  "vimdoc" -> pure $ literal text+  _ -> "" <$ report (InlineNotRendered inline)++inlineToVimdoc (Link _ txt (src, _)) = do+  let srcSuffix = fromMaybe src (T.stripPrefix "mailto:" src)+  linkText <- render Nothing <$> inlineListToVimdoc txt++  let isAutolink = case txt of+        [Str x] | escapeURI x `elem` [src, srcSuffix] -> True+        _ -> False++  pure $ case refdocLinkToLink src of+    Right link | isAutolink -> "|" <> literal link <> "|"+    Right link ->+      literal (T.stripEnd linkText) <> space <> "|" <> literal link <> "|"+    Left _ | isURI src, isAutolink -> literal srcSuffix+    Left _ -> literal (T.stripEnd linkText) <> space <> literal srcSuffix++inlineToVimdoc (Image {}) = pure ""++inlineToVimdoc (Note blocks) = do+  newN <- gets (succ . Seq.length)+  contents <- blockListToVimdoc blocks+  tag <- mkVimdocTag ("footnote" <> tshow newN)+  tw <- asks (writerColumns . writerOptions)++  -- (+2) due to concealment of stars+  --                     vvvvvvvv+  let taggedContents = rblock (tw + 2) (literal tag) $$ contents+  modify (|> taggedContents)++  ref <- mkVimdocRef ("footnote" <> tshow newN)+  pure $ space <> literal ref++inlineToVimdoc (Span _ inlines) = inlineListToVimdoc inlines+++refdocLinkToLink :: Text -> Either PandocError Text+refdocLinkToLink x = (\parser -> readWith parser Nothing x) $ do+  string "http" >> optional (char 's') >> string "://"++  let vimhelpP = do+        try (string "vimhelp.org/") <|> string "neo.vimhelp.org/"++        try (many1Till anyChar (char '#') >> many1TillChar anyChar eof)+          <|> many1TillChar anyChar (try $ string ".html" >> eof)++  let neovimP = do+        string "neovim.io/doc/user/"+        try (many1Till anyChar (char '#') >> many1TillChar anyChar eof)+          <|> do base <- many1TillChar anyChar (try $ string ".html" >> eof)+                 pure $ base <> ".txt"++  try vimhelpP <|> neovimP
+ src/Text/Pandoc/Writers/XML.hs view
@@ -0,0 +1,365 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}++-- |+--   Module      : Text.Pandoc.Writers.XML+--   Copyright   : Copyright (C) 2025- Massimiliano Farinella and John MacFarlane+--   License     : GNU GPL, version 2 or above+--+--   Maintainer  : Massimiliano Farinella <massifrg@gmail.com>+--   Stability   : WIP+--   Portability : portable+--+-- Conversion of 'Pandoc' documents to (pandoc specific) xml markup.+module Text.Pandoc.Writers.XML (writeXML) where++import Data.Map (Map, toList)+import Data.Maybe (mapMaybe)+import qualified Data.Text as T+import Data.Version (versionBranch)+import Text.Pandoc.Class.PandocMonad (PandocMonad)+import Text.Pandoc.Definition+import Text.Pandoc.Options (WriterOptions (..))+import Text.Pandoc.XML.Light+import qualified Text.Pandoc.XML.Light as XML+import Text.Pandoc.XMLFormat+import Text.XML.Light (xml_header)++type PandocAttr = Text.Pandoc.Definition.Attr++writeXML :: (PandocMonad m) => WriterOptions -> Pandoc -> m T.Text+writeXML _ doc = do+  return $ pandocToXmlText doc++text_node :: T.Text -> Content+text_node text = Text (CData CDataText text Nothing)++emptyElement :: T.Text -> Element+emptyElement tag =+  Element+    { elName = unqual tag,+      elAttribs = [],+      elContent = [],+      elLine = Nothing+    }++elementWithContents :: T.Text -> [Content] -> Element+elementWithContents tag contents =+  Element+    { elName = unqual tag,+      elAttribs = [],+      elContent = contents,+      elLine = Nothing+    }++elementWithAttributes :: T.Text -> [XML.Attr] -> Element+elementWithAttributes tag attributes =+  Element+    { elName = unqual tag,+      elAttribs = attributes,+      elContent = [],+      elLine = Nothing+    }++elementWithAttrAndContents :: T.Text -> PandocAttr -> [Content] -> Element+elementWithAttrAndContents tag attr contents = addAttrAttributes attr $ elementWithContents tag contents++asBlockOfInlines :: Element -> [Content]+asBlockOfInlines el = [Elem el, text_node "\n"]++asBlockOfBlocks :: Element -> [Content]+asBlockOfBlocks el = [Elem newline_before_first, newline]+  where+    newline = text_node "\n"+    newline_before_first = if null (elContent el) then el else prependContents [newline] el++itemName :: (Show a) => a -> T.Text+itemName a = T.pack $ takeWhile (/= ' ') (show a)++intAsText :: Int -> T.Text+intAsText i = T.pack $ show i++itemAsEmptyElement :: (Show a) => a -> Element+itemAsEmptyElement item = emptyElement $ itemName item++pandocToXmlText :: Pandoc -> T.Text+pandocToXmlText (Pandoc (Meta meta) blocks) = with_header . with_blocks . with_meta . with_version $ el+  where+    el = prependContents [text_node "\n"] $ emptyElement "Pandoc"+    with_version = addAttribute atNameApiVersion (T.intercalate "," $ map (T.pack . show) $ versionBranch pandocTypesVersion)+    with_meta = appendContents (metaMapToXML meta "meta")+    with_blocks = appendContents (asBlockOfBlocks $ elementWithContents "blocks" $ blocksToXML blocks)+    with_header :: Element -> T.Text+    with_header e = T.concat [T.pack xml_header, "\n", showElement e]++metaMapToXML :: Map T.Text MetaValue -> T.Text -> [Content]+metaMapToXML mmap tag = asBlockOfBlocks $ elementWithContents tag entries+  where+    entries = concatMap to_entry $ toList mmap+    to_entry :: (T.Text, MetaValue) -> [Content]+    to_entry (text, metavalue) = asBlockOfBlocks with_key+      where+        entry = elementWithContents tgNameMetaMapEntry $ metaValueToXML metavalue+        with_key = addAttribute atNameMetaMapEntryKey text entry++metaValueToXML :: MetaValue -> [Content]+metaValueToXML value =+  let name = itemName value+      el = itemAsEmptyElement value+   in case (value) of+        MetaBool b -> asBlockOfInlines $ addAttribute atNameMetaBoolValue bool_value el+          where+            bool_value = if b then "true" else "false"+        MetaString s -> asBlockOfInlines $ appendContents [text_node s] el+        MetaInlines inlines -> asBlockOfInlines $ appendContents (inlinesToXML inlines) el+        MetaBlocks blocks -> asBlockOfBlocks $ appendContents (blocksToXML blocks) el+        MetaList items -> asBlockOfBlocks $ appendContents (concatMap metaValueToXML items) el+        MetaMap mm -> metaMapToXML mm name++blocksToXML :: [Block] -> [Content]+blocksToXML blocks = concatMap blockToXML blocks++inlinesToXML :: [Inline] -> [Content]+inlinesToXML inlines = concatMap inlineContentToContents (ilsToIlsContent inlines [])++data InlineContent+  = NormalInline Inline+  | ElSpace Int+  | ElStr T.Text++ilsToIlsContent :: [Inline] -> [InlineContent] -> [InlineContent]+ilsToIlsContent (Space : xs) [] = ilsToIlsContent xs [ElSpace 1]+ilsToIlsContent (Space : xs) (NormalInline Space : cs) = ilsToIlsContent xs (ElSpace 2 : cs)+ilsToIlsContent (Space : xs) (ElSpace n : cs) = ilsToIlsContent xs (ElSpace (n + 1) : cs)+-- empty Str are always encoded as <Str />+ilsToIlsContent (Str "" : xs) ilct = ilsToIlsContent xs (ElStr "" : ilct)+-- Str s1, Str s2 -> s1<Str content="s2">+ilsToIlsContent (Str s2 : xs) (NormalInline str1@(Str _) : ilct) = ilsToIlsContent xs (ElStr s2 : NormalInline str1 : ilct)+--+ilsToIlsContent (Str s : xs) ilct =+  if T.any (== ' ') s+    then ilsToIlsContent xs (ElStr s : ilct)+    else ilsToIlsContent xs (NormalInline (Str s) : ilct)+ilsToIlsContent (x : xs) ilct = ilsToIlsContent xs (NormalInline x : ilct)+ilsToIlsContent [] ilct = reverse $ lastSpaceAsElem ilct+  where+    lastSpaceAsElem :: [InlineContent] -> [InlineContent]+    lastSpaceAsElem (NormalInline Space : xs) = ElSpace 1 : xs+    lastSpaceAsElem ilcts = ilcts++inlineContentToContents :: InlineContent -> [Content]+inlineContentToContents (NormalInline il) = inlineToXML il+inlineContentToContents (ElSpace 1) = [Elem $ emptyElement "Space"]+inlineContentToContents (ElSpace n) = [Elem $ addAttribute atNameSpaceCount (intAsText n) (emptyElement "Space")]+inlineContentToContents (ElStr "") = [Elem $ emptyElement "Str"]+inlineContentToContents (ElStr s) = [Elem $ addAttribute atNameStrContent s (emptyElement "Str")]++asContents :: Element -> [Content]+asContents el = [Elem el]++wrapBlocks :: T.Text -> [Block] -> [Content]+wrapBlocks tag blocks = asBlockOfBlocks $ elementWithContents tag $ blocksToXML blocks++wrapArrayOfBlocks :: T.Text -> [[Block]] -> [Content]+wrapArrayOfBlocks tag array = concatMap (wrapBlocks tag) array++-- wrapInlines :: T.Text -> [Inline] -> [Content]+-- wrapInlines tag inlines = asBlockOfInlines $ element_with_contents tag $ inlinesToXML inlines++blockToXML :: Block -> [Content]+blockToXML block =+  let el = itemAsEmptyElement block+   in case (block) of+        Para inlines -> asBlockOfInlines $ appendContents (inlinesToXML inlines) el+        Header level (idn, cls, attrs) inlines -> asBlockOfInlines $ appendContents (inlinesToXML inlines) with_attr+          where+            with_attr = addAttrAttributes (idn, cls, attrs ++ [(atNameLevel, intAsText level)]) el+        Plain inlines -> asBlockOfInlines $ appendContents (inlinesToXML inlines) el+        Div attr blocks -> asBlockOfBlocks $ appendContents (blocksToXML blocks) with_attr+          where+            with_attr = addAttrAttributes attr el+        BulletList items -> asBlockOfBlocks $ appendContents (wrapArrayOfBlocks tgNameListItem items) el+        OrderedList (start, style, delim) items -> asBlockOfBlocks $ with_contents . with_attrs $ el+          where+            with_attrs =+              addAttributes+                ( validAttributes+                    [ (atNameStart, intAsText start),+                      (atNameNumberStyle, itemName style),+                      (atNameNumberDelim, itemName delim)+                    ]+                )+            with_contents = appendContents (wrapArrayOfBlocks tgNameListItem items)+        BlockQuote blocks -> asBlockOfBlocks $ appendContents (blocksToXML blocks) el+        HorizontalRule -> asBlockOfInlines el+        CodeBlock attr text -> asBlockOfInlines $ with_contents . with_attr $ el+          where+            with_contents = appendContents [text_node text]+            with_attr = addAttrAttributes attr+        LineBlock lins -> asBlockOfBlocks $ appendContents (concatMap wrapInlines lins) el+          where+            wrapInlines inlines = asContents $ appendContents (inlinesToXML inlines) $ emptyElement tgNameLineItem+        Table attr caption colspecs thead tbodies tfoot -> asBlockOfBlocks $ with_foot . with_bodies . with_head . with_colspecs . with_caption . with_attr $ el+          where+            with_attr = addAttrAttributes attr+            with_caption = appendContents (captionToXML caption)+            with_colspecs = appendContents (colSpecsToXML colspecs)+            with_head = appendContents (tableHeadToXML thead)+            with_bodies = appendContents (concatMap tableBodyToXML tbodies)+            with_foot = appendContents (tableFootToXML tfoot)+        Figure attr caption blocks -> asBlockOfBlocks $ with_contents . with_caption . with_attr $ el+          where+            with_attr = addAttrAttributes attr+            with_caption = appendContents (captionToXML caption)+            with_contents = appendContents (blocksToXML blocks)+        RawBlock (Format format) text -> asContents $ appendContents [text_node text] raw+          where+            raw = addAttribute atNameFormat format el+        DefinitionList items -> asBlockOfBlocks $ appendContents (map definitionListItemToXML items) el++inlineToXML :: Inline -> [Content]+inlineToXML inline =+  let el = itemAsEmptyElement inline+      wrapInlines inlines = asContents $ appendContents (inlinesToXML inlines) el+   in case (inline) of+        Space -> [text_node " "]+        Str s -> [text_node s]+        Emph inlines -> wrapInlines inlines+        Strong inlines -> wrapInlines inlines+        Quoted quote_type inlines -> asContents $ appendContents (inlinesToXML inlines) quoted+          where+            quoted = addAttribute atNameQuoteType (itemName quote_type) el+        Underline inlines -> wrapInlines inlines+        Strikeout inlines -> wrapInlines inlines+        SmallCaps inlines -> wrapInlines inlines+        Superscript inlines -> wrapInlines inlines+        Subscript inlines -> wrapInlines inlines+        SoftBreak -> asContents el+        LineBreak -> asContents el+        Span attr inlines -> asContents $ appendContents (inlinesToXML inlines) with_attr+          where+            with_attr = addAttrAttributes attr el+        Link (idn, cls, attrs) inlines (url, title) -> asContents $ appendContents (inlinesToXML inlines) with_attr+          where+            with_attr = addAttrAttributes (idn, cls, attrs ++ [(atNameLinkUrl, url), (atNameTitle, title)]) el+        Image (idn, cls, attrs) inlines (url, title) -> asContents $ appendContents (inlinesToXML inlines) with_attr+          where+            with_attr = addAttrAttributes (idn, cls, attrs ++ [(atNameImageUrl, url), (atNameTitle, title)]) el+        RawInline (Format format) text -> asContents $ appendContents [text_node text] raw+          where+            raw = addAttribute atNameFormat format el+        Math math_type text -> asContents $ appendContents [text_node text] math+          where+            math = addAttribute atNameMathType (itemName math_type) el+        Code attr text -> asContents $ appendContents [text_node text] with_attr+          where+            with_attr = addAttrAttributes attr el+        Note blocks -> asContents $ appendContents (blocksToXML blocks) el+        Cite citations inlines -> asContents $ appendContents (inlinesToXML inlines) with_citations+          where+            with_citations = addCitations citations el++-- TODO: don't let an attribute overwrite id or class+maybeAttribute :: (T.Text, T.Text) -> Maybe XML.Attr+maybeAttribute (_, "") = Nothing+maybeAttribute ("", _) = Nothing+maybeAttribute (name, value) = Just $ XML.Attr (unqual name) value++validAttributes :: [(T.Text, T.Text)] -> [XML.Attr]+validAttributes pairs = mapMaybe maybeAttribute pairs++appendContents :: [Content] -> Element -> Element+appendContents newContents el = el {elContent = (elContent el) ++ newContents}++prependContents :: [Content] -> Element -> Element+prependContents newContents el = el {elContent = newContents ++ (elContent el)}++addAttributes :: [XML.Attr] -> Element -> Element+addAttributes newAttrs el = el {elAttribs = newAttrs ++ elAttribs el}++addAttribute :: T.Text -> T.Text -> Element -> Element+addAttribute attr_name attr_value el = el {elAttribs = new_attr : elAttribs el}+  where+    new_attr = XML.Attr (unqual attr_name) attr_value++addAttrAttributes :: PandocAttr -> Element -> Element+addAttrAttributes (identifier, classes, attributes) el = addAttributes attrs' el+  where+    attrs' = mapMaybe maybeAttribute (("id", identifier) : ("class", T.intercalate " " classes) : attributes)++addCitations :: [Citation] -> Element -> Element+addCitations citations el = appendContents [Elem $ elementWithContents tgNameCitations $ (text_node "\n") : concatMap citation_to_elem citations] el+  where+    citation_to_elem :: Citation -> [Content]+    citation_to_elem citation = asBlockOfInlines with_suffix+      where+        cit_elem = elementWithAttributes (itemName citation) attrs+        prefix = citationPrefix citation+        suffix = citationSuffix citation+        with_prefix =+          if null prefix+            then cit_elem+            else appendContents [Elem $ elementWithContents tgNameCitationPrefix $ inlinesToXML prefix] cit_elem+        with_suffix =+          if null suffix+            then with_prefix+            else appendContents [Elem $ elementWithContents tgNameCitationSuffix $ inlinesToXML suffix] with_prefix+        attrs =+          map+            (\(n, v) -> XML.Attr (unqual n) v)+            [ ("id", citationId citation),+              (atNameCitationMode, T.pack $ show $ citationMode citation),+              (atNameCitationNoteNum, intAsText $ citationNoteNum citation),+              (atNameCitationHash, intAsText $ citationHash citation)+            ]++definitionListItemToXML :: ([Inline], [[Block]]) -> Content+definitionListItemToXML (inlines, defs) = Elem $ elementWithContents tgNameDefListItem $ term ++ wrapArrayOfBlocks tgNameDefListDef defs+  where+    term = asBlockOfInlines $ appendContents (inlinesToXML inlines) $ emptyElement tgNameDefListTerm++captionToXML :: Caption -> [Content]+captionToXML (Caption short blocks) = asBlockOfBlocks with_short_caption+  where+    el = elementWithContents "Caption" $ blocksToXML blocks+    with_short_caption = case (short) of+      Just inlines -> prependContents (asBlockOfInlines $ elementWithContents tgNameShortCaption $ inlinesToXML inlines) el+      _ -> el++colSpecToXML :: (Alignment, ColWidth) -> [Content]+colSpecToXML (align, cw) = asBlockOfInlines colspec+  where+    colspec = elementWithAttributes "ColSpec" $ validAttributes [(atNameAlignment, itemName align), (atNameColWidth, colwidth)]+    colwidth = case (cw) of+      ColWidth d -> T.pack $ show d+      ColWidthDefault -> "0"++colSpecsToXML :: [(Alignment, ColWidth)] -> [Content]+colSpecsToXML colspecs = asBlockOfBlocks $ elementWithContents tgNameColspecs $ concatMap colSpecToXML colspecs++tableHeadToXML :: TableHead -> [Content]+tableHeadToXML (TableHead attr rows) = asBlockOfBlocks $ elementWithAttrAndContents "TableHead" attr $ concatMap rowToXML rows++tableBodyToXML :: TableBody -> [Content]+tableBodyToXML (TableBody (idn, cls, attrs) (RowHeadColumns headcols) hrows brows) = asBlockOfBlocks $ elementWithAttrAndContents "TableBody" attr children+  where+    attr = (idn, cls, (atNameRowHeadColumns, intAsText headcols) : attrs)+    header_rows = asBlockOfBlocks $ elementWithContents tgNameBodyHeader $ concatMap rowToXML hrows+    body_rows = asBlockOfBlocks $ elementWithContents tgNameBodyBody $ concatMap rowToXML brows+    children = header_rows ++ body_rows++tableFootToXML :: TableFoot -> [Content]+tableFootToXML (TableFoot attr rows) = asBlockOfBlocks $ elementWithAttrAndContents "TableFoot" attr $ concatMap rowToXML rows++rowToXML :: Row -> [Content]+rowToXML (Row attr cells) = asBlockOfBlocks $ elementWithAttrAndContents "Row" attr $ concatMap cellToXML cells++cellToXML :: Cell -> [Content]+cellToXML (Cell (idn, cls, attrs) alignment (RowSpan rowspan) (ColSpan colspan) blocks) = asBlockOfBlocks $ elementWithAttrAndContents "Cell" attr $ blocksToXML blocks+  where+    with_alignment a = (atNameAlignment, itemName alignment) : a+    with_rowspan a = if rowspan > 1 then (atNameRowspan, intAsText rowspan) : a else a+    with_colspan a = if colspan > 1 then (atNameColspan, intAsText colspan) : a else a+    attrs' = (with_colspan . with_rowspan . with_alignment) attrs+    attr = (idn, cls, attrs')
src/Text/Pandoc/Writers/XWiki.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE OverloadedStrings #-} {--Copyright (C) 2008-2023 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2008-2024 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -19,7 +19,7 @@  {- |    Module      : Text.Pandoc.Writers.XWiki-   Copyright   : Copyright (C) 2008-2023 John MacFarlane+   Copyright   : Copyright (C) 2008-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : Derek Chen-Becker <dchenbecker@gmail.com>
src/Text/Pandoc/Writers/ZimWiki.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Writers.ZimWiki-   Copyright   : © 2008-2023 John MacFarlane,+   Copyright   : © 2008-2024 John MacFarlane,                    2017-2019 Alex Ivkin    License     : GNU GPL, version 2 or above @@ -128,7 +128,9 @@                       c <- inlineListToZimWiki opts capt                       return $ "" <> c <> "\n"   headers' <- if all null headers-                 then zipWithM (tableItemToZimWiki opts) aligns (head rows)+                 then case rows of+                        [] -> pure mempty+                        (r:_) -> zipWithM (tableItemToZimWiki opts) aligns r                  else mapM (inlineListToZimWiki opts . removeFormatting)headers  -- emphasis, links etc. are not allowed in table headers   rows' <- mapM (zipWithM (tableItemToZimWiki opts) aligns) rows   let widths = map (maybe 0 maximum . nonEmpty . map T.length) $
src/Text/Pandoc/XML.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.XML-   Copyright   : Copyright (C) 2006-2023 John MacFarlane+   Copyright   : Copyright (C) 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -208,6 +208,7 @@   , "draggable"   , "enctype"   , "enterkeyhint"+  , "fetchpriority"   , "for"   , "form"   , "formaction"
+ src/Text/Pandoc/XMLFormat.hs view
@@ -0,0 +1,188 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Text.Pandoc.XMLFormat+  ( atNameAlignment,+    atNameApiVersion,+    atNameCitationHash,+    atNameCitationMode,+    atNameCitationNoteNum,+    atNameColspan,+    atNameColWidth,+    atNameFormat,+    atNameImageUrl,+    atNameLevel,+    atNameLinkUrl,+    atNameMathType,+    atNameMetaBoolValue,+    atNameMetaMapEntryKey,+    atNameNumberDelim,+    atNameNumberStyle,+    atNameQuoteType,+    atNameRowHeadColumns,+    atNameRowspan,+    atNameSpaceCount,+    atNameStart,+    atNameStrContent,+    atNameTitle,+    tgNameBodyBody,+    tgNameBodyHeader,+    tgNameCitations,+    tgNameCitationPrefix,+    tgNameCitationSuffix,+    tgNameColspecs,+    tgNameDefListDef,+    tgNameDefListItem,+    tgNameDefListTerm,+    tgNameLineItem,+    tgNameListItem,+    tgNameMetaMapEntry,+    tgNameShortCaption,+  )+where++import Data.Text (Text)++-- the attribute carrying the API version of pandoc types in the main Pandoc element+atNameApiVersion :: Text+atNameApiVersion = "api-version"++-- the element of a <meta> or <MetaMap> entry+tgNameMetaMapEntry :: Text+tgNameMetaMapEntry = "entry"++-- the attribute carrying the key name of a <meta> or <MetaMap> entry+atNameMetaMapEntryKey :: Text+atNameMetaMapEntryKey = "key"++-- the attribute carrying the boolean value ("true" or "false") of a MetaBool+atNameMetaBoolValue :: Text+atNameMetaBoolValue = "value"++-- level of a Header+atNameLevel :: Text+atNameLevel = "level"++-- start number of an OrderedList+atNameStart :: Text+atNameStart = "start"++-- number delimiter of an OrderedList+atNameNumberDelim :: Text+atNameNumberDelim = "number-delim"++-- number style of an OrderedList+atNameNumberStyle :: Text+atNameNumberStyle = "number-style"++-- target title in Image and Link+atNameTitle :: Text+atNameTitle = "title"++-- target url in Image+atNameImageUrl :: Text+atNameImageUrl = "src"++-- target url in Link+atNameLinkUrl :: Text+atNameLinkUrl = "href"++-- QuoteType of a Quoted+atNameQuoteType :: Text+atNameQuoteType = "quote-type"++-- MathType of a Math+atNameMathType :: Text+atNameMathType = "math-type"++-- format of a RawInline or a RawBlock+atNameFormat :: Text+atNameFormat = "format"++-- alignment attribute in a ColSpec or in a Cell+atNameAlignment :: Text+atNameAlignment = "alignment"++-- ColWidth attribute in a ColSpec+atNameColWidth :: Text+atNameColWidth = "col-width"++-- RowHeadColumns attribute in a TableBody+atNameRowHeadColumns :: Text+atNameRowHeadColumns = "row-head-columns"++-- RowSpan attribute in a Cell+atNameRowspan :: Text+atNameRowspan = "row-span"++-- ColSpan attribute in a Cell+atNameColspan :: Text+atNameColspan = "col-span"++-- the citationMode of a Citation+atNameCitationMode :: Text+atNameCitationMode = "mode"++-- the citationHash of a Citation+atNameCitationHash :: Text+atNameCitationHash = "hash"++-- the citationNoteNum of a Citation+atNameCitationNoteNum :: Text+atNameCitationNoteNum = "note-num"++-- the number of consecutive spaces of the <Space> element+atNameSpaceCount :: Text+atNameSpaceCount = "count"++-- the content of the <Str> element+atNameStrContent :: Text+atNameStrContent = "content"++-- container of Citation elements in Cite inlines+tgNameCitations :: Text+tgNameCitations = "citations"++-- element around the prefix inlines of a Citation+tgNameCitationPrefix :: Text+tgNameCitationPrefix = "prefix"++-- element around the suffix inlines of a Citation+tgNameCitationSuffix :: Text+tgNameCitationSuffix = "suffix"++-- list item for BulletList and OrderedList+tgNameListItem :: Text+tgNameListItem = "item"++-- list item for DefinitionList+tgNameDefListItem :: Text+tgNameDefListItem = "item"++-- element around the inlines of the term of a DefinitionList item+tgNameDefListTerm :: Text+tgNameDefListTerm = "term"++-- element around the blocks of a definition in a DefinitionList item+tgNameDefListDef :: Text+tgNameDefListDef = "def"++-- optional element of the ShortCaption+tgNameShortCaption :: Text+tgNameShortCaption = "ShortCaption"++-- element around the ColSpec of a Table+tgNameColspecs :: Text+tgNameColspecs = "colspecs"++-- element around the header rows of a TableBody+tgNameBodyHeader :: Text+tgNameBodyHeader = "header"++-- element around the body rows of a TableBody+tgNameBodyBody :: Text+tgNameBodyBody = "body"++-- element around the inlines of a line in a LineBlock+tgNameLineItem :: Text+tgNameLineItem = "line"
test/Tests/Command.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE BangPatterns #-} {- |    Module      : Tests.Command-   Copyright   : © 2006-2023 John MacFarlane+   Copyright   : © 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley@edu>
test/Tests/Helpers.hs view
@@ -3,7 +3,7 @@ {-# LANGUAGE FlexibleInstances    #-} {- |    Module      : Tests.Helpers-   Copyright   : © 2006-2023 John MacFarlane+   Copyright   : © 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley@edu>@@ -16,6 +16,7 @@                      , TestResult(..)                      , setupEnvironment                      , showDiff+                     , nativeDiff                      , testGolden                      , (=?>)                      , purely@@ -89,12 +90,14 @@   mldpath   <- Env.lookupEnv "LD_LIBRARY_PATH"   mdyldpath <- Env.lookupEnv "DYLD_LIBRARY_PATH"   mpdd <- Env.lookupEnv "pandoc_datadir"+  mbpath <- Env.lookupEnv "PATH"   -- Note that Cabal sets the pandoc_datadir environment variable   -- to point to the source directory, since otherwise getDataFilename   -- will look in the data directory into which pandoc will be installed   -- (but has not yet been).  So when we spawn a new process with   -- pandoc, we need to make sure this environment variable is set.-  return $ ("PATH",takeDirectory testExePath) :+  return $ ("PATH",takeDirectory testExePath <>+                    maybe mempty (searchPathSeparator:) mbpath) :            ("TMP",".") :            ("LANG","en_US.UTF-8") :            ("HOME", "./") :@@ -129,6 +132,19 @@ vividize (Both s _) = "  " ++ s vividize (First s)  = "- " ++ s vividize (Second s) = "+ " ++ s++nativeDiff :: FilePath -> Pandoc -> Pandoc -> IO (Maybe String)+nativeDiff normPath expectedNative actualNative+  | expectedNative == actualNative = return Nothing+  | otherwise = Just <$> do+      expected <- T.unpack <$> runIOorExplode (writeNative def expectedNative)+      actual <- T.unpack <$> runIOorExplode (writeNative def actualNative)+      let dash = replicate 72 '-'+      let diff = getDiff (lines actual) (lines expected)+      return $ '\n' : dash +++               "\n--- " ++ normPath +++               "\n+++ " ++ "test" ++ "\n" +++               showDiff (1,1) diff ++ dash  purely :: (b -> PandocPure a) -> b -> a purely f = either (error . show) id . runPure . f
test/Tests/MediaBag.hs view
@@ -7,42 +7,50 @@ import Text.Pandoc.Class.IO (extractMedia) import Text.Pandoc.Class (fillMediaBag, runIOorExplode) import System.IO.Temp (withTempDirectory)-import Text.Pandoc.Shared (inDirectory) import System.FilePath import Text.Pandoc.Builder as B-import System.Directory (doesFileExist, copyFile)+import qualified Data.Text as T+import System.Directory (doesFileExist, makeAbsolute)  tests :: [TestTree] tests = [   testCase "test fillMediaBag & extractMedia" $-      withTempDirectory "." "extractMediaTest" $ \tmpdir -> inDirectory tmpdir $ do-        copyFile "../../test/lalune.jpg" "moon.jpg"+      withTempDirectory "." "extractMediaTest" $ \tmpdir -> do+        -- Use absolute paths so the test does not need to change+        -- the process-wide current directory (which is not thread-safe+        -- and breaks other tests running in parallel).+        absTmpdir <- makeAbsolute tmpdir+        absLalune <- makeAbsolute "lalune.jpg"         let d = B.doc $-                  B.para (B.image "../../test/lalune.jpg" "" mempty) <>-                  B.para (B.image "moon.jpg" "" mempty) <>+                  -- simple relative path -> extracted with original name+                  B.para (B.image "lalune.jpg" "" mempty) <>+                  -- absolute path -> extracted with hashed name+                  B.para (B.image (T.pack absLalune) "" 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)+        let fooDir = absTmpdir </> "foo"         runIOorExplode $ do           fillMediaBag d-          extractMedia "foo" d-        exists1 <- doesFileExist ("foo" </> "moon.jpg")+          extractMedia fooDir d+        exists1 <- doesFileExist (fooDir </> "lalune.jpg")         assertBool "file in directory is not extracted with original name" exists1-        exists2 <- doesFileExist ("foo" </> "f9d88c3dbe18f6a7f5670e994a947d51216cdf0e.jpg")-        assertBool "file above directory is not extracted with hashed name" exists2-        exists3 <- doesFileExist ("foo" </> "2a0eaa89f43fada3e6c577beea4f2f8f53ab6a1d.lua")-        exists4 <- doesFileExist "a.lua"+        exists2 <- doesFileExist (fooDir </> "f9d88c3dbe18f6a7f5670e994a947d51216cdf0e.jpg")+        assertBool "file with absolute path is not extracted with hashed name" exists2+        exists3 <- doesFileExist (fooDir </> "2a0eaa89f43fada3e6c577beea4f2f8f53ab6a1d.png")+        exists4 <- doesFileExist (absTmpdir </> "a.lua")         assertBool "data uri with malicious payload gets written outside of destination dir"           (exists3 && not exists4)-        exists5 <- doesFileExist ("foo" </> "d5fceb6532643d0d84ffe09c40c481ecdf59e15a.gif")+        exists5 <- doesFileExist (fooDir </> "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)+        let barDir = absTmpdir </> "bar"         runIOorExplode $ do           fillMediaBag e-          extractMedia "bar" e-        exists6 <- doesFileExist ("bar" </> "772ceca21a2751863ec46cb23db0e7fc35b9cff8.png")-        exists7 <- doesFileExist "b.lua"+          extractMedia barDir e+        exists6 <- doesFileExist (barDir </> "772ceca21a2751863ec46cb23db0e7fc35b9cff8.png")+        exists7 <- doesFileExist (absTmpdir </> "b.lua")         assertBool "data uri with double-encoded malicious payload gets written outside of destination dir"           (exists6 && not exists7)   ]
test/Tests/Old.hs view
@@ -1,6 +1,6 @@ {- |    Module      : Tests.Old-   Copyright   : © 2006-2023 John MacFarlane+   Copyright   : © 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley@edu>@@ -26,7 +26,7 @@ tests pandocPath =   [ testGroup "markdown"     [ testGroup "writer"-      $ writerTests' "markdown" ++ lhsWriterTests' "markdown"+      $ writerTests' "markdown" ++ lhsWriterTests' "markdown" ++ extWriterTests' "markdown"     , testGroup "reader"       [ test' "basic" ["-r", "markdown", "-w", "native", "-s"]         "testsuite.txt" "testsuite.native"@@ -78,6 +78,14 @@     , s5WriterTest' "inserts"  ["-s", "-H", "insert",       "-B", "insert", "-A", "insert", "-c", "main.css"] "html4"     ]+  , testGroup "asciidoc"+    [ testGroup "writer" (writerTests' "asciidoc" +++                          writerTests' "asciidoc_legacy")+    , testGroup "reader"+      [ test' "basic" ["-f", "asciidoc", "-t", "native", "-s"]+          "asciidoc-reader.adoc" "asciidoc-reader.native"+      ]+    ]   , testGroup "textile"     [ testGroup "writer" $ writerTests' "textile"     , test' "reader" ["-r", "textile", "-w", "native", "-s"]@@ -183,9 +191,7 @@         "tikiwiki-reader.tikiwiki" "tikiwiki-reader.native" ]   , testGroup "other writers" $ map (\f -> testGroup f $ writerTests' f)     [ "opendocument" , "context" , "texinfo", "icml", "tei"-    , "man" , "plain" , "asciidoc", "asciidoc_legacy"-    , "xwiki", "zimwiki"-    ]+    , "man" , "plain" , "xwiki", "zimwiki" ]   , testGroup "writers-lang-and-dir"     [ test' "latex" ["-f", "native", "-t", "latex", "-s"]       "writers-lang-and-dir.native" "writers-lang-and-dir.latex"@@ -196,7 +202,14 @@     [ testGroup "writer" $ writerTests' "muse"     ]   , testGroup "ms"-    [ testGroup "writer" $ writerTests' "ms"+    [ test' "basic"  ["-f", "native", "-t", "ms", "--columns=80",+                      "--variable", "pandoc-version=",+                      "--pdf-engine", "pdfroff", "-s"]+      "testsuite.native" "writer.ms"+    , test' "tables" ["-f", "native", "-t", "ms", "--columns=80",+                      "--variable", "pandoc-version=",+                      "--pdf-engine", "pdfroff"]+      "tables.native"  "tables.ms"     ]   , testGroup "typst"     [ testGroup "writer" $ writerTests' "typst" ++ extWriterTests' "typst"@@ -242,6 +255,33 @@       "ipynb/rank.ipynb" "ipynb/rank.out.html"     ]   , testGroup "markua" [ testGroup "writer" $ writerTests' "markua"]+  , testGroup "ansi"+      [ test' "ansi" ["-f", "markdown", "-t", "ansi"]+        "ansi-test.txt" "ansi-test.ansi"+      ]+  , testGroup "pod"+      [ test' "pod" ["-f", "pod", "-t", "native"]+        "pod-reader.pod" "pod-reader.native"+      ]+  , testGroup "vimdoc" [ testGroup "writer" $+      writerTests' "vimdoc" +++        [ test' "vimdoc-specific definition lists"+            ["-s", "-r", "markdown", "-w", "vimdoc", "--toc", "--columns=78"]+            "vimdoc/definition-lists.markdown" "vimdoc/definition-lists.vimdoc"+        , test' "linking to docs"+            ["-s", "-r", "markdown", "-w", "vimdoc", "--toc", "--columns=78"]+            "vimdoc/vim-online-doc.markdown" "vimdoc/vim-online-doc.vimdoc"+        , test' "unnumbered TOC up to level 2 headers"+            ["-s", "-r", "markdown", "-w", "vimdoc", "--toc", "--columns=78",+             "--toc-depth=2"]+            "vimdoc/headers.markdown" "vimdoc/headers.vimdoc"+        , test' "numbered TOC"+            ["-s", "-r", "markdown", "-w", "vimdoc", "--toc", "--columns=78",+             "-N"]+            "vimdoc/headers.markdown" "vimdoc/headers-numbered.vimdoc"+        ]+    ]+  , testGroup "bbcode" [testGroup "writer" $ writerTests' "bbcode"]   ]  where     test'           = test pandocPath@@ -304,7 +344,7 @@ s5WriterTest :: FilePath -> String -> [String] -> String -> TestTree s5WriterTest pandocPath modifier opts format   = test pandocPath (format ++ " writer (" ++ modifier ++ ")")-    (["-r", "native", "-w", format] ++ opts)+    (["-r", "native", "-w", format] ++ opts ++ ["--variable", "pandoc-version="])     "s5.native"  ("s5-" ++ modifier <.> "html")  fb2WriterTest :: FilePath -> String -> [String] -> String -> String -> TestTree
test/Tests/Readers/Creole.hs view
@@ -2,7 +2,7 @@ {- |    Module      : Tests.Readers.Creole    Copyright   : © 2017 Sascha Wilde-                   2017-2023 John MacFarlane+                   2017-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : Sascha Wilde <wilde@sha-bang.de>
test/Tests/Readers/Docx.hs view
@@ -15,11 +15,11 @@ import Codec.Archive.Zip import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as B-import qualified Data.Map as M import qualified Data.Text as T import Data.Maybe import System.IO.Unsafe import Test.Tasty+import Test.Tasty.Golden.Advanced import Test.Tasty.HUnit import Tests.Helpers import Text.Pandoc@@ -27,52 +27,24 @@ import qualified Text.Pandoc.MediaBag as MB import Text.Pandoc.UTF8 as UTF8 --- We define a wrapper around pandoc that doesn't normalize in the--- tests. Since we do our own normalization, we want to make sure--- we're doing it right.--newtype NoNormPandoc = NoNormPandoc {unNoNorm :: Pandoc}-                 deriving Show--noNorm :: Pandoc -> NoNormPandoc-noNorm = NoNormPandoc- defopts :: ReaderOptions defopts = def{ readerExtensions = getDefaultExtensions "docx" } -instance ToString NoNormPandoc where-  toString d = T.unpack $ purely (writeNative def{ writerTemplate = s }) $ toPandoc d-   where s = case d of-                  NoNormPandoc (Pandoc (Meta m) _)-                    | M.null m  -> Nothing-                    | otherwise -> Just mempty -- need this to get meta output--instance ToPandoc NoNormPandoc where-  toPandoc = unNoNorm--compareOutput :: ReaderOptions-                 -> FilePath-                 -> FilePath-                 -> IO (NoNormPandoc, NoNormPandoc)-compareOutput opts docxFile nativeFile = do-  df <- B.readFile docxFile-  nf <- UTF8.toText <$> BS.readFile nativeFile-  p <- runIOorExplode $ readDocx opts df-  df' <- runIOorExplode $ readNative def nf-  return (noNorm p, noNorm df')--testCompareWithOptsIO :: ReaderOptions -> String -> FilePath -> FilePath -> IO TestTree-testCompareWithOptsIO opts name docxFile nativeFile = do-  (dp, np) <- compareOutput opts docxFile nativeFile-  return $ test id name (dp, np)--testCompareWithOpts :: ReaderOptions -> String -> FilePath -> FilePath -> TestTree-testCompareWithOpts opts name docxFile nativeFile =-  unsafePerformIO $ testCompareWithOptsIO opts name docxFile nativeFile- testCompare :: String -> FilePath -> FilePath -> TestTree testCompare = testCompareWithOpts defopts +testCompareWithOpts :: ReaderOptions -> String -> FilePath -> FilePath -> TestTree+testCompareWithOpts opts testName docxFP nativeFP =+  goldenTest+  testName+  (do nf <- UTF8.toText <$> BS.readFile nativeFP+      runIOorExplode (readNative def nf))+  (do df <- B.readFile docxFP+      runIOorExplode (readDocx opts df))+  (nativeDiff nativeFP)+  (\a -> runIOorExplode (writeNative def{ writerTemplate = Just mempty} a)+            >>= BS.writeFile nativeFP . UTF8.fromText)+ testForWarningsWithOptsIO :: ReaderOptions -> String -> FilePath -> [String] -> IO TestTree testForWarningsWithOptsIO opts name docxFile expected = do   df <- B.readFile docxFile@@ -236,9 +208,25 @@             "docx/overlapping_targets.docx"             "docx/overlapping_targets.native"           , testCompare+            "anchor in header after anchor"+            "docx/anchor_header_after_anchor.docx"+            "docx/anchor_header_after_anchor.native"+          , testCompare             "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@@ -298,6 +286,10 @@             "docx/definition_list.docx"             "docx/definition_list.native"           , testCompare+            "task lists"+            "docx/task_list.docx"+            "docx/task_list.native"+          , testCompare             "custom defined lists in styles"             "docx/german_styled_lists.docx"             "docx/german_styled_lists.native"@@ -338,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"@@ -479,11 +475,25 @@             "comment warnings (all)"             "docx/comments_warning.docx"             ["Docx comment 1 will not retain formatting"]+          , testForWarningsWithOpts def{readerTrackChanges=AllChanges,+                                        readerExtensions=extensionsFromList [Ext_styles]}+            "comments (with styles extension)"+            "docx/comments.docx"+            []           ]         , testGroup "media"           [ 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
test/Tests/Readers/DokuWiki.hs view
@@ -269,9 +269,9 @@                     , ">> baz"                     , "> bat"                     ] =?>-          blockQuote (plain "foo" <>-                      plain "no space is required after >" <>-                      plain "bar" <>+          blockQuote (plain (text "foo" <> linebreak <>+                        text "no space is required after >" <> linebreak <>+                        text "bar") <>                       blockQuote (plain "baz") <>                       plain "bat")         , "Code block" =:
test/Tests/Readers/EPUB.hs view
@@ -1,6 +1,6 @@ {- |    Module      : Tests.Readers.EPUB-   Copyright   : © 2006-2023 John MacFarlane+   Copyright   : © 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.eu>
test/Tests/Readers/HTML.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Tests.Readers.HTML-   Copyright   : © 2006-2023 John MacFarlane+   Copyright   : © 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -87,16 +87,16 @@             setMeta "lang" (text "es") (doc (plain (text "hola")))           ]         , testGroup "main"-          [ test htmlNativeDivs "<main> becomes <div role=main>" $ "<main>hello</main>" =?>-            doc (divWith ("", [], [("role", "main")]) (plain (text "hello")))+          [ test htmlNativeDivs "<main> contents are parsed" $ "<header>ignore me</header><nav><p>ignore me</p><main>hello</main><footer>ignore me</footer>" =?>+            doc (plain (text "hello"))           , test htmlNativeDivs "<main role=X> becomes <div role=X>" $ "<main role=foobar>hello</main>" =?>             doc (divWith ("", [], [("role", "foobar")]) (plain (text "hello")))           , test htmlNativeDivs "<main> has attributes preserved" $ "<main id=foo class=bar data-baz=qux>hello</main>" =?>             doc (divWith ("foo", ["bar"], [("role", "main"), ("baz", "qux")]) (plain (text "hello")))           , test htmlNativeDivs "<main> closes <p>" $ "<p>hello<main>main content</main>" =?>-            doc (para (text "hello") <> divWith ("", [], [("role", "main")]) (plain (text "main content")))+            doc (plain (text "main content"))           , test htmlNativeDivs "<main> followed by text" $ "<main>main content</main>non-main content" =?>-            doc (divWith ("", [], [("role", "main")]) (plain (text "main content")) <> plain (text "non-main content"))+            doc (plain (text "main content"))           ]         , testGroup "code"           [@@ -124,16 +124,16 @@         , testGroup "header"           [ test htmlNativeDivs "<header> is parsed as a div" $             "<header id=\"title\">Title</header>" =?>-            divWith ("title", mempty, mempty) (plain "Title")+            divWith ("title", ["header"], mempty) (plain "Title")           ]         , testGroup "code block"           [ test html "attributes in pre > code element" $             "<pre><code id=\"a\" class=\"python\">\nprint('hi')\n</code></pre>"             =?>-            codeBlockWith ("a", ["python"], []) "print('hi')"+            codeBlockWith ("a", ["python"], []) "\nprint('hi')"            , test html "attributes in pre take precedence" $-            "<pre id=\"c\"><code id=\"d\">\nprint('hi mom!')\n</code></pre>"+            "<pre id=\"c\"><code id=\"d\">print('hi mom!')\n</code></pre>"             =?>             codeBlockWith ("c", [], []) "print('hi mom!')"           ]
test/Tests/Readers/Jira.hs view
@@ -2,10 +2,10 @@ {-# LANGUAGE ScopedTypeVariables #-} {- |    Module      : Tests.Readers.Jira-   Copyright   : © 2019-2023 Albert Krewinel+   Copyright   : © 2019-2024 Albert Krewinel    License     : GNU GPL, version 2 or above -   Maintainer  : Albert Krewinkel <tarleb@zeitkraut.de>+   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>    Stability   : alpha    Portability : portable 
test/Tests/Readers/LaTeX.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Tests.Readers.LaTeX-   Copyright   : © 2006-2023 John MacFarlane+   Copyright   : © 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>
test/Tests/Readers/Man.hs view
@@ -2,7 +2,7 @@ {- |    Module      : Tests.Readers.Man    Copyright   : © 2018-2019 Yan Pas <yanp.bugz@gmail.com>,-                   2018-2023 John MacFarlane+                   2018-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>
test/Tests/Readers/Markdown.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Tests.Readers.Markdown-   Copyright   : © 2006-2023 John MacFarlane+   Copyright   : © 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -29,10 +29,6 @@ markdownSmart = purely $  readMarkdown def { readerExtensions =                              enableExtension Ext_smart pandocExtensions } -markdownCDL :: Text -> Pandoc-markdownCDL = purely $ readMarkdown def { readerExtensions = enableExtension-                 Ext_compact_definition_lists pandocExtensions }- markdownGH :: Text -> Pandoc markdownGH = purely $ readMarkdown def {readerExtensions = enableExtension                  Ext_wikilinks_title_before_pipe githubMarkdownExtensions }@@ -58,6 +54,9 @@ autolinkWith attr s = linkWith attr s' "" (str s')   where s' = T.pack s +wikilink :: Attr+wikilink = (mempty, ["wikilink"], mempty)+ bareLinkTests :: [(Text, Inlines)] bareLinkTests =   [ ("http://google.com is a search engine.",@@ -185,7 +184,6 @@                 , ("after literal backticks", ["`x``- x`"            ], [code "x``- x"                                           ])                 ]               lis = ["`text","y","x`"]-              lis' = ["text","y","x"]               bldLsts w lsts txts                 = let (res, res', f) =                          foldr (\((_, _, lt), lc) (acc, tacc, t) ->@@ -207,18 +205,12 @@                =?> bldLsts plain lsts lis              | lsts <- [ [i, j, k] | i <- lists, j <- lists, k <- lists]              ]-          <> [ "lists with newlines and indent in backticks" =:-               T.intercalate ("\n" <> T.replicate 4 " ") (zipWith (\i (_, lt, _) -> lt <> i) lis lsts)-               =?> let (_, _, f) = head lsts-                   in f [plain $ code $ T.intercalate (T.replicate 5 " ") $ head lis' : zipWith (\i (_, lt, _) -> lt <> i) (tail lis') (tail lsts)]-             | lsts <- [ [i, j, k] | i <- lists, j <- lists, k <- lists]-             ]           <> [ "lists with blank lines and indent in backticks" =:-               T.intercalate ("\n\n" <> T.replicate 4 " ") (zipWith (\i (_, lt, _) -> lt <> i) lis lsts)+               T.intercalate ("\n\n" <> T.replicate 4 " ") (zipWith (\i (_, lt, _) -> lt <> i) lis (l:ls))                <> "\n"-               =?> let (_, _, f) = head lsts-                   in f . pure $ (para . text $ head lis) <> bldLsts para (tail lsts) (tail lis)-             | lsts <- [ [i, j, k] | i <- lists, j <- lists, k <- lists]+               =?> let (_, _, f) = l+                   in f . pure $ (para . text $ "`text") <> bldLsts para ls (drop 1 lis)+             | (l:ls) <- [ [i, j, k] | i <- lists, j <- lists, k <- lists]              ]         , testGroup "emph and strong"           [ "two strongs in emph" =:@@ -312,22 +304,22 @@         , testGroup "Github wiki links"           [ test markdownGH "autolink" $             "[[https://example.org]]" =?>-            para (link "https://example.org" "wikilink" (str "https://example.org"))+            para (linkWith wikilink "https://example.org" "" (str "https://example.org"))           , test markdownGH "link with title" $             "[[title|https://example.org]]" =?>-            para (link "https://example.org" "wikilink" (str "title"))+            para (linkWith wikilink "https://example.org" "" (str "title"))           , test markdownGH "bad link with title" $             "[[title|random string]]" =?>-            para (link "random string" "wikilink" (str "title"))+            para (linkWith wikilink "random string" "" (str "title"))           , test markdownGH "autolink not being a link" $             "[[Name of page]]" =?>-            para (link "Name of page" "wikilink" (text "Name of page"))+            para (linkWith wikilink "Name of page" "" (text "Name of page"))           , test markdownGH "autolink not being a link with a square bracket" $             "[[Name of ]page]]" =?>-            para (link "Name of ]page" "wikilink" (text "Name of ]page"))+            para (linkWith wikilink "Name of ]page" "" (text "Name of ]page"))           , test markdownGH "link with inline start should be a link" $             "[[t`i*t_le|https://example.org]]" =?>-            para (link "https://example.org" "wikilink" (str "t`i*t_le"))+            para (linkWith wikilink "https://example.org" "" (str "t`i*t_le"))           ]         , testGroup "Headers"           [ "blank line before header" =:@@ -383,6 +375,12 @@           , test markdownSmart "unclosed double quote"             ("**this should \"be bold**"             =?> para (strong "this should \8220be bold"))+          , test markdownSmart "single quote in inline note within single quotes" $ -- issue #11613+              "'a^['b'.] c.'" =?>+              para (singleQuoted ("a" <> note (para (singleQuoted "b" <> ".")) <> space <> "c."))+          , test markdownSmart "double quote in inline note within double quotes" $ -- issue #11613+              "\"a^[\"b\".] c.\"" =?>+              para (doubleQuoted ("a" <> note (para (doubleQuoted "b" <> ".")) <> space <> "c."))           ]         , testGroup "sub- and superscripts"           [@@ -449,7 +447,7 @@                   <>                   codeBlockWith ("",["haskell"],[]) "b"                   <>-                  rawBlock "html" "<div>\n\n"+                  divWith ("",[],[]) mempty           ] -- the round-trip properties frequently fail --        , testGroup "round trip"@@ -465,14 +463,14 @@           , "blank space before first def" =:             "foo1\n\n  :  bar\n\nfoo2\n\n  : bar2\n  : bar3\n" =?>             definitionList [ (text "foo1", [para (text "bar")])-                           , (text "foo2", [para (text "bar2"),-                                            plain (text "bar3")])+                           , (text "foo2", [plain (text "bar2"),+                                            para (text "bar3")])                            ]           , "blank space before second def" =:             "foo1\n  :  bar\n\nfoo2\n  : bar2\n\n  : bar3\n" =?>             definitionList [ (text "foo1", [plain (text "bar")])                            , (text "foo2", [plain (text "bar2"),-                                            para (text "bar3")])+                                            plain (text "bar3")])                            ]           , "laziness" =:             "foo1\n  :  bar\nbaz\n  : bar2\n" =?>@@ -482,8 +480,8 @@                            ]           , "no blank space before first of two paragraphs" =:             "foo1\n  : bar\n\n    baz\n" =?>-            definitionList [ (text "foo1", [para (text "bar") <>-                                            para (text "baz")])+            definitionList [ (text "foo1", [plain (text "bar") <>+                                            plain (text "baz")])                            ]           , "first line not indented" =:             "foo\n: bar\n" =?>@@ -496,14 +494,6 @@             divWith nullAttr (definitionList               [ (text "foo", [bulletList [plain (text "bar")]]) ])           ]-        , testGroup "+compact_definition_lists"-          [ test markdownCDL "basic compact list" $-            "foo1\n:   bar\n    baz\nfoo2\n:   bar2\n" =?>-            definitionList [ (text "foo1", [plain (text "bar" <> softbreak <>-                                                     text "baz")])-                           , (text "foo2", [plain (text "bar2")])-                           ]-          ]         , testGroup "lists"           [ "issue #1154" =:               " -  <div>\n    first div breaks\n    </div>\n\n    <button>if this button exists</button>\n\n    <div>\n    with this div too.\n    </div>\n"@@ -594,4 +584,11 @@                   (str "@cita" <> space <> str "[foo]")               )           ]+      , testGroup "figures"+        [ "latex placement" =:+          "![caption](img.jpg){latex-placement=\"htbp\" alt=\"alt text\"}" =?>+          figureWith ("", [], [("latex-placement", "htbp")])+            (simpleCaption $ plain "caption")+            (plain $ image (T.pack "img.jpg") (T.pack "") (text "alt text"))         ]+      ]
+ test/Tests/Readers/Mdoc.hs view
@@ -0,0 +1,321 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+   Module      : Tests.Readers.Mdoc+   Copyright   : © 2024 Evan Silberman+   License     : GNU GPL, version 2 or above++   Maintainer  : +   Stability   : alpha+   Portability : portable++Tests for the Mdoc reader.+-}++module Tests.Readers.Mdoc (tests) where++import Data.Text (Text)+import qualified Data.Text as T+import Test.Tasty+import Test.Tasty.HUnit (HasCallStack)+import Tests.Helpers+import Text.Pandoc+import Text.Pandoc.Arbitrary ()+import Text.Pandoc.Builder++mdoc :: Text -> Pandoc+mdoc = purely $ readMdoc def++infix 4 =:+(=:) :: (ToString c, HasCallStack)+     => String -> (Text, c) -> TestTree+(=:) = test mdoc++cls :: Text -> Attr+cls x = (mempty, [x], mempty)++tests :: [TestTree]+tests = [+  testGroup "one-line enclosures"+    [ "Dq" =:+        ".Dq hello world" =?>+        para (doubleQuoted "hello world")+    , "Sq" =:+        ".Sq hello world" =?>+        para (singleQuoted "hello world")+    , "empty" =:+        ".Dq" =?>+        para (doubleQuoted mempty)+    , "nested" =:+        ".Dq Pq hello world" =?>+        para (doubleQuoted "(hello world)")+    , "nested with closing delimiters" =:+        ".Dq Pq hi mom !" =?>+        para (doubleQuoted "(hi mom)" <> "!")+    , "nested multiline enclosure" =:+        ".Dq Po a \\&; b \\&; c Pc ." =?>+        para (doubleQuoted "(a ; b ; c)" <> ".")+    , "with inlines" =:+        ".Dq hello Sy world ." =?>+        para (doubleQuoted ("hello" <> space <> strong "world" <> "."))+    , "with text production" =:+        ".Dq I love the St -iso8601 standard!" =?>+        para (doubleQuoted "I love the ISO 8601 standard!")+    , "with Ns" =:+        ".Op , Ns Ar value ..." =?>+        para ("[," <> (codeWith (cls "variable") "value ...") <> "]")+    , "ending with open delimiter" =:+        ".Dq hi (" =?>+        para (doubleQuoted "hi (")+    ]+  , testGroup "multiline enclosures"+    [ "nested multiline" =:+        T.unlines [".Bo", ".Po", "hi", ".Pc", ".Bc"] =?>+        para ("[(hi)]")+    , "nested on one line" =:+        ".Bo Po hi Pc Bc" =?>+        para ("[(hi)]")+    , "with wacky delimiters" =:+        ".Bo ( | hi ! Bc ?" =?>+        para ("([| hi!]?")+    ]+  , testGroup "simple inlines"+    [ "Sy" =:+        ".Sy hello world" =?>+        para (strong "hello world")+    , "Em" =:+        ".Em hello world" =?>+        para (emph "hello world")+    , "Ev" =:+        ".Ev HELLO_WORLD ," =?>+        para (codeWith (cls "Ev") "HELLO_WORLD" <> ",")+    , "Ar" =:+        ".Ar ) z" =?>+        para (codeWith (cls "variable") "file ..." <> ") " <> codeWith (cls "variable") "z")+    , "In" =:+        ".In ( math.h ) b c" =?>+        para ("(" <> codeWith (cls "In") "<math.h>" <> ") b c")+    , "Mt" =:+        ".Mt a@example.org , b@example.org" =?>+        para ((link "mailto:a@example.org" "" "a@example.org") <>+               "," <> space <> (link "mailto:b@example.org" "" "b@example.org"))+    , "No" =:+        ".No ( hello , world ! )" =?>+        para "(hello, world!)"+    , "empty Pa with closing punctuation" =:+        ".Pa ) z" =?>+        para (spanWith (cls "Pa") "~" <> ")" <> space <> spanWith (mempty, ["Pa"], mempty) "z")+    , "delimiters" =:+        ".Sy ( hello world )" =?>+        para (mconcat ["(", strong "hello world", ")"])+    , "multiple" =:+        ".Sy hello Em world" =?>+        para (strong "hello" <> space <> emph "world")+    ]+  , testGroup "Fl"+    [ "simple" =:+        ".Fl w" =?>+        para (codeWith (cls "Fl") "-w")+    , "multiple" =:+        ".Fl W all" =?>+        para (codeWith (cls "Fl") "-W" <> space <> codeWith (cls "Fl") "-all")+    , "empty with following macro" =:+        ".Fl Cm x" =?>+        para (codeWith (cls "Fl") "-" <> codeWith (cls "Cm") "x")+    , "enclosed with following macro" =:+        ".Pq Fl Cm x" =?>+        para ("(" <> codeWith (cls "Fl") "-" <> codeWith (cls "Cm") "x" <> ")")+    -- XXX this is a mandoc delta, the period is meant to land outside+    -- the enclosure. parseInline has learned how to defer eols but not+    -- closing delimiters+    , "enclosed with following delimiters" =:+        ".Pq Fl x ." =?>+        para ("(" <> codeWith (cls "Fl") "-x" <> ".)")+    , "following Ns" =:+        ".Fl W Ns Cm all" =?>+        para (codeWith (cls "Fl") "-W" <> codeWith (cls "Cm") "all")+    , "GNU" =:+        ".Fl -help" =?>+        para (codeWith (cls "Fl") "--help")+    , "GNU escaped" =:+        ".Fl \\-help" =?>+        para (codeWith (cls "Fl") "--help")+    , "GNU Fl Fl" =:+        ".Fl Fl help" =?>+        para (codeWith (cls "Fl") "--help")+    , "punctuation" =:+        ".Op Fl a | b" =?>+        para ("[" <> codeWith (cls "Fl") "-a" <> " | " <> codeWith (cls "Fl") "-b" <> "]")+    , "middle close paren" =:+        ".Fl a ) z" =?>+        para (codeWith (cls "Fl") "-a" <> ") " <> codeWith (cls "Fl") "-z")+    , "empty with close paren" =:+        ".Fl ) z" =?>+        para (codeWith (cls "Fl") "-" <> ") " <> codeWith (cls "Fl") "-z")+    , "empty with pipe" =:+        ".Fl | z" =?>+        para (codeWith (cls "Fl") "-" <> " | " <> codeWith (cls "Fl") "-z")+    , "empty with parens" =:+        ".Fl ( )" =?>+        para ("(" <> codeWith (cls "Fl") "-" <> ")")+    ]+  , testGroup "links"+    [ "basic" =:+        ".Lk href name" =?>+        para (link "href" "" "name")+    , "complicated" =:+        ".Lk , ( href name )" =?>+        para ("," <> space <> "(" <> link "href" "" "name" <> ")")+    , "unnamed" =:+        ".Lk href" =?>+        para (link "href" "" "href")+    ]+  , testGroup "Ns macro"+    [ "at the beginning of a macro line (mandoc delta)" =:+        T.unlines [".Op before", ".Ns Op after"] =?>+        para "[before] [after]"  -- mandoc: warning+    , "after a block closing macro" =:+        T.unlines [".Oo before", ".Oc Ns Op after"] =?>+        para "[before][after]"+    , "in the middle of a macro line" =:+        ".Oo before Oc Ns Op after" =?>+        para "[before][after]"+    , "before closing punctuation" =:+        ".Oo before Oc Ns : Op after" =?>+        para "[before]: [after]"  -- mandoc: warning+    , "after closing punctuation" =:+        ".Oo before Oc : Ns Op after" =?>+        para "[before]:[after]"+    , "at the end of a macro line" =:+        T.unlines [".Oo before Oc Ns", ".Op after"] =?>+        para "[before][after]"+    , "at the end of a partial-implicit line" =:+        T.unlines [".Op before Ns", ".Op after"] =?>+        para "[before][after]"+    , "normal words" =:+        ".No no Ns ns No no" =?>+        para ("nons" <> space <> "no")+    , "opening punctuation" =:+        ".No no Ns \"(\" ns No no" =?>+        para ("no(ns" <> space <> "no")+    , "closing punctuation" =:+        ".No no \"Ns\" ns \")\" No no" =?>+        para ("nons)" <> space <> "no")+    ]+  , testGroup "spacing mode"+    [ "all text" =:+        T.unlines ["a", ".Sm off", "b c", "d", ".Sm on", "e"] =?>+        para ("a b c d e")+    , "text around macro" =:+        T.unlines ["a", ".Sm off", ".Sy b c", ".Sm on", "d"] =?>+        para ("a" <> space <> strong "bc" <> space <> "d")+    , "mulitple macros" =:+        T.unlines ["a", ".Sm off", ".Sy b Em c", ".Sm on", "d"] =?>+        para ("a" <> space <> strong "b" <> emph "c" <> space <> "d")+    , "mulitple control lines" =:+        T.unlines ["a", ".Sm off", ".Sy b", ".Em c", ".Sm on", "d"] =?>+        para ("a" <> space <> strong "b" <> emph "c" <> space <> "d")+    , "mixed control and text lines" =:+        T.unlines ["a", ".Sm off", ".Sy b", "c", ".Em d", ".Sm on", "d"] =?>+        para ("a" <> space <> strong "b" <> "c" <> emph "d" <> space <> "d")+    , "delimiters" =:+        T.unlines [".Sm off", ".Em a ", ".Em [ b | c ]", ".Sm on"] =?>+        para (emph "a" <> "[" <> emph "b" <> "|" <> emph "c" <> "]")+    ]+  , testGroup "Ap macro"+    [ "in the middle of a macro line" =:+        ".Xr mandoc 1 Ap s" =?>+        para (spanWith (cls "Xr") "mandoc(1)" <> "'s")+    -- mandoc difference: the edge case of "Ap (" tested in this mandoc regress+    -- isn't present in any actual OpenBSD base system manuals, where Ap is+    -- only ever followed by a letter. Furthermore, "Ap" is generally uncommon+    -- compared to "Ns '" (e.g. ".Xr mandoc 1 Ns 's"). I'm accepting a+    -- difference from mandoc here because correctly suppressing space after+    -- the "(" here would require more refactoring than I feel like doing at+    -- time of writing.+    -- per mandoc, should be: para (strong "bold" <> "'(" <> strong "bold")+    , "with punctuation and called macro" =:+        ".Sy bold Ap ( \"Sy\" bold" =?>+        para (strong "bold" <> "'( " <> strong "bold")+    ]+  , testGroup "Pf macro"+    [ "closing punctuation" =:+        ".Pf . right ." =?>+        para ".right."+    , "double punctuation" =:+        ".Pf . . double" =?>+        para ".. double"+    , "opening punctuation" =:+        ".Pf ( left ." =?>+        para "(left."+    , "unparsed argument" =:+        ".Pf Ar Sy gument " =?>+        para ("Ar" <> strong "gument")+    ]+  , testGroup "text production"+    [ "early NetBSD versions" =:+        T.unlines [".Nx 0.9a", "and", ".Nx 9.4b"] =?>+        para "NetBSD 0.9A and NetBSD 9.4b"+    , "with Ns" =:+        ".Ox Ns -specific" =?>+        para "OpenBSD-specific"+    , "with punctuation" =:+        ".Fx ," =?>+        para "FreeBSD,"+    , "with argument and punctuation" =:+        ".Fx 12.0 ." =?>+        para "FreeBSD 12.0."+    , "BSD alone" =:+        ".Bx ." =?>+        para "BSD."+    , "BSD with macro" =:+        ".Bx No rocks" =?>+        para "BSD rocks"+    , "BSD with version" =:+        ".Bx 4.4 ," =?>+        para "4.4BSD,"+    , "BSD with variant" =:+        ".Bx 4.3 tahoe !" =?>+        para "4.3BSD-Tahoe!"+    ]+  , testGroup "inline punctuation"+    [ testGroup "leading punctuation"+      [ "open paren"           =: ".Em ( b"     =?> para ("(" <> emph "b")+      , "open square bracket"  =: ".Em \"[\" b" =?> para ("[" <> emph "b")+      , "pipe"                 =: ".Em | b"     =?> para ("|" <> space <> emph "b")+      , "period"               =: ".Em . b"     =?> para ("." <> space <> emph "b")+      , "comma"                =: ".Em , b"     =?> para ("," <> space <> emph "b")+      , "semicolon"            =: ".Em ; b"     =?> para (";" <> space <> emph "b")+      , "colon"                =: ".Em : b"     =?> para (":" <> space <> emph "b")+      , "question mark"        =: ".Em ? b"     =?> para ("?" <> space <> emph "b")+      , "exclamation"          =: ".Em ! b"     =?> para ("!" <> space <> emph "b")+      , "close paren"          =: ".Em ) b"     =?> para (")" <> space <> emph "b")+      , "close square bracket" =: ".Em \"]\" b" =?> para ("]" <> space <> emph "b")+      ]+    , testGroup "trailing punctuation"+      [ "open paren"           =: ".Em a ("     =?> para (emph "a" <> space <> "(")+      , "open square bracket"  =: ".Em a ["     =?> para (emph "a" <> space <> "[")+      , "pipe"                 =: ".Em a |"     =?> para (emph "a" <> space <> "|")+      , "period"               =: ".Em a ."     =?> para (emph "a" <> ".")+      , "comma"                =: ".Em a ,"     =?> para (emph "a" <> ",")+      , "semicolon"            =: ".Em a ;"     =?> para (emph "a" <> ";")+      , "colon"                =: ".Em a :"     =?> para (emph "a" <> ":")+      , "question mark"        =: ".Em a ?"     =?> para (emph "a" <> "?")+      , "exclamation"          =: ".Em a !"     =?> para (emph "a" <> "!")+      , "close parens"         =: ".Em a \")\"" =?> para (emph "a" <> ")")+      , "close square bracket" =: ".Em a ]"     =?> para (emph "a" <> "]")+      ]+    , testGroup "middle punctuation"+      [ "open paren"           =: ".Em a ( b"     =?> para (mconcat [emph "a", space, "(", emph "b"])+      , "open square bracket"  =: ".Em a [ b"     =?> para (mconcat [emph "a", space, "[", emph "b"])+      , "pipe"                 =: ".Em a \"|\" b" =?> para (mconcat [emph "a", space, "|", space, emph "b"])+      , "period"               =: ".Em a . b"     =?> para (mconcat [emph "a", ".", space, emph "b"])+      , "comma"                =: ".Em a , b"     =?> para (mconcat [emph "a", ",", space, emph "b"])+      , "semicolon"            =: ".Em a ; b"     =?> para (mconcat [emph "a", ";", space, emph "b"])+      , "colon"                =: ".Em a \":\" b" =?> para (mconcat [emph "a", ":", space, emph "b"])+      , "question mark"        =: ".Em a ? b"     =?> para (mconcat [emph "a", "?", space, emph "b"])+      , "exclamation"          =: ".Em a ! b"     =?> para (mconcat [emph "a", "!", space, emph "b"])+      , "close paren"          =: ".Em a ) b"     =?> para (mconcat [emph "a", ")", space, emph "b"])+      , "close square bracket" =: ".Em a ] b"     =?> para (mconcat [emph "a", "]", space, emph "b"])+      ]+    ]+  ]
test/Tests/Readers/ODT.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Tests.Readers.ODT-   Copyright   : © 2015-2023 John MacFarlane+   Copyright   : © 2015-2024 John MacFarlane                    2015 Martin Linnemann    License     : GNU GPL, version 2 or above @@ -167,6 +167,7 @@ namesOfTestsComparingToNative   = [ "blockquote"                                   , "image"                                   , "imageIndex"+                                  , "imageRelative"                                   , "imageWithCaption"                                   , "inlinedCode"                                   , "listContinueNumbering"@@ -175,15 +176,20 @@                                   , "orderedListRoman"                                   , "orderedListSimple"                                   , "orderedListHeader"+                                  , "preformattedText"+                                  , "preformattedTextParentStyle"                                   , "referenceToChapter"                                   , "referenceToListItem"                                   , "referenceToText"                                   , "simpleTable"                                   , "simpleTableWithCaption"+                                  , "simpleTableWithHeader"+                                  , "simpleTableWithMultipleHeaderRows"                                   , "tab" --                                , "table"                                   , "textMixedStyles"                                   , "tableWithContents"+                                  , "tableWithSpans"                                   , "unicode"                                   , "unorderedList"                                   , "unorderedListHeader"
test/Tests/Readers/Org.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Tests.Shared-   Copyright   : © 2014-2023 Albert Krewinkel+   Copyright   : © 2014-2024 Albert Krewinkel    License     : GNU GPL, version 2 or above -   Maintainer  : Albert Krewinkel <albert@zeitkraut.de>+   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>    Stability   : alpha    Portability : portable 
test/Tests/Readers/Org/Block.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Tests.Readers.Org.Block-   Copyright   : © 2014-2023 Albert Krewinkel+   Copyright   : © 2014-2024 Albert Krewinkel    License     : GNU GPL, version 2 or above -   Maintainer  : Albert Krewinkel <albert@zeitkraut.de>+   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>    Stability   : alpha    Portability : portable @@ -43,7 +43,7 @@       T.unlines [ ": echo hello"                 , ": echo dear tester"                 ] =?>-      codeBlockWith ("", ["example"], []) "echo hello\necho dear tester\n"+      codeBlockWith ("", [], []) "echo hello\necho dear tester\n"    , "Example block surrounded by text" =:       T.unlines [ "Greetings"@@ -52,7 +52,7 @@                 , "Bye"                 ] =?>       mconcat [ para "Greetings"-              , codeBlockWith ("", ["example"], [])+              , codeBlockWith ("", [], [])                               "echo hello\necho dear tester\n"               , para "Bye"               ]@@ -169,26 +169,24 @@       rawBlock "html" "<samp>Hello, World!</samp>\n"      , "LaTeX fragment" =:-      T.unlines [ "\\begin{equation}"-                , "X_i = \\begin{cases}"-                , "      G_{\\alpha(i)} & \\text{if }\\alpha(i-1) = \\alpha(i)\\\\"-                , "      C_{\\alpha(i)} & \\text{otherwise}"-                , "      \\end{cases}"-                , "\\end{equation}"-                ] =?>-      rawBlock "latex"-      (T.unlines [ "\\begin{equation}"-               , "X_i = \\begin{cases}"-               , "      G_{\\alpha(i)} & \\text{if }\\alpha(i-1) =" <>-                 " \\alpha(i)\\\\"-               , "      C_{\\alpha(i)} & \\text{otherwise}"-               , "      \\end{cases}"-               , "\\end{equation}"-               ])+      "\\begin{equation}\n\+      \X_i = \\begin{cases}\n\+      \      G_{\\alpha(i)} & \\text{if }\\alpha(i-1) = \\alpha(i)\\\\\n\+      \      C_{\\alpha(i)} & \\text{otherwise}\n\+      \      \\end{cases}\n\+      \\\end{equation}"+      =?>+      para (rawInline "latex"+             "\\begin{equation}\n\+             \X_i = \\begin{cases}\n\+             \      G_{\\alpha(i)} & \\text{if }\\alpha(i-1) = \\alpha(i)\\\\\n\+             \      C_{\\alpha(i)} & \\text{otherwise}\n\+             \      \\end{cases}\n\+             \\\end{equation}")      , "One-line LaTeX fragment" =:       "\\begin{equation} 2 + 3 \\end{equation}" =?>-      rawBlock "latex" "\\begin{equation} 2 + 3 \\end{equation}\n"+      para (rawInline "latex" "\\begin{equation} 2 + 3 \\end{equation}")      , "LaTeX fragment with more arguments" =:       T.unlines [ "\\begin{tikzcd}[ampersand replacement=\\&]"
test/Tests/Readers/Org/Block/CodeBlock.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Tests.Readers.Org.Block.CodeBlock-   Copyright   : © 2014-2023 Albert Krewinkel+   Copyright   : © 2014-2024 Albert Krewinkel    License     : GNU GPL, version 2 or above -   Maintainer  : Albert Krewinkel <albert@zeitkraut.de>+   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>    Stability   : alpha    Portability : portable @@ -99,7 +99,7 @@            results' = "65\n"        in codeBlockWith ("", classes, params) code'           <>-          codeBlockWith ("", ["example"], []) results'+          codeBlockWith ("", [], []) results'    , "Source block with results and :exports code" =:        T.unlines [ "#+begin_src emacs-lisp :exports code"@@ -126,7 +126,7 @@                  , "#+RESULTS:"                  , ": 65" ] =?>        let results' = "65\n"-       in codeBlockWith ("", ["example"], []) results'+       in codeBlockWith ("", [], []) results'    , "Source block with results and :exports none" =:        T.unlines [ "#+begin_src emacs-lisp :exports none"@@ -171,7 +171,7 @@                  , "a rule."                  , "#+eND_exAMPle"                  ] =?>-       codeBlockWith ("", ["example"], [])+       codeBlockWith ("", [], [])                      "A chosen representation of\na rule.\n"    , "Code block with caption" =:
test/Tests/Readers/Org/Block/Figure.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Tests.Readers.Org.Block.Figure-   Copyright   : © 2014-2023 Albert Krewinkel+   Copyright   : © 2014-2024 Albert Krewinkel    License     : GNU GPL, version 2 or above -   Maintainer  : Albert Krewinkel <albert@zeitkraut.de>+   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>    Stability   : alpha    Portability : portable 
test/Tests/Readers/Org/Block/Header.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Tests.Readers.Org.Block.Header-   Copyright   : © 2014-2023 Albert Krewinkel+   Copyright   : © 2014-2024 Albert Krewinkel    License     : GNU GPL, version 2 or above -   Maintainer  : Albert Krewinkel <albert@zeitkraut.de>+   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>    Stability   : alpha    Portability : portable @@ -118,6 +118,13 @@         in headerWith ("compile", [], []) 1 (waiting <> space <> "compile")         <> headerWith ("lunch", [], []) 1 (cancelled <> space <> "lunch")         <> headerWith ("todo-feature", [], []) 1 (done <> space <> "todo-feature")++    , "Fast access TODO states" =:+        T.unlines [ "#+TODO: TODO(t) | DONE(d)"+                  , "* TODO test"+                  ] =?>+        let todoSpan = spanWith ("", ["todo", "TODO"], []) "TODO"+        in headerWith ("test", [], []) 1 (todoSpan <> space <> "test")     ]    , "Tagged headers" =:
test/Tests/Readers/Org/Block/List.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Tests.Readers.Org.Block.Header-   Copyright   : © 2014-2023 Albert Krewinkel+   Copyright   : © 2014-2024 Albert Krewinkel    License     : GNU GPL, version 2 or above -   Maintainer  : Albert Krewinkel <albert@zeitkraut.de>+   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>    Stability   : alpha    Portability : portable 
test/Tests/Readers/Org/Block/Table.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Tests.Readers.Org.Block.Table-   Copyright   : © 2014-2023 Albert Krewinkel+   Copyright   : © 2014-2024 Albert Krewinkel    License     : GNU GPL, version 2 or above -   Maintainer  : Albert Krewinkel <albert@zeitkraut.de>+   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>    Stability   : alpha    Portability : portable 
test/Tests/Readers/Org/Directive.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Tests.Readers.Org.Directive-   Copyright   : © 2014-2023 Albert Krewinkel+   Copyright   : © 2014-2024 Albert Krewinkel    License     : GNU GPL, version 2 or above -   Maintainer  : Albert Krewinkel <albert@zeitkraut.de>+   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>    Stability   : alpha    Portability : portable @@ -188,7 +188,7 @@           T.unlines [ "#+OPTIONS: tex:t"                     , "Hello \\emph{Name}"                     ] =?>-          para ("Hello" <> space <> emph "Name")+          para ("Hello" <> space <> rawInline "latex" "\\emph{Name}")          , "Alpha" =:           T.unlines [ "#+OPTIONS: tex:t"@@ -197,15 +197,15 @@           para "α"          , "equation environment" =:-          T.unlines [ "#+OPTIONS: tex:t"-                    , "\\begin{equation}"-                    , "f(x) = x^2"-                    , "\\end{equation}"-                    ] =?>-          rawBlock "latex" (T.unlines [ "\\begin{equation}"-                                      , "f(x) = x^2"-                                      , "\\end{equation}"-                                      ])+          "#+OPTIONS: tex:t\n\+          \\\begin{equation}\n\+          \f(x) = x^2\n\+          \\\end{equation}"+          =?>+          para (rawInline "latex"+                 "\\begin{equation}\n\+                 \f(x) = x^2\n\+                 \\\end{equation}")         ]        , testGroup "Ignore LaTeX fragments"@@ -227,7 +227,7 @@                     , "f(x) = x^2"                     , "\\end{equation}"                     ] =?>-          (mempty :: Blocks)+          (para mempty)         ]        , testGroup "Verbatim LaTeX"
test/Tests/Readers/Org/Inline.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Tests.Readers.Org.Inline-   Copyright   : © 2014-2023 Albert Krewinkel+   Copyright   : © 2014-2024 Albert Krewinkel    License     : GNU GPL, version 2 or above -   Maintainer  : Albert Krewinkel <albert@zeitkraut.de>+   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>    Stability   : alpha    Portability : portable @@ -88,6 +88,10 @@       "2^{n-1}" =?>       para (str "2" <> superscript "n-1") +  , "Superscript-like, but not after string" =:+      "a ^caret" =?>+      para "a ^caret"+   , "Subscript simple expression" =:       "a_n" =?>       para (str "a" <> subscript "n")@@ -96,6 +100,14 @@       "a_{n+1}" =?>       para (str "a" <> subscript "n+1") +  , "Subscript-like, but not after string" =:+      "_underscore" =?>+      para "_underscore"++  , "Subscript takes precedence before underline" =:+      "text_subscript_" =?>+      para (str "text" <> subscript "subscript" <> str "_")+   , "Linebreak" =:       "line \\\\ \nbreak" =?>       para ("line" <> linebreak <> "break")@@ -342,7 +354,7 @@    , "Inline LaTeX command with spaces" =:       "\\emph{Emphasis mine}" =?>-      para (emph "Emphasis mine")+      para (rawInline "latex" "\\emph{Emphasis mine}")    , "Inline math symbols" =:       "\\tau \\oplus \\alpha" =?>
test/Tests/Readers/Org/Inline/Citation.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Tests.Readers.Org.Inline.Citation-   Copyright   : © 2014-2023 Albert Krewinkel+   Copyright   : © 2014-2024 Albert Krewinkel    License     : GNU GPL, version 2 or above -   Maintainer  : Albert Krewinkel <albert@zeitkraut.de>+   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>    Stability   : alpha    Portability : portable @@ -201,13 +201,6 @@    , "LaTeX citation" =:     "\\cite{Coffee}" =?>-    let citation = Citation-                   { citationId = "Coffee"-                   , citationPrefix = []-                   , citationSuffix = []-                   , citationMode = NormalCitation-                   , citationNoteNum = 0-                   , citationHash = 0}-    in (para . cite [citation] $ rawInline "latex" "\\cite{Coffee}")+      para (rawInline "latex" "\\cite{Coffee}")    ]
test/Tests/Readers/Org/Inline/Note.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Tests.Readers.Org.Inline.Note-   Copyright   : © 2014-2023 Albert Krewinkel+   Copyright   : © 2014-2024 Albert Krewinkel    License     : GNU GPL, version 2 or above -   Maintainer  : Albert Krewinkel <albert@zeitkraut.de>+   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>    Stability   : alpha    Portability : portable 
test/Tests/Readers/Org/Inline/Smart.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Tests.Readers.Org.Inline.Smart-   Copyright   : © 2014-2023 Albert Krewinkel+   Copyright   : © 2014-2024 Albert Krewinkel    License     : GNU GPL, version 2 or above -   Maintainer  : Albert Krewinkel <albert@zeitkraut.de>+   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>    Stability   : alpha    Portability : portable @@ -46,6 +46,10 @@   , test orgSmart "Dashes are allowed at the borders of emphasis'"     ("/foo---/" =?>      para (emph "foo—"))++  , test orgSmart "Support for shy (soft) hyphen"+    ("Ur\\-instinkt" =?>+     para "Ur\173instinkt")    , test orgSmart "Single quotes can be followed by emphasized text"     ("Singles on the '/meat market/'" =?>
test/Tests/Readers/Org/Meta.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Tests.Readers.Org.Meta-   Copyright   : © 2014-2023 Albert Krewinkel+   Copyright   : © 2014-2024 Albert Krewinkel    License     : GNU GPL, version 2 or above -   Maintainer  : Albert Krewinkel <albert@zeitkraut.de>+   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>    Stability   : alpha    Portability : portable 
test/Tests/Readers/Org/Shared.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Tests.Readers.Org.Shared-   Copyright   : © 2014-2023 Albert Krewinkel+   Copyright   : © 2014-2024 Albert Krewinkel    License     : GNU GPL, version 2 or above -   Maintainer  : Albert Krewinkel <albert@zeitkraut.de>+   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>    Stability   : alpha    Portability : portable 
+ test/Tests/Readers/Pod.hs view
@@ -0,0 +1,187 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+   Module      : Tests.Readers.Pod+   Copyright   : © 2024 Evan Silberman+   License     : GNU GPL, version 2 or above++   Maintainer  : +   Stability   : alpha+   Portability : portable++Tests for the Pod reader.+-}++module Tests.Readers.Pod (tests) where++import Data.Text (Text, pack)+import Test.Tasty+import Test.Tasty.HUnit (HasCallStack)+import Tests.Helpers+import Text.Pandoc+import Text.Pandoc.Arbitrary ()+import Text.Pandoc.Builder++pod :: Text -> Pandoc+pod t = (purely $ readPod def) ("=pod\n\n" <> t <> "\n\n=cut\n")++manLink :: Text -> Maybe Text -> Inlines -> Inlines+manLink nm Nothing = linkWith (mempty, mempty, [("manual", nm)]) "" ""+manLink nm (Just sc) = linkWith (mempty, mempty, [("manual", nm), ("section", sc)]) "" ""++bogusEntity :: String -> TestTree+bogusEntity t = t =: "E<" <> pack t <> ">" =?> para ("E<" <> str (pack t) <> ">")++infix 4 =:+(=:) :: (ToString c, HasCallStack)+     => String -> (Text, c) -> TestTree+(=:) = test pod++tests :: [TestTree]+tests = [+  testGroup "inlines"+    [ "code with nested inlines" =:+        "C</I<A> (*PRUNE) I<B>/>" =?>+        para (code "/A (*PRUNE) B/")+    , "compact in compact" =:+        "I<B<strong> emphasis>" =?>+        para (emph $ (strong "strong") <> " emphasis")+    , "expanded in compact" =:+        "I<B<< strong >> emphasis>" =?>+        para (emph $ (strong "strong") <> " emphasis")+    , "compact in expanded" =:+        "I<<< B<strong> emphasis >>>" =?>+        para (emph $ (strong "strong") <> " emphasis")+    , "expanded in expanded" =:+        "I<<< B<<< strong >>> emphasis >>>" =?>+        para (emph $ (strong "strong") <> " emphasis")+    ]+  , testGroup "links"+    [ testGroup "compact"+      [ "URL" =:+          "L<https://example.org>" =?>+          para (link "https://example.org" "" "https://example.org")+      , "URL with link text" =:+          "L<link|https://example.org/index.html>" =?>+          para (link "https://example.org/index.html" "" "link")+      , "perl manual" =:+          "L<Foo::Bar>" =?>+          para (manLink "Foo::Bar" Nothing "Foo::Bar")+      , "manual with quoted section" =:+          "L<crontab(5)/\"DESCRIPTION\">" =?>+          para (manLink "crontab(5)" (Just "DESCRIPTION") (doubleQuoted "DESCRIPTION" <> " in crontab(5)"))+      , "manual with section and formatted link text" =:+          "L<B<< extravagant >> link|HTTP::Simple/is_info>" =?>+          para (manLink "HTTP::Simple" (Just "is_info") (strong "extravagant" <> " link"))+      , "internal link" =:+          "L</section name>" =?>+          para (link "#section-name" "" (doubleQuoted "section name"))+      , "internal link with formatting" =:+          "L</The C<pod2html> command>" =?>+          para (link "#the-pod2html-command" "" (doubleQuoted ("The " <> code "pod2html" <> " command")))+      , "link with angle bracket" =:+          "L<m<>" =?>+          para (manLink "m<" Nothing "m<")+      , "empty name" =:+          "L<|https://example.org>" =?>+          para (link "https://example.org" "" mempty)+      ]+    , testGroup "expanded"+      [ "URL" =:+          "L<< https://example.org >>" =?>+          para (link "https://example.org" "" "https://example.org")+      , "URL with link text" =:+          "L<< link|https://example.org/index.html >>" =?>+          para (link "https://example.org/index.html" "" "link")+      , "perl manual" =:+          "L<<< Foo::Bar >>>" =?>+          para (manLink "Foo::Bar" Nothing "Foo::Bar")+      , "manual with quoted section" =:+          "L<< crontab(5)/\"DESCRIPTION\"     >>" =?>+          para (manLink "crontab(5)" (Just "DESCRIPTION") (doubleQuoted "DESCRIPTION" <> " in crontab(5)"))+      , "manual with section and formatted link text" =:+          "L<< B<< extravagant >> link|HTTP::Simple/is_info >>" =?>+          para (manLink "HTTP::Simple" (Just "is_info") (strong "extravagant" <> " link"))+      , "internal link" =:+          "L<<   /section name  >>" =?>+          para (link "#section-name" "" (doubleQuoted "section name"))+      , "internal link with formatting" =:+          "L<<<<<          /The C<pod2html> command    >>>>>" =?>+          para (link "#the-pod2html-command" "" (doubleQuoted ("The " <> code "pod2html" <> " command")))+      , "link with angle bracket" =:+          "L<< m< >>" =?>+          para (manLink "m<" Nothing "m<")+      , "empty name" =:+          "L<< |https://example.org >>" =?>+          para (link "https://example.org" "" mempty)+      ]+    ]+  , testGroup "entities"+      [ testGroup "required"+        [ "quot" =:+            "E<quot>" =?>+          para "\""+        , "amp" =:+            "E<amp>" =?>+            para "&"+        , "apos" =:+            "E<apos>" =?>+            para "'"+        , "lt" =:+            "E<lt>" =?>+            para "<"+        , "gt" =:+            "E<gt>" =?>+            para ">"+        , "sol" =:+            "E<sol>" =?>+            para "/"+        , "verbar" =:+            "E<verbar>" =?>+            para "|"+        , "lchevron" =:+            "E<lchevron>" =?>+            para "«"+        , "rchevron" =:+            "E<rchevron>" =?>+            para "»"+        ]+      , testGroup "html"+        [ "trade" =:+           "E<trade>" =?>+           para "™"+        , "ccaron" =:+           "E<ccaron>" =?>+           para "č"+        , "cent" =:+           "E<cent>" =?>+           para "¢"+        ]+      , testGroup "numeric"+        [ "decimal" =:+            "E<162>" =?>+            para "¢"+        , "octal" =:+            "E<0242>" =?>+            para "¢"+        , "hexadecimal" =:+            "E<0xA2>" =?>+            para "¢"+        , "hexadecimal variant" =:+            "E<0x00A2>" =?>+            para "¢"+        , "actually decimal" =:+            "E<099>" =?>+            para "c"+        ]+      , testGroup "bogus"+        [ bogusEntity "0XA2"+        , bogusEntity "not a real entity"+        , bogusEntity "162 1"+        , bogusEntity "99 bottles of beer"+        , bogusEntity "0xhh"+        , bogusEntity "077x"+        , bogusEntity "0x63 skidoo"+        , bogusEntity "trade;"+        ]+      ]+    ]
+ test/Tests/Readers/Pptx.hs view
@@ -0,0 +1,48 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+   Module      : Tests.Readers.Pptx+   Copyright   : © 2025 Anton Antic+   License     : GNU GPL, version 2 or above++   Maintainer  : Anton Antic <anton@everworker.ai>+   Stability   : alpha+   Portability : portable++Tests for the PPTX reader.+-}+module Tests.Readers.Pptx (tests) where++import qualified Data.ByteString as BS+import qualified Data.ByteString.Lazy as B+import Test.Tasty+import Test.Tasty.Golden.Advanced+import Tests.Helpers+import Text.Pandoc+import Text.Pandoc.UTF8 as UTF8++defopts :: ReaderOptions+defopts = def{ readerExtensions = getDefaultExtensions "pptx" }++testCompare :: String -> FilePath -> FilePath -> TestTree+testCompare = testCompareWithOpts defopts++testCompareWithOpts :: ReaderOptions -> String -> FilePath -> FilePath -> TestTree+testCompareWithOpts opts testName pptxFP nativeFP =+  goldenTest+  testName+  (do nf <- UTF8.toText <$> BS.readFile nativeFP+      runIOorExplode (readNative def nf))+  (do df <- B.readFile pptxFP+      runIOorExplode (readPptx opts df))+  (nativeDiff nativeFP)+  (\a -> runIOorExplode (writeNative def{ writerTemplate = Just mempty} a)+            >>= BS.writeFile nativeFP . UTF8.fromText)++tests :: [TestTree]+tests = [ testGroup "basic"+          [ testCompare+            "text extraction"+            "pptx-reader/basic.pptx"+            "pptx-reader/basic.native"+          ]+        ]
test/Tests/Readers/RST.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE ScopedTypeVariables #-} {- |    Module      : Tests.Readers.RST-   Copyright   : © 2006-2023 John MacFarlane+   Copyright   : © 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -50,13 +50,13 @@              , "  on two lines" ]              =?>               doc (para "para" <>-                   definitionList [ (str "Hostname", [para "media08"])-                                  , (text "IP address", [para "10.0.0.19"])-                                  , (str "Size", [para "3ru"])-                                  , (str "Version", [para "1"])-                                  , (str "Indentation", [para "Since the field marker may be quite long, the second\nand subsequent lines of the field body do not have to line up\nwith the first line, but they must be indented relative to the\nfield name marker, and they must line up with each other."])-                                  , (text "Parameter i", [para "integer"])-                                  , (str "Final", [para "item\non two lines"])+                   definitionList [ (str "Hostname", [plain "media08"])+                                  , (text "IP address", [plain "10.0.0.19"])+                                  , (str "Size", [plain "3ru"])+                                  , (str "Version", [plain "1"])+                                  , (str "Indentation", [plain "Since the field marker may be quite long, the second\nand subsequent lines of the field body do not have to line up\nwith the first line, but they must be indented relative to the\nfield name marker, and they must line up with each other."])+                                  , (text "Parameter i", [plain "integer"])+                                  , (str "Final", [plain "item\non two lines"])                                   ])           , "metadata" =: T.unlines              [ "====="@@ -69,7 +69,7 @@              , ":Version: 1"              ]              =?>-              setMeta "version" (para "1") (setMeta "title" ("Title" :: Inlines)+              setMeta "version" (str "1") (setMeta "title" ("Title" :: Inlines)                  $ setMeta "subtitle" ("Subtitle" :: Inlines)                  $ doc mempty)           , "with inline markup" =: T.unlines@@ -87,10 +87,10 @@              ]              =?>               setMeta "date" (str "today") (doc-                 $ definitionList [ (emph "one", [para "emphasis"])-                                  , (link "http://example.com" "" "two", [para "reference"])-                                  , (link "http://example.org" "" "three", [para "another one"])-                                  , (code "four", [para "literal"])+                 $ definitionList [ (emph "one", [plain "emphasis"])+                                  , (link "http://example.com" "" "two", [plain "reference"])+                                  , (link "http://example.org" "" "three", [plain "another one"])+                                  , (code "four", [plain "literal"])                                   ])           ]         , "URLs with following punctuation" =:
test/Tests/Readers/RTF.hs view
@@ -1,6 +1,6 @@ {- |    Module      : Tests.Readers.RTF-   Copyright   : © 2021-2023 John MacFarlane+   Copyright   : © 2021-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : jgm@berkeley.edu
test/Tests/Readers/Txt2Tags.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Tests.Readers.Txt2Tags-   Copyright   : © 2014-2023 John MacFarlane,+   Copyright   : © 2014-2024 John MacFarlane,                  © 2014 Matthew Pickering    License     : GNU GPL, version 2 or above 
+ test/Tests/Readers/Xlsx.hs view
@@ -0,0 +1,48 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+   Module      : Tests.Readers.Xlsx+   Copyright   : © 2025 Anton Antic+   License     : GNU GPL, version 2 or above++   Maintainer  : Anton Antic <anton@everworker.ai>+   Stability   : alpha+   Portability : portable++Tests for the XLSX reader.+-}+module Tests.Readers.Xlsx (tests) where++import qualified Data.ByteString as BS+import qualified Data.ByteString.Lazy as B+import Test.Tasty+import Test.Tasty.Golden.Advanced+import Tests.Helpers+import Text.Pandoc+import Text.Pandoc.UTF8 as UTF8++defopts :: ReaderOptions+defopts = def{ readerExtensions = getDefaultExtensions "xlsx" }++testCompare :: String -> FilePath -> FilePath -> TestTree+testCompare = testCompareWithOpts defopts++testCompareWithOpts :: ReaderOptions -> String -> FilePath -> FilePath -> TestTree+testCompareWithOpts opts testName xlsxFP nativeFP =+  goldenTest+  testName+  (do nf <- UTF8.toText <$> BS.readFile nativeFP+      runIOorExplode (readNative def nf))+  (do df <- B.readFile xlsxFP+      runIOorExplode (readXlsx opts df))+  (nativeDiff nativeFP)+  (\a -> runIOorExplode (writeNative def{ writerTemplate = Just mempty} a)+            >>= BS.writeFile nativeFP . UTF8.fromText)++tests :: [TestTree]+tests = [ testGroup "basic"+          [ testCompare+            "sheet extraction"+            "xlsx-reader/basic.xlsx"+            "xlsx-reader/basic.native"+          ]+        ]
test/Tests/Shared.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Tests.Shared-   Copyright   : © 2006-2023 John MacFarlane+   Copyright   : © 2006-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley@edu>@@ -51,7 +51,8 @@    in d' == makeSections False Nothing d'  givesTOC :: String -> (Blocks, Blocks) -> TestTree-givesTOC desc (blocks, toc) = test (toTableOfContents def) desc (toList blocks, head . toList $ toc)+givesTOC desc (blocks, toc) =+  test (singleton . toTableOfContents def) desc (toList blocks, toc)  linkId :: T.Text -> T.Text -> T.Text -> Inlines -> Inlines linkId lId = linkWith (lId,[],[])
test/Tests/Writers/AsciiDoc.hs view
@@ -36,7 +36,7 @@                  "__foo__bar"           , testAsciidoc "emph quoted" $                para (doubleQuoted (emph (text "foo"))) =?>-                 "``__foo__''"+                 "``_foo_''"           , testAsciidoc "strong word before" $                para (text "foo" <> strong (text "bar")) =?>                  "foo**bar**"@@ -45,7 +45,7 @@                  "**foo**bar"           , testAsciidoc "strong quoted" $                para (singleQuoted (strong (text "foo"))) =?>-                 "`**foo**'"+                 "`*foo*'"           ]         , testGroup "blocks"           [ testAsciidoc "code block without line numbers" $@@ -61,6 +61,19 @@                                            , "----"                                            , "foo"                                            , "----"+                                           ]+          , testAsciidoc "sidebar block" $+               divWith ("sidebar_id", ["sidebar"], [])+                                           (divWith ("", ["title"], [])+                                           (plain "Sidebar Title")+                                           <> para "Sidebar paragraph"+                                           ) =?> unlines+                                           [ "[[sidebar_id]]"+                                           , "[SIDEBAR]"+                                           , ".Sidebar Title"+                                           , "****"+                                           , "Sidebar paragraph"+                                           , "****"                                            ]           ]         , testGroup "tables"
+ test/Tests/Writers/BBCode.hs view
@@ -0,0 +1,355 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeApplications #-}++module Tests.Writers.BBCode (tests) where++import Data.Maybe (isNothing)+import Data.Text as T+import Test.Tasty+import Test.Tasty.HUnit (HasCallStack)+import Test.Tasty.QuickCheck+import Tests.Helpers+import Text.Pandoc+import Text.Pandoc.Arbitrary ()+import Text.Pandoc.Builder+import Text.Pandoc.Shared (tshow)+import Text.Read (readMaybe)++bbcodeDefault+  , bbcodeSteam+  , bbcodePhpBB+  , bbcodeFluxBB+  , bbcodeHubzilla+  , bbcodeXenforo ::+    (ToPandoc a) => a -> Text+bbcodeDefault = purely (writeBBCode def) . toPandoc+bbcodeSteam = purely (writeBBCodeSteam def) . toPandoc+bbcodePhpBB = purely (writeBBCodePhpBB def) . toPandoc+bbcodeFluxBB = purely (writeBBCodeFluxBB def) . toPandoc+bbcodeHubzilla = purely (writeBBCodeHubzilla def) . toPandoc+bbcodeXenforo = purely (writeBBCodeXenforo def) . toPandoc++infix 4 =:, `steam`, `phpbb`, `fluxbb`, `hubzilla`, `xenforo`+(=:)+  , steam+  , phpbb+  , fluxbb+  , hubzilla+  , xenforo ::+    (ToString a, ToPandoc a, HasCallStack) =>+    String ->+    (a, Text) ->+    TestTree+(=:) = test bbcodeDefault+steam = test bbcodeSteam+phpbb = test bbcodePhpBB+fluxbb = test bbcodeFluxBB+hubzilla = test bbcodeHubzilla+xenforo = test bbcodeXenforo++spanClasses :: [Text] -> Inlines -> Inlines+spanClasses cls = spanWith ("", cls, [])++spanAttrs :: [(Text, Text)] -> Inlines -> Inlines+spanAttrs kvList = spanWith ("", [], kvList)++divClasses :: [Text] -> Blocks -> Blocks+divClasses cls = divWith ("", cls, [])++divAttrs :: [(Text, Text)] -> Blocks -> Blocks+divAttrs kvList = divWith ("", [], kvList)++tests :: [TestTree]+tests =+  [ testGroup+      "spans classes"+      [ "left" =: spanClasses ["left"] "foo" =?> "foo"+      , "center" =: spanClasses ["center"] "foo" =?> "foo"+      , "right" =: spanClasses ["right"] "foo" =?> "foo"+      , "spoiler" =: spanClasses ["spoiler"] "foo" =?> "foo"+      ]+  , testGroup+      "spans attributes"+      [ testProperty "incorrect size ignored" . property $ do+          n <- arbitrary @String+          let nInt = readMaybe @Int n+          let actual = bbcodeDefault (spanAttrs [("size", T.pack n)] "foo")+          pure $ isNothing nInt ==> actual === "foo"+      , testProperty "size<=0 ignored" . property $ do+          NonPositive n <- arbitrary @(NonPositive Int)+          let actual = bbcodeDefault (spanAttrs [("size", tshow n)] "foo")+          pure $ actual === "foo"+      , testProperty "size>0" . property $ do+          Positive n <- arbitrary @(Positive Int)+          let actual = bbcodeDefault (spanAttrs [("size", tshow n)] "foo")+          let expected = "[size=" <> tshow n <> "]" <> "foo[/size]"+          pure $ actual === expected+      , "size=20" =: spanAttrs [("size", "20")] "foo" =?> "[size=20]foo[/size]"+      , "color=#AAAAAA"+          =: spanAttrs [("color", "#AAAAAA")] "foo"+          =?> "[color=#AAAAAA]foo[/color]"+      , "spoiler ignored"+          =: spanAttrs [("spoiler", "name with spaces and ]brackets[]")] "foo"+          =?> "foo"+      ]+  , testGroup+      "divs classes"+      [ "left"+          =: divClasses ["left"] (para "foo")+          =?> "[left]foo[/left]"+      , "center"+          =: divClasses ["center"] (para "foo")+          =?> "[center]foo[/center]"+      , "right"+          =: divClasses ["right"] (para "foo")+          =?> "[right]foo[/right]"+      , "spoiler"+          =: divClasses ["spoiler"] (para "foo")+          =?> "[spoiler]foo[/spoiler]"+      ]+  , testGroup+      "divs attributes"+      [ testProperty "incorrect size ignored" . property $ do+          n <- arbitrary @String+          let nInt = readMaybe @Int n+          let actual = bbcodeDefault (divAttrs [("size", T.pack n)] $ para "foo")+          pure $ isNothing nInt ==> actual === "foo"+      , testProperty "size<=0 ignored" . property $ do+          NonPositive n <- arbitrary @(NonPositive Int)+          let actual = bbcodeDefault (divAttrs [("size", tshow n)] $ para "foo")+          pure $ actual === "foo"+      , testProperty "size>0" . property $ do+          Positive n <- arbitrary @(Positive Int)+          let actual = bbcodeDefault (divAttrs [("size", tshow n)] $ para "foo")+          let expected = "[size=" <> tshow n <> "]" <> "foo[/size]"+          pure $ actual === expected+      , "size=20"+          =: divAttrs [("size", "20")] (para "foo")+          =?> "[size=20]foo[/size]"+      , "color=#AAAAAA"+          =: divAttrs [("color", "#AAAAAA")] (para "foo")+          =?> "[color=#AAAAAA]foo[/color]"+      , "spoiler"+          =: divAttrs+            [("spoiler", "name with spaces and ]brackets[]")]+            (para "foo")+          =?> "[spoiler=name with spaces and brackets]foo[/spoiler]"+      ]+  , testGroup+      "default flavor"+      [ "link"+          =: link "https://example.com" "title" "label"+          =?> "[url=https://example.com]label[/url]"+      , "autolink"+          =: link "https://example.com" "title" "https://example.com"+          =?> "[url]https://example.com[/url]"+      , "email autolink"+          =: link+            "mailto:example@example.com"+            "title"+            "example@example.com"+          =?> "[email]example@example.com[/email]"+      , "named email"+          =: link "mailto:example@example.com" "title" "example email"+          =?> "[email=example@example.com]example email[/email]"+      , "h0" =: header 0 "heading 0" =?> "[u][b]heading 0[/b][/u]"+      , "h1" =: header 1 "heading 1" =?> "[u][b]heading 1[/b][/u]"+      , "h2" =: header 2 "heading 2" =?> "[b]heading 2[/b]"+      , "h3" =: header 3 "heading 3" =?> "[u]heading 3[/u]"+      , "h4" =: header 4 "heading 4" =?> "heading 4"+      , "h5" =: header 5 "heading 5" =?> "heading 5"+      ]+  , testGroup+      "steam"+      [ test bbcodeSteam "dename spoiler" $+          divAttrs [("spoiler", "bar")] (para "foo")+            =?> ("[spoiler]foo[/spoiler]" :: Text)+      , testProperty "ordered list styleless" . property $ do+          let listItems = [para "foo", para "bar", para "baz"]+          attrsRand <- (,,) <$> arbitrary <*> arbitrary <*> arbitrary+          let actual = bbcodeSteam $ orderedListWith attrsRand listItems+          let expected = "[olist]\n[*]foo\n[*]bar\n[*]baz\n[/olist]"+          pure $ actual === expected+      , "h0" `steam` header 0 "heading 0" =?> "[h1]heading 0[/h1]"+      , "h1" `steam` header 1 "heading 1" =?> "[h1]heading 1[/h1]"+      , "h2" `steam` header 2 "heading 2" =?> "[h2]heading 2[/h2]"+      , "h3" `steam` header 3 "heading 3" =?> "[h3]heading 3[/h3]"+      , "h4" `steam` header 4 "heading 4" =?> "[h3]heading 4[/h3]"+      , "code"+          `steam` codeWith ("id", ["haskell"], []) "map (2^) [1..5]"+          =?> "[noparse]map (2^) [1..5][/noparse]"+      ]+  , testGroup+      "phpBB"+      [ "image"+          `phpbb` imageWith+            ("id", [], [("width", "100")])+            "https://example.com"+            "title"+            "alt text"+          =?> "[img]https://example.com[/img]"+      ]+  , testGroup+      "FluxBB"+      [ "image"+          `fluxbb` imageWith+            ("id", [], [("width", "100")])+            "https://example.com"+            "title"+            "alt text"+          =?> "[img=alt text]https://example.com[/img]"+      , testProperty "ordered list" . property $ do+          let listItems = [para "foo", para "bar", para "baz"]+          attrsRand <- (,,) <$> arbitrary <*> arbitrary <*> arbitrary+          let actual = bbcodeFluxBB $ orderedListWith attrsRand listItems+          let opening = case attrsRand of+                (_, LowerAlpha, _) -> "[list=a]"+                (_, UpperAlpha, _) -> "[list=a]"+                _ -> "[list=1]"+          let expected = opening <> "\n[*]foo\n[*]bar\n[*]baz\n[/list]"+          pure $ actual === expected+      , "ulist > BlockQuote not rendered"+          `fluxbb` bulletList [blockQuote (para "foo") <> para "bar"]+          =?> "[list]\n[*]bar\n[/list]"+      , "code block"+          `fluxbb` codeBlockWith+            ("id", ["haskell"], [])+            ( T.intercalate "\n" $+                [ "vals ="+                , "  take 10"+                , "    . filter (\\x -> (x - 5) `mod` 3 == 0)"+                , "    $ map (2 ^) [1 ..]"+                ]+            )+          =?> T.intercalate+            "\n"+            [ "[code]vals ="+            , "  take 10"+            , "    . filter (\\x -> (x - 5) `mod` 3 == 0)"+            , "    $ map (2 ^) [1 ..]"+            , "[/code]"+            ]+      ]+  , testGroup+      "Hubzilla"+      [ "unordered list"+          `hubzilla` bulletList [para "foo", para "bar", para "baz"]+          =?> "[ul]\n[*]foo\n[*]bar\n[*]baz\n[/ul]"+      , testProperty "ordered list" . property $ do+          let listItems = [para "foo", para "bar", para "baz"]+          attrsRand <- (,,) <$> arbitrary <*> arbitrary <*> arbitrary+          let actual = bbcodeHubzilla $ orderedListWith attrsRand listItems+          let (opening, closing) = case attrsRand of+                (_, Decimal, _) -> ("[list=1]", "[/list]")+                (_, DefaultStyle, _) -> ("[ol]", "[/ol]")+                (_, Example, _) -> ("[ol]", "[/ol]")+                (_, LowerAlpha, _) -> ("[list=a]", "[/list]")+                (_, UpperAlpha, _) -> ("[list=A]", "[/list]")+                (_, LowerRoman, _) -> ("[list=i]", "[/list]")+                (_, UpperRoman, _) -> ("[list=I]", "[/list]")+          let expected =+                opening <> "\n[*]foo\n[*]bar\n[*]baz\n" <> closing+          pure $ actual === expected+      , "definition list"+          `hubzilla` definitionList+            [ ("term_foo", [para "def_foo1", para "def_foo2"])+            , ("term_bar", [para "def_bar1", para "def_bar2"])+            , ("term_baz", [para "def_baz1", para "def_baz2"])+            ]+          =?> mconcat+            [ "[dl terms=\"b\"]\n"+            , "[*= term_foo]\ndef_foo1\ndef_foo2\n"+            , "[*= term_bar]\ndef_bar1\ndef_bar2\n"+            , "[*= term_baz]\ndef_baz1\ndef_baz2\n"+            , "[/dl]"+            ]+      , "h0" `hubzilla` header 0 "heading 0" =?> "[h1]heading 0[/h1]"+      , "h1" `hubzilla` header 1 "heading 1" =?> "[h1]heading 1[/h1]"+      , "h2" `hubzilla` header 2 "heading 2" =?> "[h2]heading 2[/h2]"+      , "h3" `hubzilla` header 3 "heading 3" =?> "[h3]heading 3[/h3]"+      , "h4" `hubzilla` header 4 "heading 4" =?> "[h4]heading 4[/h4]"+      , "h5" `hubzilla` header 5 "heading 5" =?> "[h5]heading 5[/h5]"+      , "h6" `hubzilla` header 6 "heading 6" =?> "[h6]heading 6[/h6]"+      , "h7" `hubzilla` header 7 "heading 7" =?> "[h6]heading 7[/h6]"+      , "link"+          `hubzilla` link "https://example.com" "title" "label"+          =?> "[url=https://example.com]label[/url]"+      , "autolink"+          `hubzilla` link "https://example.com" "title" "https://example.com"+          =?> "[url]https://example.com[/url]"+      , "email autolink"+          `hubzilla` link+            "mailto:example@example.com"+            "title"+            "example@example.com"+          =?> "[url=mailto:example@example.com]example@example.com[/url]"+      , "named email"+          `hubzilla` link "mailto:example@example.com" "title" "example email"+          =?> "[url=mailto:example@example.com]example email[/url]"+      , "inline code"+          `hubzilla` ( "inline code: "+                        <> codeWith ("id", ["haskell"], []) "map (2^) [1..5]"+                     )+          =?> "inline code: [code]map (2^) [1..5][/code]"+      , "font"+          `hubzilla` divAttrs [("font", "serif")] (para "foo")+          =?> "[font=serif]foo[/font]"+      ]+  , testGroup+      "xenForo"+      [ "unordered list"+          `xenforo` bulletList [para "foo", para "bar", para "baz"]+          =?> "[list]\n[*]foo\n[*]bar\n[*]baz\n[/list]"+      , testProperty "ordered list styleless" . property $ do+          let listItems = [para "foo", para "bar", para "baz"]+          attrsRand <- (,,) <$> arbitrary <*> arbitrary <*> arbitrary+          let actual = bbcodeXenforo $ orderedListWith attrsRand listItems+          let expected = "[list=1]\n[*]foo\n[*]bar\n[*]baz\n[/list]"+          pure $ actual === expected+      , "h0" `xenforo` header 0 "heading 0" =?> "[heading=1]heading 0[/heading]"+      , "h1" `xenforo` header 1 "heading 1" =?> "[heading=1]heading 1[/heading]"+      , "h2" `xenforo` header 2 "heading 2" =?> "[heading=2]heading 2[/heading]"+      , "h3" `xenforo` header 3 "heading 3" =?> "[heading=3]heading 3[/heading]"+      , "h4" `xenforo` header 4 "heading 4" =?> "[heading=4]heading 4[/heading]"+      , "link"+          `xenforo` link "https://example.com" "title" "label"+          =?> "[url=https://example.com]label[/url]"+      , "autolink"+          `xenforo` link "https://example.com" "title" "https://example.com"+          =?> "[url]https://example.com[/url]"+      , "email autolink"+          `xenforo` link+            "mailto:example@example.com"+            "title"+            "example@example.com"+          =?> "[email]example@example.com[/email]"+      , "named email"+          `xenforo` link "mailto:example@example.com" "title" "example email"+          =?> "[email=example@example.com]example email[/email]"+      , "inline code"+          `xenforo` ( "inline code: "+                        <> codeWith ("id", ["haskell"], []) "map (2^) [1..5]"+                    )+          =?> "inline code: [icode]map (2^) [1..5][/icode]"+      , "font"+          `xenforo` divAttrs [("font", "serif")] (para "foo")+          =?> "[font=serif]foo[/font]"+      , "inline spoiler"+          `xenforo` ("It was " <> spanClasses ["spoiler"] ("DNS") <> "!")+          =?> "It was [ispoiler]DNS[/ispoiler]!"+      , "image w=50% h=50%"+          `xenforo` imageWith+            ("", [], [("width", "50%"), ("height", "50%")])+            "https://example.com"+            "title text"+            "alt text"+          =?> "[img alt=\"alt text\" title=\"title text\" width=50%]https://example.com[/img]"+      , "image w=50 h=50"+          `xenforo` imageWith+            ("", [], [("width", "50"), ("height", "50")])+            "https://example.com"+            ""+            ""+          =?> "[img]https://example.com[/img]"+      ]+  ]
test/Tests/Writers/Docx.hs view
@@ -1,10 +1,18 @@+{-# LANGUAGE OverloadedStrings #-} module Tests.Writers.Docx (tests) where -import Text.Pandoc+import Codec.Archive.Zip (findEntryByPath, fromEntry, toArchive)+import qualified Data.ByteString.Lazy as BL+import Data.List (isInfixOf, isPrefixOf)+import qualified Data.Map as M+import Data.Text (Text)+import qualified Data.Text as Text+import qualified Data.Text.IO as T import Test.Tasty-import Tests.Writers.OOXML import Test.Tasty.HUnit-import Data.List (isPrefixOf)+import Tests.Writers.OOXML+import Text.Pandoc+import Text.XML.Light (QName(QName), findAttr, findElements, parseXMLDoc)  -- we add an extra check to make sure that we're not writing in the -- toplevel docx directory. We don't want to accidentally overwrite an@@ -98,6 +106,16 @@             "docx/definition_list.native"             "docx/golden/definition_list.docx"           , docxTest+            "task lists"+            def+            "docx/task_list.native"+            "docx/golden/task_list.docx"+          , docxTest+            "issue 9994"+            def+            "docx/lists_9994.native"+            "docx/golden/lists_9994.docx"+          , docxTest             "footnotes and endnotes"             def             "docx/notes.native"@@ -203,5 +221,157 @@             def             "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" }+              txt <- T.readFile "docx/inline_formatting.native"+              bs <- runIOorExplode $ do+                mblang <- toLang (Just (Text.pack "en-US") :: Maybe Text)+                maybe (return ()) setTranslations mblang+                setVerbosity ERROR+                readNative def txt >>= writeDocx opts+              let archive = toArchive bs+              entry <- case findEntryByPath "[Content_Types].xml" archive of+                Nothing -> assertFailure "Missing [Content_Types].xml in output docx"+                Just e -> return e+              doc <- case parseXMLDoc (fromEntry entry) of+                Nothing -> assertFailure "Failed to parse [Content_Types].xml"+                Just d -> return d+              let partNameAttr = QName "PartName" Nothing Nothing+              let overrideName = QName "Override" Nothing Nothing+              let overrides = findElements overrideName doc+              let hasBadOverride =+                    any (\el -> findAttr partNameAttr el == Just "/word/media/")+                        overrides+              assertBool "Found invalid /word/media/ Override in [Content_Types].xml"+                (not hasBadOverride)+          , testCase "language from reference docx is preserved" $ do+              -- First, verify that the german-reference.docx actually has de-DE+              refBs <- BL.readFile "docx/german-reference.docx"+              let refArchive = toArchive refBs+              refEntry <- case findEntryByPath "word/styles.xml" refArchive of+                Nothing -> assertFailure "Missing word/styles.xml in german-reference.docx"+                Just e -> return e+              let refStylesXml = show (fromEntry refEntry)+              let getLangLines = filter ("w:lang" `isInfixOf`) . lines+              assertBool ("german-reference.docx w:lang line: " +++                  unlines (getLangLines refStylesXml))+                (any ("de-DE" `isInfixOf`) (getLangLines refStylesXml))+              -- Now test that using this reference preserves the language+              let opts = def{ writerReferenceDoc = Just "docx/german-reference.docx" }+              txt <- T.readFile "docx/inline_formatting.native"+              bs <- runIOorExplode $ do+                setVerbosity ERROR+                readNative def txt >>= writeDocx opts+              let archive = toArchive bs+              entry <- case findEntryByPath "word/styles.xml" archive of+                Nothing -> assertFailure "Missing word/styles.xml in output docx"+                Just e -> return e+              let stylesXml = show (fromEntry entry)+              -- Find the w:lang line for debugging+              -- Check that the styles.xml contains the German language+              assertBool ("Language from reference docx not preserved. w:lang lines: " ++ unlines (getLangLines stylesXml))+                (any ("de-DE" `isInfixOf`) (getLangLines stylesXml))+          , testCase "language from metadata overrides reference docx" $ do+              -- Use a reference docx with German language, but specify French in metadata+              let opts = def{ writerReferenceDoc = Just "docx/german-reference.docx" }+              bs <- runIOorExplode $ do+                setVerbosity ERROR+                -- Create a document with French language metadata+                let doc = Pandoc (Meta $ M.fromList [("lang", MetaString "fr-FR")])+                                 [Para [Str "Test"]]+                writeDocx opts doc+              let archive = toArchive bs+              entry <- case findEntryByPath "word/styles.xml" archive of+                Nothing -> assertFailure "Missing word/styles.xml in output docx"+                Just e -> return e+              let stylesXml = show (fromEntry entry)+              -- Check that the styles.xml contains the French language (not German)+              let getLangLines = filter ("w:lang" `isInfixOf`) . lines+              assertBool "Language from metadata did not override reference docx (expected fr-FR)"+                (any ("fr-FR" `isInfixOf`) (getLangLines stylesXml))+          ]+        , testGroup "paragraph styles"+          [ testCase "FirstParagraph after heading with footnote (#11573)" $ do+              let opts = def+              bs <- runIOorExplode $ do+                setVerbosity ERROR+                let doc = Pandoc mempty+                          [ Header 3 ("heading-with-note", [], [])+                              [Note [Para [Str "note"]], Str "Heading"]+                          , Para [Str "Para", Space, Str "after."]+                          ]+                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)+              assertBool+                ("Expected FirstParagraph style after heading with footnote, got: "+                  ++ docXml)+                ("FirstParagraph" `isInfixOf` docXml)           ]         ]
test/Tests/Writers/HTML.hs view
@@ -102,13 +102,13 @@   , testGroup "sample with style"     [ "samp should wrap highlighted code" =:       codeWith ("",["sample","haskell"],[]) ">>="-      =?> ("<samp><code class=\"sourceCode haskell\">" +++      =?> ("<samp><code class=\"sourceCode haskell sample\">" ++           "<span class=\"op\">&gt;&gt;=</span></code></samp>")     ]   , testGroup "variable with style"     [ "var should wrap highlighted code" =:       codeWith ("",["haskell","variable"],[]) ">>="-      =?> ("<var><code class=\"sourceCode haskell\">" +++      =?> ("<var><code class=\"sourceCode haskell variable\">" ++           "<span class=\"op\">&gt;&gt;=</span></code></var>")     ]   , testGroup "footnotes"
test/Tests/Writers/LaTeX.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} module Tests.Writers.LaTeX (tests) where -import Data.Text (unpack)+import Data.Text (pack, unpack) import Test.Tasty import Test.Tasty.HUnit (HasCallStack) import Tests.Helpers@@ -13,7 +13,7 @@ latex = latexWithOpts def  latexListing :: (ToPandoc a) => a -> String-latexListing = latexWithOpts def{ writerListings = True }+latexListing = latexWithOpts def{ writerHighlightMethod = IdiomaticHighlighting }  latexWithOpts :: (ToPandoc a) => WriterOptions -> a -> String latexWithOpts opts = unpack . purely (writeLaTeX opts) . toPandoc@@ -70,7 +70,7 @@             "\\begin{description}\n\\item[foo] ~ \n\\subsection{bar}\n\nbaz\n\\end{description}"           , "containing image" =:             header 1 (image "imgs/foo.jpg" "" (text "Alt text")) =?>-            "\\section{\\texorpdfstring{\\protect\\includegraphics{imgs/foo.jpg}}{Alt text}}"+            "\\section{\\texorpdfstring{\\protect\\pandocbounded{\\includegraphics[keepaspectratio,alt={Alt text}]{imgs/foo.jpg}}}{Alt text}}"           ]         , testGroup "inline code"           [ "struck out and highlighted" =:@@ -241,5 +241,15 @@                       , "\\addcontentsline{toc}{paragraph}{header6}"                       ]             ]+          ]+        , testGroup "figures"+          [ "placement" =:+            figureWith ("", [], [("latex-placement", "htbp")])+            (simpleCaption $ plain "caption")+            (plain $ image (pack "img.jpg") (pack "") (text "alt text"))+            =?>+              "\\begin{figure}[htbp]\n\\centering\n"+              <> "\\pandocbounded{\\includegraphics[keepaspectratio,alt={alt text}]{img.jpg}}\n"+              <> "\\caption{caption}\n\\end{figure}"           ]         ]
test/Tests/Writers/Markdown.hs view
@@ -41,11 +41,14 @@ tests :: [TestTree] tests = [ "indented code after list"              =: (orderedList [ para "one" <> para "two" ] <> codeBlock "test")-             =?> "1.  one\n\n    two\n\n```{=html}\n<!-- -->\n```\n    test"+             =?> "1.  one\n\n    two\n\n<!-- -->\n\n    test"         , "list with tight sublist"              =: bulletList [ plain "foo" <> bulletList [ plain "bar" ],                              plain "baz" ]-             =?> "-   foo\n    -   bar\n-   baz\n"+             =?> "- foo\n  - bar\n- baz\n"+        , "emph/strong with spaces (#10696)"+             =: emph (str "f" <> strong (space <> str "d" <> space)) <> str "l" =?>+             "*f **d*** l"         ] ++ [noteTests] ++ [shortcutLinkRefsTests]  {-
test/Tests/Writers/Powerpoint.hs view
@@ -102,6 +102,14 @@       def       "pptx/two-column/text-and-image/input.native"       "pptx/two-column/text-and-image/output.pptx"+    , pptxTests "single column text"+      def+      "pptx/single-column/text/input.native"+      "pptx/single-column/text/output.pptx"+    , pptxTests "single column image"+      def+      "pptx/single-column/image/input.native"+      "pptx/single-column/image/output.pptx"     , pptxTests "speaker notes"       def       "pptx/speaker-notes/input.native"@@ -118,6 +126,10 @@       def       "pptx/speaker-notes-after-metadata/input.native"       "pptx/speaker-notes-after-metadata/output.pptx"+    , pptxTests "speaker notes from metadata field"+      def+      "pptx/metadata-speaker-notes/input.native"+      "pptx/metadata-speaker-notes/output.pptx"     , pptxTests "remove empty slides"       def       "pptx/remove-empty-slides/input.native"@@ -268,5 +280,17 @@       def {writerReferenceDoc = Just "pptx/reference-deleted-layouts.pptx"}       "pptx/layouts/input.native"       "pptx/layouts/deleted.pptx"+    , ooxmlTest+      writePowerpoint+      "Slides can be missing from the reference doc"+      def {writerReferenceDoc = Just "pptx/reference-no-slides.pptx"}+      "pptx/reference-no-slides/add-slides/input.native"+      "pptx/reference-no-slides/add-slides/output.pptx"+    , ooxmlTest+      writePowerpoint+      "Notes are placed at the right position with a reference doc without slides"+      def {writerReferenceDoc = Just "pptx/reference-no-slides.pptx"}+      "pptx/reference-no-slides/with-notes/input.native"+      "pptx/reference-no-slides/with-notes/output.pptx"     ]   in regularTests <> referenceSpecificTests
test/Tests/Writers/RST.hs view
@@ -32,7 +32,7 @@ tests = [ testGroup "rubrics"           [ "in list item" =:               bulletList [header 2 (text "foo")] =?>-              "-  .. rubric:: foo"+              "- .. rubric:: foo"           , "in definition list item" =:               definitionList [(text "foo", [header 2 (text "bar"),                                             para $ text "baz"])] =?>@@ -60,7 +60,7 @@           [ "a list is closed by a comment before a quote" =: -- issue 4248             bulletList [plain "bulleted"] <> blockQuote (plain "quoted") =?>               unlines-              [ "-  bulleted"+              [ "- bulleted"               , ""               , ".."               , ""
+ test/Tests/XML.hs view
@@ -0,0 +1,28 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+--   Module      : Tests.XML+--   Copyright   : Copyright (C) 2025- Massimiliano Farinella and John MacFarlane+--   License     : GNU GPL, version 2 or above+--+--   Maintainer  : Massimiliano Farinella <massifrg@gmail.com>+--   Stability   : WIP+--   Portability : portable+Runs a roundtrip conversion of an AST trough the XML format:+- first from AST to XML (XML Writer),+- then back to AST (XML Reader),+- and checks that the two ASTs are the same+-}+module Tests.XML (tests) where++import Control.Monad ((>=>))+import Test.Tasty (TestTree)+import Test.Tasty.QuickCheck+import Tests.Helpers+import Text.Pandoc+import Text.Pandoc.Arbitrary ()++p_xml_roundtrip :: Pandoc -> Bool+p_xml_roundtrip d = d == purely (writeXML def {writerTemplate = Just mempty} >=> readXML def) d++tests :: [TestTree]+tests = [testProperty "p_xml_roundtrip" p_xml_roundtrip]
+ test/ansi-test.ansi view
@@ -0,0 +1,122 @@+[1m[23m[39m[49m[24m[29mLEVEL 1 HEADING[0m++Text++[1m[23m[39m[49m[24m[29mLevel 2 heading[0m++Text++[22m[3m[39m[49m[24m[29mLevel 3 heading[0m++Text++[22m[3m[39m[49m[24m[29mLevel 4 heading[0m++Text++[22m[3m[39m[49m[24m[29mLevel 5 heading[0m++Text++• list++  • nested++    1) numbered++       continuation paragraph++[22m[23m[36m[49m[4m[29m]8;;http://example.com\link[0m]8;;\++[22m[23m[36m[49m[4m[29m]8;;mailto:mail@example.com\mail@example.com[0m]8;;\++│ Block quote+│+│ │ Nested block quote++Multiline table with caption:++Centered    Left       Right        Default aligned+Header      Aligned    Aligned      +─────────── ────────── ──────────── ──────────────────────────+First       row        12.0         Example of a row that+                                    spans multiple lines.+Second      row        5.0          Here’s another one. Note+                                    the blank line between+                                    rows.+─────────── ────────── ──────────── ──────────────────────────++  Here’s the caption. It may span multiple lines.++Multiline table without caption:++Centered    Left       Right        Default aligned+Header      Aligned    Aligned      +─────────── ────────── ──────────── ──────────────────────────+First       row        12.0         Example of a row that+                                    spans multiple lines.+Second      row        5.0          Here’s another one. Note+                                    the blank line between+                                    rows.+─────────── ────────── ──────────── ──────────────────────────++Table without column headers:++───────────────── ───────────────── ───────────────── ─────────────────+12                12                12                12+123               123               123               123+1                 1                 1                 1+───────────────── ───────────────── ───────────────── ─────────────────++Footnote¹++Multiple blocks in a cell++────────────────── ─────────── ────────────+[1m[23m[39m[49m[24m[29mCOL 1[0m              [1m[23m[39m[49m[24m[29mCOL 2[0m       [1m[23m[39m[49m[24m[29mCOL 3[0m+                               +col 1              col 2       col 3+r1 a               • b         c c 2 c 2+                               +r1 bis             • b 2       +                               +                   • b 2       +────────────────── ─────────── ────────────++East Asian characters have double width++── ────+魚 fish+── ────++This is inline code: [22m[23m[31m[47m[24m[29m x >>= y ++ 3 [0m.++    [22m[23m[31m[49m[24m[29mcode block[0m+    [22m[23m[31m[49m[24m[29m   >>> ## ``[0m++Highlighted:++    [0m[0m[22;23;24m[31;22;23;24m<[0m[22;23;24m[32;1;23;24mp[0m[22;23;24m[31;22;23;24m><[0m[22;23;24m[32;1;23;24ma[0m[22;23;24m[32;22;23;24m href[0m[22;23;24m[90;22;23;24m=[0m[22;23;24m[36;22;23;24m"foobar"[0m[22;23;24m[32;22;23;24m title[0m[22;23;24m[90;22;23;24m=[0m[22;23;24m[36;22;23;24m"title"[0m[22;23;24m[31;22;23;24m>[0m[22;23;24m[0m[22;23;24mThis is a link[0m[22;23;24m[31;22;23;24m</[0m[22;23;24m[32;1;23;24ma[0m[22;23;24m[31;22;23;24m></[0m[22;23;24m[32;1;23;24mp[0m[22;23;24m[31;22;23;24m>[0m[22;23;24m+    [90;22;3;24m<!-- comment -->[0m[22;23;24m[0m++Math: $\pi^2 = \frac{1}{2}$++[22m[3m[39m[49m[24m[29me[0m = [22m[3m[39m[49m[24m[29mmc[0m²++────────────────────++More text.++[1m[23m[39m[49m[24m[29mboldface text[0m, [22m[23m[39m[49m[4m[29munderlined text[0m, [22m[3m[39m[49m[24m[29memphasized text[0m.++small caps++We see a log₁₀ reduction in 2⁹ seconds.++Hello++Goodbye++                          ────────────────────++  1. Here’s the note.[0m]8;;\
+ test/ansi-test.txt view
@@ -0,0 +1,127 @@+---+title: My Document+author: John Doe+date: July 25, 1933+...++# Level 1 heading++Text++## Level 2 heading++Text++### Level 3 heading++Text++#### Level 4 heading++Text++##### Level 5 heading++Text++- list+  - nested+    1) numbered++       continuation paragraph++[link](http://example.com)++<mail@example.com>++> Block quote+>+> > Nested block quote++Multiline table with caption:++:  Here's the caption.+It may span multiple lines.++---------------------------------------------------------------+ Centered   Left             Right+  Header    Aligned        Aligned  Default aligned+----------  ---------  -----------  ---------------------------+   First    row               12.0  Example of a row that spans+                                    multiple lines.++   Second   row                5.0  Here's another one.  Note+                                    the blank line between rows.+---------------------------------------------------------------++Multiline table without caption:++---------------------------------------------------------------+ Centered   Left             Right+  Header    Aligned        Aligned  Default aligned+----------  ---------  -----------  ---------------------------+   First    row               12.0  Example of a row that spans+                                    multiple lines.++   Second   row                5.0  Here's another one.  Note+                                    the blank line between rows.+---------------------------------------------------------------++Table without column headers:++-------     ------ ----------   -------+     12     12        12             12+    123     123       123           123+      1     1          1              1+-------     ------ ----------   -------++Footnote^[Here's the note.]++Multiple blocks in a cell+++------------------+-----------+------------++| # col 1          | # col 2   | # col 3    |+| col 1            | col 2     | col 3      |++------------------+-----------+------------++| r1 a             | - b       | c          |+|                  | - b 2     | c 2        |+| r1 bis           | - b 2     | c 2        |++------------------+-----------+------------+++East Asian characters have double width+++--+----++|魚|fish|++--+----+++This is inline code: `x >>= y ++ 3`.++```+code block+   >>> ## ``+```++Highlighted:++```html+<p><a href="foobar" title="title">This is a link</a></p>+<!-- comment -->+```++Math: $\pi^2 = \frac{1}{2}$++$$e = mc^2$$++----++More text.++**boldface text**, [underlined text]{.underline}, *emphasized text*.++[small caps]{.smallcaps}++We see a log~10~ reduction in 2^9^ seconds.++| Hello+|+| Goodbye
+ test/asciidoc-reader-include.adoc view
@@ -0,0 +1,4 @@+This is a test!++. one+.. two
+ test/asciidoc-reader-include.rb view
@@ -0,0 +1,4 @@+# A function+def foo+  return 42+end
+ test/asciidoc-reader.adoc view
@@ -0,0 +1,908 @@+// Some comment here.+= AsciiDoc reader test+John MacFarlane <jgm@berkeley.edu>; John Doe <doe@example.com>+v1.0, 2025-11-24+:custom: Foo bar \+baz+:flag:+:stem: latexmath++[#firsty]+== Inline markup++=== Characters and escapes++Dog's has a curved apostrophe, but dog\'s does not.++An escaped symbol: \*star\*.++Character references: &auml;&#160;&#x22E0; ++=== Line breaks++This is a hard ++break.++Or set it for a whole paragraph++[%hardbreaks]+These are+all+hard+breaks.++=== Autolinks++http://example.com/foobar?a=333&b=no%20body, me@example.com++<http://example.com/foobar?a=333&b=no%20body>, <me@example.com>++=== Cross-reference++See <<firsty>>++See <<firsty,My great section on Inline markup>>++Go to <<anch,an inline anchor>>++=== Anchors++An [[anch]]inline anchor.++[[[bibanchor]]Doe, John. A Book.++=== Inline macros++kbd:[F11]++kbd:[Ctrl+Shift+F]++menu:File[Save]++menu:Reader[Markdown > Pandoc]++btn:[Cancel]++icon:heart[2x,role=red]++anchor:tiger++pass:[<b>*bold*</b>]++link:downloads/report.pdf[Get Report]++link:tools.html#editors[]++link:file:///home/username[Your files]++Tricky cases:++link:pass:[My Documents/report.pdf][Get Report]++link:My&#32;Documents/report.pdf[Get Report]++link:My%20Documents/report.pdf[Get Report]++link:++https://example.org/now_this__link_works.html++[]++mailto:join@discuss.example.org[Subscribe]++mailto:join@discuss.example.org["Click, subscribe, and participate!",role=mail]++xref:link-macro-attributes[use attributes within the link macro]++image::sunset.jpg[Sunset]++image::name.png[]++image::sunset.jpg[Sunset,300,400]++image::sunset.jpg[alt=Sunset,width=300,height=400]++[latexmath]++++++e=mc^2+++++++[asciimath]++++++sin n / 3+++++++[stem]++++++e^i+++++++=== Attribute substitutions++{custom}++{nonexistent}++Built in: x{blank}y{empty}z{sp}a{nbsp}b{zwsp}c{apos}d{lsquo}++=== Bold and italic++Constrained: *this is bold _and italic_*.++Unconstrained: wild**content__with italic__stuff**.++=== Monospace++`simple`++`complex *with bold* text and a link:foo.html[]`++unconstrained``wwow``okay++=== Span and inline attributes++[.red]#Bonjour *monsieur*#++Un[.red]##constrained##content++With #no attribute# it's highlighted.++=== Sub and superscript++H~2~O++H~a{sp}b~O++Not subscript: H~a b~O.++H^2&O++H^a{sp}b^O++Not subscript: H^a b^O.++=== Passthrough++Here the special characters just come through as literal:+++<b>*test*</b>+++xx++<b>*test*</b>++xx++But here they are passed through:++xx+++<b>*test*</b>+++xx++=== Quoted++"`double quoted`"++'`single quoted`'++=== Footnotes++Doublefootnote:[The double hail-and-rainbow level makes my toes tingle.]++A bold statement!footnote:disclaimer[Opinions are my own.]+Another outrageous statement.footnote:disclaimer[]++== Block markup++=== Sections++==== Another level++===== Level 5++#### Markdown style++##### Level 5++=== Discrete heading++[discrete]+==== A discrete heading, not a section++=== Paragraph++This is a paragraph+whose source fits on two lines.++{.This is my title}+A paragraph with a title.++=== Example block++.Optional title+[example]+This is an example of an example block.++.Optional title+====+Paragraph *one*.++Paragraph *two*.+====++=== Admonition++Simple form:++WARNING: This is very dangerous.+Don't do it unless you understand the risks.++[IMPORTANT]+.Title of the admonition+====+Remember:++. Don't do this.+. And don't do that.+====++=== Sidebar++[sidebar]+A simple sidebar.++.Optional Title *with strong emphasis*+****+Here is a sidebar.++TIP: It can contain any type of content.+****++=== Literal block++Short indented code:++  $ ls -a+  $ cat /foo/bar/baz \+       /bi/bim/bop++[literal]+This is+  a literal block too.++....+  Fenced+    $+ *a* literal++****+not a sidebar+****+....++=== Listing++[source,ruby]+----+require 'sinatra'++get '/hi' do+  "Hello World!"+end+----++Implied:++[source,ruby]+----+require 'sinatra'++get '/hi' do+  "Hello World!"+end+----++[,ruby]+----+include::asciidoc-reader-include.rb[]+----++[#hello.haskell]+----+putStrLn $ unwords ["Hello", "world"]+----++Line numbering:++[%linenums,ruby]+----+puts 1+puts 2+puts 3+----++----+This doesn't have a language.+  +="hi"+----++And with a callout list:++[source,ruby]+----+require 'sinatra' <1>++get '/hi' do <2> <3>+  "Hello World!"+end+----+<1> Library import+<2> URL mapping+<3> Response block++Markdown-style fenced:++```ruby+def foo+  return 5+end+```++=== Verse++[verse,Carl Sandburg, two lines from the poem Fog]+The fog comes+on little cat feet.++[verse,Carl Sandburg,Fog]+____+The fog comes+on little cat feet.+It sits looking+over harbor and city+on silent haunches+and then moves on.+____++=== Collapsible++Click here for more.+[%collapsible%open]+====+This is collapsible.++It can be hidden.+====++.Click me!+[%collapsible]+This paragraph is+also collapsible.++=== Quote++[quote,Captain James T. Kirk,Star Trek IV: The Voyage Home]+Everybody remember where we parked.++[quote,Monty Python and the Holy Grail]+____+Dennis: Come and see the violence inherent in the system. Help! Help! I'm being+repressed.++King Arthur: Bloody peasant!++Dennis: Oh, what a giveaway! Did you hear that? Did you hear that, eh? That's what I'm+on about! Did you see him repressing me? You saw him, Didn't you?+____++[quote.movie#roads,Dr. Emmett Brown]+____+Roads? Where we're going, we don't need roads.+____++=== Pass+++++++<p>pass <em>through</em>+  </p>+++++++=== Open block++.A title.+[key="a value"]+--+Any content can go here:++. one+. two+--++=== Anchor++[[goals]]+* one+* two++=== Breaks++Asciidoc thematic break:++'''++Markdown style:++---+- - -+***+* * *++Page breaks:++<<<++[%always]+<<<++=== List++* Edgar Allan Poe+* Sheri S. Tepper+* Bill Bryson++// titled++.Kizmet's Favorite Authors+* Edgar Allan Poe+* Sheri S. Tepper+* Bill Bryson++// hyphen++- Edgar Allan Poe+- Sheri S. Tepper+- Bill Bryson++. Nested list+* West wood maze+** Maze heart+*** Reflection pool+** Secret exit+* Level 1 list item+** Level 2 list item+*** Level 3 list item+**** Level 4 list item+***** Level 5 list item+****** etc.+* Level 1 list item++// attributes++[square]+* one+* two+* three++// ordered with actual numbers++1. Protons+2. Electrons+3. Neutrons++// ordered with .++. Protons+. Electrons+. Neutrons++Start with 4:++4. Step four+5. Step five+6. Step six++or++[start=4]+. Step four+. Step five+. Step six++Reversed:++[%reversed]+.Parts of an atom+. Protons+. Electrons+. Neutrons++Nested++. Step 1+. Step 2+.. Step 2a+.. Step 2b+. Step 3++Mixed nested++. Linux+* Fedora+* Ubuntu+* Slackware+. BSD+* FreeBSD+* NetBSD++With spacing++. Linux+* Fedora+* Ubuntu+* Slackware+. BSD+* FreeBSD+* NetBSD++With number styles++[lowerroman,start=5]+. Five+. Six+[loweralpha]+.. a+.. b+.. c+. Seven++Checklist++* [*] checked+* [x] also checked+* [ ] not checked+* normal list item++Separate lists with block attribute++* Apples+* Oranges+[]+. Wash+. Slice++Multiline items++* Blah blah.+Blah blah.+* The document header in AsciiDoc is optional.+If present, it must start with a document title.++* Optional author and revision information lines+immediately follow the document title.++* The document header must be separated from+  the remainder of the document by one or more+  empty lines and it cannot contain empty lines.++Complex item++* The header in AsciiDoc must start with a document title.+++----+= Document Title+----+++Keep in mind that the header is optional.+* Optional author and revision information lines immediately follow the document+title.+++----+= Document Title+Doc Writer <doc.writer@asciidoc.org>+v1.0, 2022-01-01+----+* Second item++Empty principle element:++. {empty}+++----+test+----++=== Table++==== Simple with column specs++[cols="3,2,3"]+|===+|This content is placed in the first cell of column 1+|This line starts with a vertical bar so this content is placed in a new cell in+column 2 |When the processor encounters a whitespace followed by a vertical bar it+ends the previous cell and starts a new cell+|===++==== Repeated column in specs++[cols="2*"]+|===+>s|This cell's specifier indicates that this cell's content is right-aligned and bold.+|The cell specifier on this cell hasn't been set explicitly, so the default+properties are applied.+|===++==== Simple without column specs++|===+|Column 1, header row |Column 2, header row++|Cell in column 1, row 2+|Cell in column 2, row 2++|Cell in column 1, row 3+|Cell in column 2, row 3+|===++==== With caption++.My cool table.+|===+|Column 1, header row |Column 2, header row++|Cell in column 1, row 2+|Cell in column 2, row 2++|Cell in column 1, row 3+|Cell in column 2, row 3+|===++==== No header++By default the first line should turn into the header, but this+can be disabled:++[%noheader]+|===+|Cell in column 1, row 1 |Cell in column 2, row 1+|Cell in column 1, row 2 |Cell in column 2, row 2+|===++And also explicitly enabled:++[%header%footer%autowidth,cols=2*~]+|===+|Cell A1 |Cell B1+|Cell A2 |Cell B2+|Cell A3 |Cell B3+|===++==== Footer++[%header%footer,cols="2,2,1"]+|===+|Column 1, header row+|Column 2, header row+|Column 3, header row+|Cell in column 1, row 2+|Cell in column 2, row 2+|Cell in column 3, row 2+|Column 1, footer row+|Column 2, footer row+|Column 3, footer row+|===++or++[options="footer"]+|===+|Column 1, header row |Column 2, header row+|Cell in column 1, row 2+|Cell in column 2, row 2+|Cell in column 1, row 3+|Cell in column 2, row 3+|Column 1, footer row+|Column 2, footer row+|===++==== Alignment++|===+|Column Name |Column Name+2+^|This cell spans two columns, and its content is horizontally centered because the+cell specifier includes the `+^+` operator.+2*^|This content is duplicated in two adjacent columns.+Its content is horizontally centered because the cell specifier+includes the `+^+` operator.+|===++==== Multiple paragraphs in cells++|===++|Single paragraph on row 1++|First paragraph on row 2++Second paragraph on row 2+|===++==== Complex table++|===++2*>m|This content is duplicated across two columns.++It is aligned right horizontally.++And it is monospaced.++.3+^.>s|This cell spans 3 rows. The content is centered horizontally, aligned to the bottom of the cell, and strong.+e|This content is emphasized.++.^l|This content is aligned to the top of the cell and literal.++a|+[source]+puts "This is a source block!"++|===++==== Column styles++[cols="m,m"]+|===+|monospace | mono+d|default | mono+|===++==== Block elements in cells++|===+|Normal Style |AsciiDoc Style+|This cell isn't prefixed with an `a`, so the processor doesn't interpret the+following lines as an AsciiDoc list.++* List item 1+* List item 2+* List item 3++a|This cell is prefixed with an `a`, so the processor interprets the following lines+as an AsciiDoc list.++* List item 1+* List item 2+* List item 3++|This cell isn't prefixed with an `a`, so the processor doesn't interpret the listing+block delimiters or the `source` style.++[source,python]+----+import os+print ("%s" %(os.uname()))+----++a|This cell is prefixed with an `a`, so the listing block is processed and rendered+according to the `source` style rules.++[source,python]+----+import os+print "%s" %(os.uname())+----+|===++==== Col and rowspan++|===+|Column 1, header row |Column 2, header row | Column 3, header row+2.2+|This cell spans 2 cols and 2 rows+|Cell in column 3, row 2+|Cell in column 3, row 3+3+|Cell in column 1-3, row 4+|===++==== CSV table++[%header,format=csv]+|===+Artist,Track,Genre+Baauer,Harlem Shake,Hip Hop+The Lumineers,Ho Hey,Folk Rock+|===++or++,===+Artist,Track,Genre+Baauer,Harlem Shake,Hip Hop+,===++==== DSV table++[format=dsv,separator=;]+|===+a;b;c+d;e;f+|===++or++:===+Artist:Track:Genre+Robyn:Indestructible:Dance+:===++=== Definition list++CPU:: The brain of the computer.+Hard drive:: Permanent storage for operating system and/or user files.++Mixed++Dairy::+* Milk+* Eggs+Bakery::+* Bread+Produce::+* Bananas++With spaces++Dairy::++  * Milk+  * Eggs++Bakery::++  * Bread++Produce::++  * Bananas++Nested++Operating Systems::+Linux:::+ . Fedora+  * Desktop+ . Ubuntu+  * Desktop+  * Server+BSD:::+ . FreeBSD+ . NetBSD+Cloud Providers::+ PaaS:::+  . OpenShift+  . CloudBees+ IaaS:::+  . Amazon EC2++This just affects the output:++[horizontal,labelwidth=25,itemwidth=75]+CPU:: The brain of the computer.+RAM:: Temporarily stores information the CPU uses during operation.++Q&A list++[qanda]+What is the answer?::+This is the answer.+Are cameras allowed?::+Are backpacks allowed?::+No.++Ordered description list (with numbers)++[ordered]+&:: ampersand+>:: greater than++=== Block macros++image::sunset.jpg[Sunset,300,200]++video::mymovie.mp4[]++audio::mysong.mp3[]++toc::[]++include::asciidoc-reader-include.adoc[]+
+ test/asciidoc-reader.native view
@@ -0,0 +1,4418 @@+Pandoc+  Meta+    { unMeta =+        fromList+          [ ( "author"+            , MetaList+                [ MetaInlines+                    [ Str "John"+                    , Space+                    , Str "MacFarlane"+                    , Space+                    , Str "("+                    , Link+                        ( "" , [] , [] )+                        [ Str "jgm@berkeley.edu" ]+                        ( "mailto:jgm@berkeley.edu" , "" )+                    , Str ")"+                    ]+                , MetaInlines+                    [ Str "John"+                    , Space+                    , Str "Doe"+                    , Space+                    , Str "("+                    , Link+                        ( "" , [] , [] )+                        [ Str "doe@example.com" ]+                        ( "mailto:doe@example.com" , "" )+                    , Str ")"+                    ]+                ]+            )+          , ( "custom" , MetaString "Foo bar baz" )+          , ( "date" , MetaString "2025-11-24" )+          , ( "flag" , MetaBool True )+          , ( "title"+            , MetaInlines+                [ Str "AsciiDoc"+                , Space+                , Str "reader"+                , Space+                , Str "test"+                ]+            )+          , ( "version" , MetaString "1.0" )+          ]+    }+  [ Header+      1+      ( "firsty" , [] , [] )+      [ Str "Inline" , Space , Str "markup" ]+  , Header+      2+      ( "_characters_and_escapes" , [] , [] )+      [ Str "Characters"+      , Space+      , Str "and"+      , Space+      , Str "escapes"+      ]+  , Para+      [ Str "Dog\8217s"+      , Space+      , Str "has"+      , Space+      , Str "a"+      , Space+      , Str "curved"+      , Space+      , Str "apostrophe,"+      , Space+      , Str "but"+      , Space+      , Str "dog's"+      , Space+      , Str "does"+      , Space+      , Str "not."+      ]+  , Para+      [ Str "An"+      , Space+      , Str "escaped"+      , Space+      , Str "symbol:"+      , Space+      , Str "*star*."+      ]+  , Para+      [ Str "Character"+      , Space+      , Str "references:"+      , Space+      , Str "\228\160\8928"+      ]+  , Header+      2+      ( "_line_breaks" , [] , [] )+      [ Str "Line" , Space , Str "breaks" ]+  , Para+      [ Str "This"+      , Space+      , Str "is"+      , Space+      , Str "a"+      , Space+      , Str "hard"+      , LineBreak+      , Str "break."+      ]+  , Para+      [ Str "Or"+      , Space+      , Str "set"+      , Space+      , Str "it"+      , Space+      , Str "for"+      , Space+      , Str "a"+      , Space+      , Str "whole"+      , Space+      , Str "paragraph"+      ]+  , Div+      ( ""+      , []+      , [ ( "wrapper" , "1" ) , ( "options" , "hardbreaks" ) ]+      )+      [ Para+          [ Str "These"+          , Space+          , Str "are"+          , LineBreak+          , Str "all"+          , LineBreak+          , Str "hard"+          , LineBreak+          , Str "breaks."+          ]+      ]+  , Header 2 ( "_autolinks" , [] , [] ) [ Str "Autolinks" ]+  , Para+      [ Link+          ( "" , [] , [] )+          [ Str "http://example.com/foobar?a=333&b=no%20body" ]+          ( "http://example.com/foobar?a=333&b=no%20body" , "" )+      , Str ","+      , Space+      , Link+          ( "" , [] , [] )+          [ Str "me@example.com" ]+          ( "me@example.com" , "" )+      ]+  , Para+      [ Link+          ( "" , [] , [] )+          [ Str "http://example.com/foobar?a=333&b=no%20body" ]+          ( "http://example.com/foobar?a=333&b=no%20body" , "" )+      , Str ","+      , Space+      , Str "<"+      , Link+          ( "" , [] , [] )+          [ Str "me@example.com" ]+          ( "me@example.com" , "" )+      , Str ">"+      ]+  , Header+      2 ( "_cross_reference" , [] , [] ) [ Str "Cross-reference" ]+  , Para+      [ Str "See"+      , Space+      , Link+          ( "" , [ "cross-reference" ] , [] )+          [ Str "Inline" , Space , Str "markup" ]+          ( "#firsty" , "" )+      ]+  , Para+      [ Str "See"+      , Space+      , Link+          ( "" , [ "cross-reference" ] , [] )+          [ Str "My"+          , Space+          , Str "great"+          , Space+          , Str "section"+          , Space+          , Str "on"+          , Space+          , Str "Inline"+          , Space+          , Str "markup"+          ]+          ( "#firsty" , "" )+      ]+  , Para+      [ Str "Go"+      , Space+      , Str "to"+      , Space+      , Link+          ( "" , [ "cross-reference" ] , [] )+          [ Str "an" , Space , Str "inline" , Space , Str "anchor" ]+          ( "#anch" , "" )+      ]+  , Header 2 ( "_anchors" , [] , [] ) [ Str "Anchors" ]+  , Para+      [ Str "An"+      , Space+      , Span ( "anch" , [] , [] ) []+      , Str "inline"+      , Space+      , Str "anchor."+      ]+  , Para+      [ Span ( "[bibanchor" , [] , [] ) []+      , Str "Doe,"+      , Space+      , Str "John."+      , Space+      , Str "A"+      , Space+      , Str "Book."+      ]+  , Header+      2+      ( "_inline_macros" , [] , [] )+      [ Str "Inline" , Space , Str "macros" ]+  , Para+      [ Span ( "" , [ "kbd" ] , [] ) [ Strong [ Str "F11" ] ] ]+  , Para+      [ Span ( "" , [ "kbd" ] , [] ) [ Strong [ Str "Ctrl" ] ]+      , Str "+"+      , Span ( "" , [ "kbd" ] , [] ) [ Strong [ Str "Shift" ] ]+      , Str "+"+      , Span ( "" , [ "kbd" ] , [] ) [ Strong [ Str "F" ] ]+      ]+  , Para+      [ Span+          ( "" , [ "menu" ] , [] )+          [ Strong [ Str "File\160\8250\160Save" ] ]+      ]+  , Para+      [ Span+          ( "" , [ "menu" ] , [] )+          [ Strong+              [ Str "Reader\160\8250\160Markdown\160\8250\160Pandoc" ]+          ]+      ]+  , Para+      [ Span+          ( "" , [ "button" ] , [] ) [ Strong [ Str "[Cancel]" ] ]+      ]+  , Para+      [ Image+          ( "" , [ "red icon" ] , [] )+          []+          ( "./images/icons/heart.png" , "" )+      ]+  , Para [ Str "anchor:tiger" ]+  , Para [ Strong [ Str "*bold*" ] ]+  , Para+      [ Link+          ( "" , [] , [] )+          [ Str "Get" , Space , Str "Report" ]+          ( "downloads/report.pdf" , "" )+      ]+  , Para+      [ Link+          ( "" , [] , [] )+          [ Str "tools.html#editors" ]+          ( "tools.html#editors" , "" )+      ]+  , Para+      [ Link+          ( "" , [] , [] )+          [ Str "Your" , Space , Str "files" ]+          ( "file:///home/username" , "" )+      ]+  , Para [ Str "Tricky" , Space , Str "cases:" ]+  , Para+      [ Link+          ( "" , [] , [] )+          [ Str "Get" , Space , Str "Report" ]+          ( "My Documents/report.pdf" , "" )+      ]+  , Para+      [ Link+          ( "" , [] , [] )+          [ Str "Get" , Space , Str "Report" ]+          ( "My&#32;Documents/report.pdf" , "" )+      ]+  , Para+      [ Link+          ( "" , [] , [] )+          [ Str "Get" , Space , Str "Report" ]+          ( "My%20Documents/report.pdf" , "" )+      ]+  , Para+      [ Link+          ( "" , [] , [] )+          [ Str "https://example.org/now_this__link_works.html" ]+          ( "https://example.org/now_this__link_works.html" , "" )+      ]+  , Para+      [ Link+          ( "" , [] , [] )+          [ Str "Subscribe" ]+          ( "join@discuss.example.org" , "" )+      ]+  , Para+      [ Link+          ( "" , [ "mail" ] , [] )+          [ Str "Click,"+          , Space+          , Str "subscribe,"+          , Space+          , Str "and"+          , Space+          , Str "participate!"+          ]+          ( "join@discuss.example.org" , "" )+      ]+  , Para+      [ Link+          ( "" , [ "cross-reference" ] , [] )+          [ Str "use"+          , Space+          , Str "attributes"+          , Space+          , Str "within"+          , Space+          , Str "the"+          , Space+          , Str "link"+          , Space+          , Str "macro"+          ]+          ( "#link-macro-attributes" , "" )+      ]+  , Figure+      ( "" , [] , [] )+      (Caption Nothing [])+      [ Plain+          [ Image+              ( "" , [] , [] ) [ Str "Sunset" ] ( "sunset.jpg" , "" )+          ]+      ]+  , Figure+      ( "" , [] , [] )+      (Caption Nothing [])+      [ Plain [ Image ( "" , [] , [] ) [] ( "name.png" , "" ) ] ]+  , Figure+      ( "" , [] , [] )+      (Caption Nothing [])+      [ Plain+          [ Image+              ( ""+              , []+              , [ ( "width" , "300px" ) , ( "height" , "400px" ) ]+              )+              [ Str "Sunset" ]+              ( "sunset.jpg" , "" )+          ]+      ]+  , Div+      ( ""+      , []+      , [ ( "wrapper" , "1" )+        , ( "alt" , "Sunset" )+        , ( "height" , "400" )+        , ( "width" , "300" )+        ]+      )+      [ Figure+          ( "" , [] , [] )+          (Caption Nothing [])+          [ Plain [ Image ( "" , [] , [] ) [] ( "sunset.jpg" , "" ) ]+          ]+      ]+  , Para [ Math DisplayMath "e=mc^2\n" ]+  , Para [ Math DisplayMath "sin n / 3\n" ]+  , Para [ Math DisplayMath "e^i\n" ]+  , Header+      2+      ( "_attribute_substitutions" , [] , [] )+      [ Str "Attribute" , Space , Str "substitutions" ]+  , Para [ Str "Foo" , Space , Str "bar" , Space , Str "baz" ]+  , Para [ Str "{nonexistent}" ]+  , Para+      [ Str "Built"+      , Space+      , Str "in:"+      , Space+      , Str "xyz"+      , Space+      , Str "a\160b\8203c'd\8216"+      ]+  , Header+      2+      ( "_bold_and_italic" , [] , [] )+      [ Str "Bold" , Space , Str "and" , Space , Str "italic" ]+  , Para+      [ Str "Constrained:"+      , Space+      , Strong+          [ Str "this"+          , Space+          , Str "is"+          , Space+          , Str "bold"+          , Space+          , Emph [ Str "and" , Space , Str "italic" ]+          ]+      , Str "."+      ]+  , Para+      [ Str "Unconstrained:"+      , Space+      , Str "wild"+      , Strong+          [ Str "content"+          , Emph [ Str "with" , Space , Str "italic" ]+          , Str "stuff"+          ]+      , Str "."+      ]+  , Header 2 ( "_monospace" , [] , [] ) [ Str "Monospace" ]+  , Para [ Code ( "" , [] , [] ) "simple" ]+  , Para+      [ Code ( "" , [] , [] ) "complex"+      , Space+      , Strong+          [ Code ( "" , [] , [] ) "with"+          , Space+          , Code ( "" , [] , [] ) "bold"+          ]+      , Space+      , Code ( "" , [] , [] ) "text"+      , Space+      , Code ( "" , [] , [] ) "and"+      , Space+      , Code ( "" , [] , [] ) "a"+      , Space+      , Link+          ( "" , [] , [] )+          [ Code ( "" , [] , [] ) "foo.html" ]+          ( "foo.html" , "" )+      ]+  , Para+      [ Str "unconstrained"+      , Code ( "" , [] , [] ) "wwow"+      , Str "okay"+      ]+  , Header+      2+      ( "_span_and_inline_attributes" , [] , [] )+      [ Str "Span"+      , Space+      , Str "and"+      , Space+      , Str "inline"+      , Space+      , Str "attributes"+      ]+  , Para+      [ Span+          ( "" , [ "red" ] , [] )+          [ Str "Bonjour" , Space , Strong [ Str "monsieur" ] ]+      ]+  , Para+      [ Str "Un"+      , Span ( "" , [ "red" ] , [] ) [ Str "constrained" ]+      , Str "content"+      ]+  , Para+      [ Str "With"+      , Space+      , Span+          ( "" , [ "mark" ] , [] )+          [ Str "no" , Space , Str "attribute" ]+      , Space+      , Str "it\8217s"+      , Space+      , Str "highlighted."+      ]+  , Header+      2+      ( "_sub_and_superscript" , [] , [] )+      [ Str "Sub"+      , Space+      , Str "and"+      , Space+      , Str "superscript"+      ]+  , Para [ Str "H" , Subscript [ Str "2" ] , Str "O" ]+  , Para+      [ Str "H"+      , Subscript [ Str "a" , Space , Str "b" ]+      , Str "O"+      ]+  , Para+      [ Str "Not"+      , Space+      , Str "subscript:"+      , Space+      , Str "H~a"+      , Space+      , Str "b~O."+      ]+  , Para [ Str "H^2&O" ]+  , Para+      [ Str "H"+      , Superscript [ Str "a" , Space , Str "b" ]+      , Str "O"+      ]+  , Para+      [ Str "Not"+      , Space+      , Str "subscript:"+      , Space+      , Str "H^a"+      , Space+      , Str "b^O."+      ]+  , Header+      2 ( "_passthrough" , [] , [] ) [ Str "Passthrough" ]+  , Para+      [ Str "Here"+      , Space+      , Str "the"+      , Space+      , Str "special"+      , Space+      , Str "characters"+      , Space+      , Str "just"+      , Space+      , Str "come"+      , Space+      , Str "through"+      , Space+      , Str "as"+      , Space+      , Str "literal:"+      ]+  , Para [ Str "<b>*test*</b>" ]+  , Para [ Str "xx<b>*test*</b>xx" ]+  , Para+      [ Str "But"+      , Space+      , Str "here"+      , Space+      , Str "they"+      , Space+      , Str "are"+      , Space+      , Str "passed"+      , Space+      , Str "through:"+      ]+  , Para [ Str "xx" , Strong [ Str "*test*" ] , Str "xx" ]+  , Header 2 ( "_quoted" , [] , [] ) [ Str "Quoted" ]+  , Para+      [ Quoted DoubleQuote [ Str "double" , Space , Str "quoted" ]+      ]+  , Para+      [ Quoted SingleQuote [ Str "single" , Space , Str "quoted" ]+      ]+  , Header 2 ( "_footnotes" , [] , [] ) [ Str "Footnotes" ]+  , Para+      [ Str "Double"+      , Note+          [ Para+              [ Str "The"+              , Space+              , Str "double"+              , Space+              , Str "hail-and-rainbow"+              , Space+              , Str "level"+              , Space+              , Str "makes"+              , Space+              , Str "my"+              , Space+              , Str "toes"+              , Space+              , Str "tingle."+              ]+          ]+      ]+  , Para+      [ Str "A"+      , Space+      , Str "bold"+      , Space+      , Str "statement!"+      , Note+          [ Para+              [ Str "Opinions"+              , Space+              , Str "are"+              , Space+              , Str "my"+              , Space+              , Str "own."+              ]+          ]+      , SoftBreak+      , Str "Another"+      , Space+      , Str "outrageous"+      , Space+      , Str "statement."+      , Note+          [ Para+              [ Str "Opinions"+              , Space+              , Str "are"+              , Space+              , Str "my"+              , Space+              , Str "own."+              ]+          ]+      ]+  , Header+      1+      ( "_block_markup" , [] , [] )+      [ Str "Block" , Space , Str "markup" ]+  , Header 2 ( "_sections" , [] , [] ) [ Str "Sections" ]+  , Header+      3+      ( "_another_level" , [] , [] )+      [ Str "Another" , Space , Str "level" ]+  , Header+      4 ( "_level_5" , [] , [] ) [ Str "Level" , Space , Str "5" ]+  , Header+      3+      ( "_markdown_style" , [] , [] )+      [ Str "Markdown" , Space , Str "style" ]+  , Header+      4+      ( "_level_5_2" , [] , [] )+      [ Str "Level" , Space , Str "5" ]+  , Header+      2+      ( "_discrete_heading" , [] , [] )+      [ Str "Discrete" , Space , Str "heading" ]+  , Header+      3+      ( "" , [] , [] )+      [ Str "A"+      , Space+      , Str "discrete"+      , Space+      , Str "heading,"+      , Space+      , Str "not"+      , Space+      , Str "a"+      , Space+      , Str "section"+      ]+  , Header 2 ( "_paragraph" , [] , [] ) [ Str "Paragraph" ]+  , Para+      [ Str "This"+      , Space+      , Str "is"+      , Space+      , Str "a"+      , Space+      , Str "paragraph"+      , SoftBreak+      , Str "whose"+      , Space+      , Str "source"+      , Space+      , Str "fits"+      , Space+      , Str "on"+      , Space+      , Str "two"+      , Space+      , Str "lines."+      ]+  , Para+      [ Str "{.This"+      , Space+      , Str "is"+      , Space+      , Str "my"+      , Space+      , Str "title}"+      , SoftBreak+      , Str "A"+      , Space+      , Str "paragraph"+      , Space+      , Str "with"+      , Space+      , Str "a"+      , Space+      , Str "title."+      ]+  , Header+      2+      ( "_example_block" , [] , [] )+      [ Str "Example" , Space , Str "block" ]+  , Div+      ( "" , [] , [] )+      [ Div+          ( "" , [ "title" ] , [] )+          [ Para [ Str "Optional" , Space , Str "title" ] ]+      , Para+          [ Str "This"+          , Space+          , Str "is"+          , Space+          , Str "an"+          , Space+          , Str "example"+          , Space+          , Str "of"+          , Space+          , Str "an"+          , Space+          , Str "example"+          , Space+          , Str "block."+          ]+      ]+  , Div+      ( "" , [ "example" ] , [] )+      [ Div+          ( "" , [ "title" ] , [] )+          [ Para [ Str "Optional" , Space , Str "title" ] ]+      , Para+          [ Str "Paragraph" , Space , Strong [ Str "one" ] , Str "." ]+      , Para+          [ Str "Paragraph" , Space , Strong [ Str "two" ] , Str "." ]+      ]+  , Header 2 ( "_admonition" , [] , [] ) [ Str "Admonition" ]+  , Para [ Str "Simple" , Space , Str "form:" ]+  , Div+      ( "" , [ "warning" ] , [] )+      [ Div ( "" , [ "title" ] , [] ) [ Para [ Str "Warning" ] ]+      , Para+          [ Str "This"+          , Space+          , Str "is"+          , Space+          , Str "very"+          , Space+          , Str "dangerous."+          , SoftBreak+          , Str "Don\8217t"+          , Space+          , Str "do"+          , Space+          , Str "it"+          , Space+          , Str "unless"+          , Space+          , Str "you"+          , Space+          , Str "understand"+          , Space+          , Str "the"+          , Space+          , Str "risks."+          ]+      ]+  , Div+      ( "" , [ "important" ] , [] )+      [ Div+          ( "" , [ "title" ] , [] )+          [ Para+              [ Str "Title"+              , Space+              , Str "of"+              , Space+              , Str "the"+              , Space+              , Str "admonition"+              ]+          ]+      , Para [ Str "Remember:" ]+      , OrderedList+          ( 1 , DefaultStyle , DefaultDelim )+          [ [ Para+                [ Str "Don\8217t"+                , Space+                , Str "do"+                , Space+                , Str "this."+                ]+            ]+          , [ Para+                [ Str "And"+                , Space+                , Str "don\8217t"+                , Space+                , Str "do"+                , Space+                , Str "that."+                ]+            ]+          ]+      ]+  , Header 2 ( "_sidebar" , [] , [] ) [ Str "Sidebar" ]+  , Para+      [ Str "A" , Space , Str "simple" , Space , Str "sidebar." ]+  , Div+      ( "" , [ "sidebar" ] , [] )+      [ Div+          ( "" , [ "title" ] , [] )+          [ Para+              [ Str "Optional"+              , Space+              , Str "Title"+              , Space+              , Strong+                  [ Str "with"+                  , Space+                  , Str "strong"+                  , Space+                  , Str "emphasis"+                  ]+              ]+          ]+      , Para+          [ Str "Here"+          , Space+          , Str "is"+          , Space+          , Str "a"+          , Space+          , Str "sidebar."+          ]+      , Div+          ( "" , [ "tip" ] , [] )+          [ Div ( "" , [ "title" ] , [] ) [ Para [ Str "Tip" ] ]+          , Para+              [ Str "It"+              , Space+              , Str "can"+              , Space+              , Str "contain"+              , Space+              , Str "any"+              , Space+              , Str "type"+              , Space+              , Str "of"+              , Space+              , Str "content."+              ]+          ]+      ]+  , Header+      2+      ( "_literal_block" , [] , [] )+      [ Str "Literal" , Space , Str "block" ]+  , Para+      [ Str "Short"+      , Space+      , Str "indented"+      , Space+      , Str "code:"+      ]+  , CodeBlock+      ( "" , [] , [] )+      "$ ls -a\n$ cat /foo/bar/baz \\\n     /bi/bim/bop\n"+  , CodeBlock+      ( "" , [] , [] ) "This is\n  a literal block too.\n"+  , CodeBlock+      ( "" , [] , [] )+      "  Fenced\n    $+ *a* literal\n\n****\nnot a sidebar\n****\n"+  , Header 2 ( "_listing" , [] , [] ) [ Str "Listing" ]+  , CodeBlock+      ( "" , [ "ruby" ] , [] )+      "require 'sinatra'\n\nget '/hi' do\n  \"Hello World!\"\nend"+  , Para [ Str "Implied:" ]+  , CodeBlock+      ( "" , [ "ruby" ] , [] )+      "require 'sinatra'\n\nget '/hi' do\n  \"Hello World!\"\nend"+  , CodeBlock+      ( "" , [ "ruby" ] , [] )+      "# A function\ndef foo\n  return 42\nend"+  , CodeBlock+      ( "hello" , [ "haskell" ] , [] )+      "putStrLn $ unwords [\"Hello\", \"world\"]"+  , Para [ Str "Line" , Space , Str "numbering:" ]+  , CodeBlock+      ( "" , [] , [ ( "options" , "linenums" ) ] )+      "puts 1\nputs 2\nputs 3"+  , CodeBlock+      ( "" , [] , [] ) "This doesn't have a language.\n  +=\"hi\""+  , Para+      [ Str "And"+      , Space+      , Str "with"+      , Space+      , Str "a"+      , Space+      , Str "callout"+      , Space+      , Str "list:"+      ]+  , CodeBlock+      ( "" , [ "ruby" ] , [] )+      "require 'sinatra' \9312\n\nget '/hi' do \9313 \9314\n  \"Hello World!\"\nend"+  , Div+      ( "" , [ "callout-list" ] , [] )+      [ OrderedList+          ( 1 , DefaultStyle , DefaultDelim )+          [ [ Para [ Str "Library" , Space , Str "import" ] ]+          , [ Para [ Str "URL" , Space , Str "mapping" ] ]+          , [ Para [ Str "Response" , Space , Str "block" ] ]+          ]+      ]+  , Para [ Str "Markdown-style" , Space , Str "fenced:" ]+  , CodeBlock+      ( "" , [ "ruby" ] , [] ) "def foo\n  return 5\nend"+  , Header 2 ( "_verse" , [] , [] ) [ Str "Verse" ]+  , BlockQuote+      [ Para+          [ Str "The"+          , Space+          , Str "fog"+          , Space+          , Str "comes"+          , LineBreak+          , Str "on"+          , Space+          , Str "little"+          , Space+          , Str "cat"+          , Space+          , Str "feet."+          ]+      , Para+          [ Str "\8212"+          , Space+          , Str "Carl"+          , Space+          , Str "Sandburg,"+          , Space+          , Str "two"+          , Space+          , Str "lines"+          , Space+          , Str "from"+          , Space+          , Str "the"+          , Space+          , Str "poem"+          , Space+          , Str "Fog"+          ]+      ]+  , BlockQuote+      [ Para+          [ Str "The"+          , Space+          , Str "fog"+          , Space+          , Str "comes"+          , LineBreak+          , Str "on"+          , Space+          , Str "little"+          , Space+          , Str "cat"+          , Space+          , Str "feet."+          , LineBreak+          , Str "It"+          , Space+          , Str "sits"+          , Space+          , Str "looking"+          , LineBreak+          , Str "over"+          , Space+          , Str "harbor"+          , Space+          , Str "and"+          , Space+          , Str "city"+          , LineBreak+          , Str "on"+          , Space+          , Str "silent"+          , Space+          , Str "haunches"+          , LineBreak+          , Str "and"+          , Space+          , Str "then"+          , Space+          , Str "moves"+          , Space+          , Str "on."+          ]+      , Para+          [ Str "\8212"+          , Space+          , Str "Carl"+          , Space+          , Str "Sandburg,"+          , Space+          , Str "Fog"+          ]+      ]+  , Header+      2 ( "_collapsible" , [] , [] ) [ Str "Collapsible" ]+  , Para+      [ Str "Click"+      , Space+      , Str "here"+      , Space+      , Str "for"+      , Space+      , Str "more."+      ]+  , Div+      ( ""+      , [ "example" ]+      , [ ( "options" , "collapsible,open" ) ]+      )+      [ Para+          [ Str "This"+          , Space+          , Str "is"+          , Space+          , Str "collapsible."+          ]+      , Para+          [ Str "It"+          , Space+          , Str "can"+          , Space+          , Str "be"+          , Space+          , Str "hidden."+          ]+      ]+  , Div+      ( "" , [] , [ ( "options" , "collapsible" ) ] )+      [ Div+          ( "" , [ "title" ] , [] )+          [ Para [ Str "Click" , Space , Str "me!" ] ]+      , Para+          [ Str "This"+          , Space+          , Str "paragraph"+          , Space+          , Str "is"+          , SoftBreak+          , Str "also"+          , Space+          , Str "collapsible."+          ]+      ]+  , Header 2 ( "_quote" , [] , [] ) [ Str "Quote" ]+  , BlockQuote+      [ Para+          [ Str "Everybody"+          , Space+          , Str "remember"+          , Space+          , Str "where"+          , Space+          , Str "we"+          , Space+          , Str "parked."+          ]+      , Para+          [ Str "\8212"+          , Space+          , Str "Captain"+          , Space+          , Str "James"+          , Space+          , Str "T."+          , Space+          , Str "Kirk,"+          , Space+          , Str "Star"+          , Space+          , Str "Trek"+          , Space+          , Str "IV:"+          , Space+          , Str "The"+          , Space+          , Str "Voyage"+          , Space+          , Str "Home"+          ]+      ]+  , BlockQuote+      [ Para+          [ Str "Dennis:"+          , Space+          , Str "Come"+          , Space+          , Str "and"+          , Space+          , Str "see"+          , Space+          , Str "the"+          , Space+          , Str "violence"+          , Space+          , Str "inherent"+          , Space+          , Str "in"+          , Space+          , Str "the"+          , Space+          , Str "system."+          , Space+          , Str "Help!"+          , Space+          , Str "Help!"+          , Space+          , Str "I\8217m"+          , Space+          , Str "being"+          , SoftBreak+          , Str "repressed."+          ]+      , Para+          [ Str "King"+          , Space+          , Str "Arthur:"+          , Space+          , Str "Bloody"+          , Space+          , Str "peasant!"+          ]+      , Para+          [ Str "Dennis:"+          , Space+          , Str "Oh,"+          , Space+          , Str "what"+          , Space+          , Str "a"+          , Space+          , Str "giveaway!"+          , Space+          , Str "Did"+          , Space+          , Str "you"+          , Space+          , Str "hear"+          , Space+          , Str "that?"+          , Space+          , Str "Did"+          , Space+          , Str "you"+          , Space+          , Str "hear"+          , Space+          , Str "that,"+          , Space+          , Str "eh?"+          , Space+          , Str "That\8217s"+          , Space+          , Str "what"+          , Space+          , Str "I\8217m"+          , SoftBreak+          , Str "on"+          , Space+          , Str "about!"+          , Space+          , Str "Did"+          , Space+          , Str "you"+          , Space+          , Str "see"+          , Space+          , Str "him"+          , Space+          , Str "repressing"+          , Space+          , Str "me?"+          , Space+          , Str "You"+          , Space+          , Str "saw"+          , Space+          , Str "him,"+          , Space+          , Str "Didn\8217t"+          , Space+          , Str "you?"+          ]+      , Para+          [ Str "\8212"+          , Space+          , Str "Monty"+          , Space+          , Str "Python"+          , Space+          , Str "and"+          , Space+          , Str "the"+          , Space+          , Str "Holy"+          , Space+          , Str "Grail"+          ]+      ]+  , Div+      ( "roads" , [ "movie" ] , [ ( "wrapper" , "1" ) ] )+      [ BlockQuote+          [ Para+              [ Str "Roads?"+              , Space+              , Str "Where"+              , Space+              , Str "we\8217re"+              , Space+              , Str "going,"+              , Space+              , Str "we"+              , Space+              , Str "don\8217t"+              , Space+              , Str "need"+              , Space+              , Str "roads."+              ]+          , Para+              [ Str "\8212"+              , Space+              , Str "Dr."+              , Space+              , Str "Emmett"+              , Space+              , Str "Brown"+              ]+          ]+      ]+  , Header 2 ( "_pass" , [] , [] ) [ Str "Pass" ]+  , Para [ Str "pass" , Space , Emph [ Str "through" ] ]+  , Header+      2+      ( "_open_block" , [] , [] )+      [ Str "Open" , Space , Str "block" ]+  , Div+      ( "" , [] , [ ( "key" , "a value" ) ] )+      [ Div+          ( "" , [ "title" ] , [] )+          [ Para [ Str "A" , Space , Str "title." ] ]+      , Para+          [ Str "Any"+          , Space+          , Str "content"+          , Space+          , Str "can"+          , Space+          , Str "go"+          , Space+          , Str "here:"+          ]+      , OrderedList+          ( 1 , DefaultStyle , DefaultDelim )+          [ [ Para [ Str "one" ] ] , [ Para [ Str "two" ] ] ]+      ]+  , Header 2 ( "_anchor" , [] , [] ) [ Str "Anchor" ]+  , Div+      ( "goals" , [] , [ ( "wrapper" , "1" ) ] )+      [ BulletList+          [ [ Para [ Str "one" ] ] , [ Para [ Str "two" ] ] ]+      ]+  , Header 2 ( "_breaks" , [] , [] ) [ Str "Breaks" ]+  , Para+      [ Str "Asciidoc"+      , Space+      , Str "thematic"+      , Space+      , Str "break:"+      ]+  , HorizontalRule+  , Para [ Str "Markdown" , Space , Str "style:" ]+  , HorizontalRule+  , HorizontalRule+  , HorizontalRule+  , HorizontalRule+  , Para [ Str "Page" , Space , Str "breaks:" ]+  , Div+      ( "" , [ "page-break" ] , [ ( "wrapper" , "1" ) ] )+      [ HorizontalRule ]+  , Div+      ( ""+      , [ "page-break" ]+      , [ ( "options" , "always" ) , ( "wrapper" , "1" ) ]+      )+      [ HorizontalRule ]+  , Header 2 ( "_list" , [] , [] ) [ Str "List" ]+  , BulletList+      [ [ Para+            [ Str "Edgar" , Space , Str "Allan" , Space , Str "Poe" ]+        ]+      , [ Para+            [ Str "Sheri" , Space , Str "S." , Space , Str "Tepper" ]+        ]+      , [ Para [ Str "Bill" , Space , Str "Bryson" ] ]+      ]+  , Div+      ( "" , [] , [] )+      [ Div+          ( "" , [ "title" ] , [] )+          [ Para+              [ Str "Kizmet\8217s"+              , Space+              , Str "Favorite"+              , Space+              , Str "Authors"+              ]+          ]+      , BulletList+          [ [ Para+                [ Str "Edgar"+                , Space+                , Str "Allan"+                , Space+                , Str "Poe"+                ]+            ]+          , [ Para+                [ Str "Sheri"+                , Space+                , Str "S."+                , Space+                , Str "Tepper"+                ]+            ]+          , [ Para [ Str "Bill" , Space , Str "Bryson" ] ]+          ]+      ]+  , BulletList+      [ [ Para+            [ Str "Edgar" , Space , Str "Allan" , Space , Str "Poe" ]+        ]+      , [ Para+            [ Str "Sheri" , Space , Str "S." , Space , Str "Tepper" ]+        ]+      , [ Para [ Str "Bill" , Space , Str "Bryson" ] ]+      ]+  , OrderedList+      ( 1 , DefaultStyle , DefaultDelim )+      [ [ Para [ Str "Nested" , Space , Str "list" ]+        , BulletList+            [ [ Para+                  [ Str "West"+                  , Space+                  , Str "wood"+                  , Space+                  , Str "maze"+                  ]+              , BulletList+                  [ [ Para [ Str "Maze" , Space , Str "heart" ]+                    , BulletList+                        [ [ Para+                              [ Str "Reflection" , Space , Str "pool" ]+                          ]+                        ]+                    ]+                  , [ Para [ Str "Secret" , Space , Str "exit" ] ]+                  ]+              ]+            , [ Para+                  [ Str "Level"+                  , Space+                  , Str "1"+                  , Space+                  , Str "list"+                  , Space+                  , Str "item"+                  ]+              , BulletList+                  [ [ Para+                        [ Str "Level"+                        , Space+                        , Str "2"+                        , Space+                        , Str "list"+                        , Space+                        , Str "item"+                        ]+                    , BulletList+                        [ [ Para+                              [ Str "Level"+                              , Space+                              , Str "3"+                              , Space+                              , Str "list"+                              , Space+                              , Str "item"+                              ]+                          , BulletList+                              [ [ Para+                                    [ Str "Level"+                                    , Space+                                    , Str "4"+                                    , Space+                                    , Str "list"+                                    , Space+                                    , Str "item"+                                    ]+                                , BulletList+                                    [ [ Para+                                          [ Str "Level"+                                          , Space+                                          , Str "5"+                                          , Space+                                          , Str "list"+                                          , Space+                                          , Str "item"+                                          ]+                                      , BulletList+                                          [ [ Para [ Str "etc." ] ] ]+                                      ]+                                    ]+                                ]+                              ]+                          ]+                        ]+                    ]+                  ]+              ]+            , [ Para+                  [ Str "Level"+                  , Space+                  , Str "1"+                  , Space+                  , Str "list"+                  , Space+                  , Str "item"+                  ]+              ]+            ]+        ]+      ]+  , BulletList+      [ [ Para [ Str "one" ] ]+      , [ Para [ Str "two" ] ]+      , [ Para [ Str "three" ] ]+      ]+  , OrderedList+      ( 1 , DefaultStyle , DefaultDelim )+      [ [ Para [ Str "Protons" ] ]+      , [ Para [ Str "Electrons" ] ]+      , [ Para [ Str "Neutrons" ] ]+      ]+  , OrderedList+      ( 1 , DefaultStyle , DefaultDelim )+      [ [ Para [ Str "Protons" ] ]+      , [ Para [ Str "Electrons" ] ]+      , [ Para [ Str "Neutrons" ] ]+      ]+  , Para+      [ Str "Start" , Space , Str "with" , Space , Str "4:" ]+  , OrderedList+      ( 4 , DefaultStyle , DefaultDelim )+      [ [ Para [ Str "Step" , Space , Str "four" ] ]+      , [ Para [ Str "Step" , Space , Str "five" ] ]+      , [ Para [ Str "Step" , Space , Str "six" ] ]+      ]+  , Para [ Str "or" ]+  , OrderedList+      ( 4 , DefaultStyle , DefaultDelim )+      [ [ Para [ Str "Step" , Space , Str "four" ] ]+      , [ Para [ Str "Step" , Space , Str "five" ] ]+      , [ Para [ Str "Step" , Space , Str "six" ] ]+      ]+  , Para [ Str "Reversed:" ]+  , Div+      ( "" , [] , [ ( "options" , "reversed" ) ] )+      [ Div+          ( "" , [ "title" ] , [] )+          [ Para+              [ Str "Parts"+              , Space+              , Str "of"+              , Space+              , Str "an"+              , Space+              , Str "atom"+              ]+          ]+      , OrderedList+          ( 1 , DefaultStyle , DefaultDelim )+          [ [ Para [ Str "Protons" ] ]+          , [ Para [ Str "Electrons" ] ]+          , [ Para [ Str "Neutrons" ] ]+          ]+      ]+  , Para [ Str "Nested" ]+  , OrderedList+      ( 1 , DefaultStyle , DefaultDelim )+      [ [ Para [ Str "Step" , Space , Str "1" ] ]+      , [ Para [ Str "Step" , Space , Str "2" ]+        , OrderedList+            ( 1 , DefaultStyle , DefaultDelim )+            [ [ Para [ Str "Step" , Space , Str "2a" ] ]+            , [ Para [ Str "Step" , Space , Str "2b" ] ]+            ]+        ]+      , [ Para [ Str "Step" , Space , Str "3" ] ]+      ]+  , Para [ Str "Mixed" , Space , Str "nested" ]+  , OrderedList+      ( 1 , DefaultStyle , DefaultDelim )+      [ [ Para [ Str "Linux" ]+        , BulletList+            [ [ Para [ Str "Fedora" ] ]+            , [ Para [ Str "Ubuntu" ] ]+            , [ Para [ Str "Slackware" ] ]+            ]+        ]+      , [ Para [ Str "BSD" ]+        , BulletList+            [ [ Para [ Str "FreeBSD" ] ] , [ Para [ Str "NetBSD" ] ] ]+        ]+      ]+  , Para [ Str "With" , Space , Str "spacing" ]+  , OrderedList+      ( 1 , DefaultStyle , DefaultDelim )+      [ [ Para [ Str "Linux" ]+        , BulletList+            [ [ Para [ Str "Fedora" ] ]+            , [ Para [ Str "Ubuntu" ] ]+            , [ Para [ Str "Slackware" ] ]+            ]+        ]+      , [ Para [ Str "BSD" ]+        , BulletList+            [ [ Para [ Str "FreeBSD" ] ] , [ Para [ Str "NetBSD" ] ] ]+        ]+      ]+  , Para+      [ Str "With" , Space , Str "number" , Space , Str "styles" ]+  , OrderedList+      ( 5 , LowerRoman , DefaultDelim )+      [ [ Para [ Str "Five" ] ]+      , [ Para [ Str "Six" ]+        , OrderedList+            ( 1 , LowerAlpha , DefaultDelim )+            [ [ Para [ Str "a" ] ]+            , [ Para [ Str "b" ] ]+            , [ Para [ Str "c" ] ]+            ]+        ]+      , [ Para [ Str "Seven" ] ]+      ]+  , Para [ Str "Checklist" ]+  , BulletList+      [ [ Para [ Str "\9746" , Space , Str "checked" ] ]+      , [ Para+            [ Str "\9746" , Space , Str "also" , Space , Str "checked" ]+        ]+      , [ Para+            [ Str "\9744" , Space , Str "not" , Space , Str "checked" ]+        ]+      , [ Para+            [ Str "normal" , Space , Str "list" , Space , Str "item" ]+        ]+      ]+  , Para+      [ Str "Separate"+      , Space+      , Str "lists"+      , Space+      , Str "with"+      , Space+      , Str "block"+      , Space+      , Str "attribute"+      ]+  , BulletList+      [ [ Para [ Str "Apples" ] ]+      , [ Para [ Str "Oranges" ]+        , OrderedList+            ( 1 , DefaultStyle , DefaultDelim )+            [ [ Para [ Str "Wash" ] ] , [ Para [ Str "Slice" ] ] ]+        ]+      ]+  , Para [ Str "Multiline" , Space , Str "items" ]+  , BulletList+      [ [ Para+            [ Str "Blah"+            , Space+            , Str "blah."+            , SoftBreak+            , Str "Blah"+            , Space+            , Str "blah."+            ]+        ]+      , [ Para+            [ Str "The"+            , Space+            , Str "document"+            , Space+            , Str "header"+            , Space+            , Str "in"+            , Space+            , Str "AsciiDoc"+            , Space+            , Str "is"+            , Space+            , Str "optional."+            , SoftBreak+            , Str "If"+            , Space+            , Str "present,"+            , Space+            , Str "it"+            , Space+            , Str "must"+            , Space+            , Str "start"+            , Space+            , Str "with"+            , Space+            , Str "a"+            , Space+            , Str "document"+            , Space+            , Str "title."+            ]+        ]+      ]+  , BulletList+      [ [ Para+            [ Str "Optional"+            , Space+            , Str "author"+            , Space+            , Str "and"+            , Space+            , Str "revision"+            , Space+            , Str "information"+            , Space+            , Str "lines"+            , SoftBreak+            , Str "immediately"+            , Space+            , Str "follow"+            , Space+            , Str "the"+            , Space+            , Str "document"+            , Space+            , Str "title."+            ]+        ]+      ]+  , BulletList+      [ [ Para+            [ Str "The"+            , Space+            , Str "document"+            , Space+            , Str "header"+            , Space+            , Str "must"+            , Space+            , Str "be"+            , Space+            , Str "separated"+            , Space+            , Str "from"+            , SoftBreak+            , Str "the"+            , Space+            , Str "remainder"+            , Space+            , Str "of"+            , Space+            , Str "the"+            , Space+            , Str "document"+            , Space+            , Str "by"+            , Space+            , Str "one"+            , Space+            , Str "or"+            , Space+            , Str "more"+            , SoftBreak+            , Str "empty"+            , Space+            , Str "lines"+            , Space+            , Str "and"+            , Space+            , Str "it"+            , Space+            , Str "cannot"+            , Space+            , Str "contain"+            , Space+            , Str "empty"+            , Space+            , Str "lines."+            ]+        ]+      ]+  , Para [ Str "Complex" , Space , Str "item" ]+  , BulletList+      [ [ Para+            [ Str "The"+            , Space+            , Str "header"+            , Space+            , Str "in"+            , Space+            , Str "AsciiDoc"+            , Space+            , Str "must"+            , Space+            , Str "start"+            , Space+            , Str "with"+            , Space+            , Str "a"+            , Space+            , Str "document"+            , Space+            , Str "title."+            ]+        , CodeBlock ( "" , [] , [] ) "= Document Title"+        , Para+            [ Str "Keep"+            , Space+            , Str "in"+            , Space+            , Str "mind"+            , Space+            , Str "that"+            , Space+            , Str "the"+            , Space+            , Str "header"+            , Space+            , Str "is"+            , Space+            , Str "optional."+            ]+        ]+      , [ Para+            [ Str "Optional"+            , Space+            , Str "author"+            , Space+            , Str "and"+            , Space+            , Str "revision"+            , Space+            , Str "information"+            , Space+            , Str "lines"+            , Space+            , Str "immediately"+            , Space+            , Str "follow"+            , Space+            , Str "the"+            , Space+            , Str "document"+            , SoftBreak+            , Str "title."+            ]+        , CodeBlock+            ( "" , [] , [] )+            "= Document Title\nDoc Writer <doc.writer@asciidoc.org>\nv1.0, 2022-01-01"+        ]+      , [ Para [ Str "Second" , Space , Str "item" ] ]+      ]+  , Para+      [ Str "Empty"+      , Space+      , Str "principle"+      , Space+      , Str "element:"+      ]+  , OrderedList+      ( 1 , DefaultStyle , DefaultDelim )+      [ [ Para [] , CodeBlock ( "" , [] , [] ) "test" ] ]+  , Header 2 ( "_table" , [] , [] ) [ Str "Table" ]+  , Header+      3+      ( "_simple_with_column_specs" , [] , [] )+      [ Str "Simple"+      , Space+      , Str "with"+      , Space+      , Str "column"+      , Space+      , Str "specs"+      ]+  , Table+      ( "" , [] , [] )+      (Caption Nothing [])+      [ ( AlignDefault , ColWidth 0.375 )+      , ( AlignDefault , ColWidth 0.25 )+      , ( AlignDefault , ColWidth 0.375 )+      ]+      (TableHead+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Str "This"+                     , Space+                     , Str "content"+                     , Space+                     , Str "is"+                     , Space+                     , Str "placed"+                     , Space+                     , Str "in"+                     , Space+                     , Str "the"+                     , Space+                     , Str "first"+                     , Space+                     , Str "cell"+                     , Space+                     , Str "of"+                     , Space+                     , Str "column"+                     , Space+                     , Str "1"+                     ]+                 ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Str "This"+                     , Space+                     , Str "line"+                     , Space+                     , Str "starts"+                     , Space+                     , Str "with"+                     , Space+                     , Str "a"+                     , Space+                     , Str "vertical"+                     , Space+                     , Str "bar"+                     , Space+                     , Str "so"+                     , Space+                     , Str "this"+                     , Space+                     , Str "content"+                     , Space+                     , Str "is"+                     , Space+                     , Str "placed"+                     , Space+                     , Str "in"+                     , Space+                     , Str "a"+                     , Space+                     , Str "new"+                     , Space+                     , Str "cell"+                     , Space+                     , Str "in"+                     , SoftBreak+                     , Str "column"+                     , Space+                     , Str "2"+                     ]+                 ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Str "When"+                     , Space+                     , Str "the"+                     , Space+                     , Str "processor"+                     , Space+                     , Str "encounters"+                     , Space+                     , Str "a"+                     , Space+                     , Str "whitespace"+                     , Space+                     , Str "followed"+                     , Space+                     , Str "by"+                     , Space+                     , Str "a"+                     , Space+                     , Str "vertical"+                     , Space+                     , Str "bar"+                     , Space+                     , Str "it"+                     , SoftBreak+                     , Str "ends"+                     , Space+                     , Str "the"+                     , Space+                     , Str "previous"+                     , Space+                     , Str "cell"+                     , Space+                     , Str "and"+                     , Space+                     , Str "starts"+                     , Space+                     , Str "a"+                     , Space+                     , Str "new"+                     , Space+                     , Str "cell"+                     ]+                 ]+             ]+         ])+      [ TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [] ]+      (TableFoot ( "" , [] , [] ) [])+  , Header+      3+      ( "_repeated_column_in_specs" , [] , [] )+      [ Str "Repeated"+      , Space+      , Str "column"+      , Space+      , Str "in"+      , Space+      , Str "specs"+      ]+  , Table+      ( "" , [] , [] )+      (Caption Nothing [])+      [ ( AlignDefault , ColWidthDefault )+      , ( AlignDefault , ColWidthDefault )+      ]+      (TableHead+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignRight+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Strong+                         [ Str "This"+                         , Space+                         , Str "cell\8217s"+                         , Space+                         , Str "specifier"+                         , Space+                         , Str "indicates"+                         , Space+                         , Str "that"+                         , Space+                         , Str "this"+                         , Space+                         , Str "cell\8217s"+                         , Space+                         , Str "content"+                         , Space+                         , Str "is"+                         , Space+                         , Str "right-aligned"+                         , Space+                         , Str "and"+                         , Space+                         , Str "bold."+                         ]+                     ]+                 ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Str "The"+                     , Space+                     , Str "cell"+                     , Space+                     , Str "specifier"+                     , Space+                     , Str "on"+                     , Space+                     , Str "this"+                     , Space+                     , Str "cell"+                     , Space+                     , Str "hasn\8217t"+                     , Space+                     , Str "been"+                     , Space+                     , Str "set"+                     , Space+                     , Str "explicitly,"+                     , Space+                     , Str "so"+                     , Space+                     , Str "the"+                     , Space+                     , Str "default"+                     , SoftBreak+                     , Str "properties"+                     , Space+                     , Str "are"+                     , Space+                     , Str "applied."+                     ]+                 ]+             ]+         ])+      [ TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [] ]+      (TableFoot ( "" , [] , [] ) [])+  , Header+      3+      ( "_simple_without_column_specs" , [] , [] )+      [ Str "Simple"+      , Space+      , Str "without"+      , Space+      , Str "column"+      , Space+      , Str "specs"+      ]+  , Table+      ( "" , [] , [] )+      (Caption Nothing [])+      [ ( AlignDefault , ColWidthDefault )+      , ( AlignDefault , ColWidthDefault )+      ]+      (TableHead+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Str "Column"+                     , Space+                     , Str "1,"+                     , Space+                     , Str "header"+                     , Space+                     , Str "row"+                     ]+                 ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Str "Column"+                     , Space+                     , Str "2,"+                     , Space+                     , Str "header"+                     , Space+                     , Str "row"+                     ]+                 ]+             ]+         ])+      [ TableBody+          ( "" , [] , [] )+          (RowHeadColumns 0)+          []+          [ Row+              ( "" , [] , [] )+              [ Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Para+                      [ Str "Cell"+                      , Space+                      , Str "in"+                      , Space+                      , Str "column"+                      , Space+                      , Str "1,"+                      , Space+                      , Str "row"+                      , Space+                      , Str "2"+                      ]+                  ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Para+                      [ Str "Cell"+                      , Space+                      , Str "in"+                      , Space+                      , Str "column"+                      , Space+                      , Str "2,"+                      , Space+                      , Str "row"+                      , Space+                      , Str "2"+                      ]+                  ]+              ]+          ]+      ]+      (TableFoot+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Str "Cell"+                     , Space+                     , Str "in"+                     , Space+                     , Str "column"+                     , Space+                     , Str "1,"+                     , Space+                     , Str "row"+                     , Space+                     , Str "3"+                     ]+                 ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Str "Cell"+                     , Space+                     , Str "in"+                     , Space+                     , Str "column"+                     , Space+                     , Str "2,"+                     , Space+                     , Str "row"+                     , Space+                     , Str "3"+                     ]+                 ]+             ]+         ])+  , Header+      3+      ( "_with_caption" , [] , [] )+      [ Str "With" , Space , Str "caption" ]+  , Table+      ( "" , [] , [] )+      (Caption+         Nothing+         [ Plain+             [ Str "My" , Space , Str "cool" , Space , Str "table." ]+         ])+      [ ( AlignDefault , ColWidthDefault )+      , ( AlignDefault , ColWidthDefault )+      ]+      (TableHead+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Str "Column"+                     , Space+                     , Str "1,"+                     , Space+                     , Str "header"+                     , Space+                     , Str "row"+                     ]+                 ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Str "Column"+                     , Space+                     , Str "2,"+                     , Space+                     , Str "header"+                     , Space+                     , Str "row"+                     ]+                 ]+             ]+         ])+      [ TableBody+          ( "" , [] , [] )+          (RowHeadColumns 0)+          []+          [ Row+              ( "" , [] , [] )+              [ Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Para+                      [ Str "Cell"+                      , Space+                      , Str "in"+                      , Space+                      , Str "column"+                      , Space+                      , Str "1,"+                      , Space+                      , Str "row"+                      , Space+                      , Str "2"+                      ]+                  ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Para+                      [ Str "Cell"+                      , Space+                      , Str "in"+                      , Space+                      , Str "column"+                      , Space+                      , Str "2,"+                      , Space+                      , Str "row"+                      , Space+                      , Str "2"+                      ]+                  ]+              ]+          ]+      ]+      (TableFoot+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Str "Cell"+                     , Space+                     , Str "in"+                     , Space+                     , Str "column"+                     , Space+                     , Str "1,"+                     , Space+                     , Str "row"+                     , Space+                     , Str "3"+                     ]+                 ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Str "Cell"+                     , Space+                     , Str "in"+                     , Space+                     , Str "column"+                     , Space+                     , Str "2,"+                     , Space+                     , Str "row"+                     , Space+                     , Str "3"+                     ]+                 ]+             ]+         ])+  , Header+      3+      ( "_no_header" , [] , [] )+      [ Str "No" , Space , Str "header" ]+  , Para+      [ Str "By"+      , Space+      , Str "default"+      , Space+      , Str "the"+      , Space+      , Str "first"+      , Space+      , Str "line"+      , Space+      , Str "should"+      , Space+      , Str "turn"+      , Space+      , Str "into"+      , Space+      , Str "the"+      , Space+      , Str "header,"+      , Space+      , Str "but"+      , Space+      , Str "this"+      , SoftBreak+      , Str "can"+      , Space+      , Str "be"+      , Space+      , Str "disabled:"+      ]+  , Table+      ( "" , [] , [] )+      (Caption Nothing [])+      [ ( AlignDefault , ColWidthDefault )+      , ( AlignDefault , ColWidthDefault )+      ]+      (TableHead ( "" , [] , [] ) [])+      [ TableBody+          ( "" , [] , [] )+          (RowHeadColumns 0)+          []+          [ Row+              ( "" , [] , [] )+              [ Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Para+                      [ Str "Cell"+                      , Space+                      , Str "in"+                      , Space+                      , Str "column"+                      , Space+                      , Str "1,"+                      , Space+                      , Str "row"+                      , Space+                      , Str "1"+                      ]+                  ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Para+                      [ Str "Cell"+                      , Space+                      , Str "in"+                      , Space+                      , Str "column"+                      , Space+                      , Str "2,"+                      , Space+                      , Str "row"+                      , Space+                      , Str "1"+                      ]+                  ]+              ]+          ]+      ]+      (TableFoot+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Str "Cell"+                     , Space+                     , Str "in"+                     , Space+                     , Str "column"+                     , Space+                     , Str "1,"+                     , Space+                     , Str "row"+                     , Space+                     , Str "2"+                     ]+                 ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Str "Cell"+                     , Space+                     , Str "in"+                     , Space+                     , Str "column"+                     , Space+                     , Str "2,"+                     , Space+                     , Str "row"+                     , Space+                     , Str "2"+                     ]+                 ]+             ]+         ])+  , Para+      [ Str "And"+      , Space+      , Str "also"+      , Space+      , Str "explicitly"+      , Space+      , Str "enabled:"+      ]+  , Table+      ( "" , [] , [] )+      (Caption Nothing [])+      [ ( AlignDefault , ColWidthDefault )+      , ( AlignDefault , ColWidthDefault )+      ]+      (TableHead+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Str "Cell" , Space , Str "A1" ] ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Str "Cell" , Space , Str "B1" ] ]+             ]+         ])+      [ TableBody+          ( "" , [] , [] )+          (RowHeadColumns 0)+          []+          [ Row+              ( "" , [] , [] )+              [ Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Para [ Str "Cell" , Space , Str "A2" ] ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Para [ Str "Cell" , Space , Str "B2" ] ]+              ]+          ]+      ]+      (TableFoot+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Str "Cell" , Space , Str "A3" ] ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Str "Cell" , Space , Str "B3" ] ]+             ]+         ])+  , Header 3 ( "_footer" , [] , [] ) [ Str "Footer" ]+  , Table+      ( "" , [] , [] )+      (Caption Nothing [])+      [ ( AlignDefault , ColWidth 0.4 )+      , ( AlignDefault , ColWidth 0.4 )+      , ( AlignDefault , ColWidth 0.2 )+      ]+      (TableHead+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Str "Column"+                     , Space+                     , Str "1,"+                     , Space+                     , Str "header"+                     , Space+                     , Str "row"+                     ]+                 ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Str "Column"+                     , Space+                     , Str "2,"+                     , Space+                     , Str "header"+                     , Space+                     , Str "row"+                     ]+                 ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Str "Column"+                     , Space+                     , Str "3,"+                     , Space+                     , Str "header"+                     , Space+                     , Str "row"+                     ]+                 ]+             ]+         ])+      [ TableBody+          ( "" , [] , [] )+          (RowHeadColumns 0)+          []+          [ Row+              ( "" , [] , [] )+              [ Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Para+                      [ Str "Cell"+                      , Space+                      , Str "in"+                      , Space+                      , Str "column"+                      , Space+                      , Str "1,"+                      , Space+                      , Str "row"+                      , Space+                      , Str "2"+                      ]+                  ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Para+                      [ Str "Cell"+                      , Space+                      , Str "in"+                      , Space+                      , Str "column"+                      , Space+                      , Str "2,"+                      , Space+                      , Str "row"+                      , Space+                      , Str "2"+                      ]+                  ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Para+                      [ Str "Cell"+                      , Space+                      , Str "in"+                      , Space+                      , Str "column"+                      , Space+                      , Str "3,"+                      , Space+                      , Str "row"+                      , Space+                      , Str "2"+                      ]+                  ]+              ]+          ]+      ]+      (TableFoot+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Str "Column"+                     , Space+                     , Str "1,"+                     , Space+                     , Str "footer"+                     , Space+                     , Str "row"+                     ]+                 ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Str "Column"+                     , Space+                     , Str "2,"+                     , Space+                     , Str "footer"+                     , Space+                     , Str "row"+                     ]+                 ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Str "Column"+                     , Space+                     , Str "3,"+                     , Space+                     , Str "footer"+                     , Space+                     , Str "row"+                     ]+                 ]+             ]+         ])+  , Para [ Str "or" ]+  , Table+      ( "" , [] , [] )+      (Caption Nothing [])+      [ ( AlignDefault , ColWidthDefault )+      , ( AlignDefault , ColWidthDefault )+      ]+      (TableHead+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Str "Column"+                     , Space+                     , Str "1,"+                     , Space+                     , Str "header"+                     , Space+                     , Str "row"+                     ]+                 ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Str "Column"+                     , Space+                     , Str "2,"+                     , Space+                     , Str "header"+                     , Space+                     , Str "row"+                     ]+                 ]+             ]+         ])+      [ TableBody+          ( "" , [] , [] )+          (RowHeadColumns 0)+          []+          [ Row+              ( "" , [] , [] )+              [ Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Para+                      [ Str "Cell"+                      , Space+                      , Str "in"+                      , Space+                      , Str "column"+                      , Space+                      , Str "1,"+                      , Space+                      , Str "row"+                      , Space+                      , Str "2"+                      ]+                  ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Para+                      [ Str "Cell"+                      , Space+                      , Str "in"+                      , Space+                      , Str "column"+                      , Space+                      , Str "2,"+                      , Space+                      , Str "row"+                      , Space+                      , Str "2"+                      ]+                  ]+              ]+          , Row+              ( "" , [] , [] )+              [ Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Para+                      [ Str "Cell"+                      , Space+                      , Str "in"+                      , Space+                      , Str "column"+                      , Space+                      , Str "1,"+                      , Space+                      , Str "row"+                      , Space+                      , Str "3"+                      ]+                  ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Para+                      [ Str "Cell"+                      , Space+                      , Str "in"+                      , Space+                      , Str "column"+                      , Space+                      , Str "2,"+                      , Space+                      , Str "row"+                      , Space+                      , Str "3"+                      ]+                  ]+              ]+          ]+      ]+      (TableFoot+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Str "Column"+                     , Space+                     , Str "1,"+                     , Space+                     , Str "footer"+                     , Space+                     , Str "row"+                     ]+                 ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Str "Column"+                     , Space+                     , Str "2,"+                     , Space+                     , Str "footer"+                     , Space+                     , Str "row"+                     ]+                 ]+             ]+         ])+  , Header 3 ( "_alignment" , [] , [] ) [ Str "Alignment" ]+  , Table+      ( "" , [] , [] )+      (Caption Nothing [])+      [ ( AlignDefault , ColWidthDefault )+      , ( AlignDefault , ColWidthDefault )+      ]+      (TableHead+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Str "Column" , Space , Str "Name" ] ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Str "Column" , Space , Str "Name" ] ]+             ]+         ])+      [ TableBody+          ( "" , [] , [] )+          (RowHeadColumns 0)+          []+          [ Row+              ( "" , [] , [] )+              [ Cell+                  ( "" , [] , [] )+                  AlignCenter+                  (RowSpan 1)+                  (ColSpan 2)+                  [ Para+                      [ Str "This"+                      , Space+                      , Str "cell"+                      , Space+                      , Str "spans"+                      , Space+                      , Str "two"+                      , Space+                      , Str "columns,"+                      , Space+                      , Str "and"+                      , Space+                      , Str "its"+                      , Space+                      , Str "content"+                      , Space+                      , Str "is"+                      , Space+                      , Str "horizontally"+                      , Space+                      , Str "centered"+                      , Space+                      , Str "because"+                      , Space+                      , Str "the"+                      , SoftBreak+                      , Str "cell"+                      , Space+                      , Str "specifier"+                      , Space+                      , Str "includes"+                      , Space+                      , Str "the"+                      , Space+                      , Code ( "" , [] , [] ) "^"+                      , Space+                      , Str "operator."+                      ]+                  ]+              ]+          ]+      ]+      (TableFoot+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignCenter+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Str "This"+                     , Space+                     , Str "content"+                     , Space+                     , Str "is"+                     , Space+                     , Str "duplicated"+                     , Space+                     , Str "in"+                     , Space+                     , Str "two"+                     , Space+                     , Str "adjacent"+                     , Space+                     , Str "columns."+                     , SoftBreak+                     , Str "Its"+                     , Space+                     , Str "content"+                     , Space+                     , Str "is"+                     , Space+                     , Str "horizontally"+                     , Space+                     , Str "centered"+                     , Space+                     , Str "because"+                     , Space+                     , Str "the"+                     , Space+                     , Str "cell"+                     , Space+                     , Str "specifier"+                     , SoftBreak+                     , Str "includes"+                     , Space+                     , Str "the"+                     , Space+                     , Code ( "" , [] , [] ) "^"+                     , Space+                     , Str "operator."+                     ]+                 ]+             , Cell+                 ( "" , [] , [] )+                 AlignCenter+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Str "This"+                     , Space+                     , Str "content"+                     , Space+                     , Str "is"+                     , Space+                     , Str "duplicated"+                     , Space+                     , Str "in"+                     , Space+                     , Str "two"+                     , Space+                     , Str "adjacent"+                     , Space+                     , Str "columns."+                     , SoftBreak+                     , Str "Its"+                     , Space+                     , Str "content"+                     , Space+                     , Str "is"+                     , Space+                     , Str "horizontally"+                     , Space+                     , Str "centered"+                     , Space+                     , Str "because"+                     , Space+                     , Str "the"+                     , Space+                     , Str "cell"+                     , Space+                     , Str "specifier"+                     , SoftBreak+                     , Str "includes"+                     , Space+                     , Str "the"+                     , Space+                     , Code ( "" , [] , [] ) "^"+                     , Space+                     , Str "operator."+                     ]+                 ]+             ]+         ])+  , Header+      3+      ( "_multiple_paragraphs_in_cells" , [] , [] )+      [ Str "Multiple"+      , Space+      , Str "paragraphs"+      , Space+      , Str "in"+      , Space+      , Str "cells"+      ]+  , Table+      ( "" , [] , [] )+      (Caption Nothing [])+      [ ( AlignDefault , ColWidthDefault ) ]+      (TableHead+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Str "Single"+                     , Space+                     , Str "paragraph"+                     , Space+                     , Str "on"+                     , Space+                     , Str "row"+                     , Space+                     , Str "1"+                     ]+                 ]+             ]+         ])+      [ TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [] ]+      (TableFoot+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Str "First"+                     , Space+                     , Str "paragraph"+                     , Space+                     , Str "on"+                     , Space+                     , Str "row"+                     , Space+                     , Str "2"+                     ]+                 , Para+                     [ Str "Second"+                     , Space+                     , Str "paragraph"+                     , Space+                     , Str "on"+                     , Space+                     , Str "row"+                     , Space+                     , Str "2"+                     ]+                 ]+             ]+         ])+  , Header+      3+      ( "_complex_table" , [] , [] )+      [ Str "Complex" , Space , Str "table" ]+  , Table+      ( "" , [] , [] )+      (Caption Nothing [])+      [ ( AlignDefault , ColWidthDefault )+      , ( AlignDefault , ColWidthDefault )+      ]+      (TableHead+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignRight+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Code ( "" , [] , [] ) "This"+                     , Space+                     , Code ( "" , [] , [] ) "content"+                     , Space+                     , Code ( "" , [] , [] ) "is"+                     , Space+                     , Code ( "" , [] , [] ) "duplicated"+                     , Space+                     , Code ( "" , [] , [] ) "across"+                     , Space+                     , Code ( "" , [] , [] ) "two"+                     , Space+                     , Code ( "" , [] , [] ) "columns."+                     ]+                 , Para+                     [ Code ( "" , [] , [] ) "It"+                     , Space+                     , Code ( "" , [] , [] ) "is"+                     , Space+                     , Code ( "" , [] , [] ) "aligned"+                     , Space+                     , Code ( "" , [] , [] ) "right"+                     , Space+                     , Code ( "" , [] , [] ) "horizontally."+                     ]+                 , Para+                     [ Code ( "" , [] , [] ) "And"+                     , Space+                     , Code ( "" , [] , [] ) "it"+                     , Space+                     , Code ( "" , [] , [] ) "is"+                     , Space+                     , Code ( "" , [] , [] ) "monospaced."+                     ]+                 ]+             , Cell+                 ( "" , [] , [] )+                 AlignRight+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Code ( "" , [] , [] ) "This"+                     , Space+                     , Code ( "" , [] , [] ) "content"+                     , Space+                     , Code ( "" , [] , [] ) "is"+                     , Space+                     , Code ( "" , [] , [] ) "duplicated"+                     , Space+                     , Code ( "" , [] , [] ) "across"+                     , Space+                     , Code ( "" , [] , [] ) "two"+                     , Space+                     , Code ( "" , [] , [] ) "columns."+                     ]+                 , Para+                     [ Code ( "" , [] , [] ) "It"+                     , Space+                     , Code ( "" , [] , [] ) "is"+                     , Space+                     , Code ( "" , [] , [] ) "aligned"+                     , Space+                     , Code ( "" , [] , [] ) "right"+                     , Space+                     , Code ( "" , [] , [] ) "horizontally."+                     ]+                 , Para+                     [ Code ( "" , [] , [] ) "And"+                     , Space+                     , Code ( "" , [] , [] ) "it"+                     , Space+                     , Code ( "" , [] , [] ) "is"+                     , Space+                     , Code ( "" , [] , [] ) "monospaced."+                     ]+                 ]+             ]+         ])+      [ TableBody+          ( "" , [] , [] )+          (RowHeadColumns 0)+          []+          [ Row+              ( "" , [] , [] )+              [ Cell+                  ( "" , [] , [] )+                  AlignCenter+                  (RowSpan 2)+                  (ColSpan 1)+                  [ Para+                      [ Strong+                          [ Str "This"+                          , Space+                          , Str "cell"+                          , Space+                          , Str "spans"+                          , Space+                          , Str "3"+                          , Space+                          , Str "rows."+                          , Space+                          , Str "The"+                          , Space+                          , Str "content"+                          , Space+                          , Str "is"+                          , Space+                          , Str "centered"+                          , Space+                          , Str "horizontally,"+                          , Space+                          , Str "aligned"+                          , Space+                          , Str "to"+                          , Space+                          , Str "the"+                          , Space+                          , Str "bottom"+                          , Space+                          , Str "of"+                          , Space+                          , Str "the"+                          , Space+                          , Str "cell,"+                          , Space+                          , Str "and"+                          , Space+                          , Str "strong."+                          ]+                      ]+                  ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Para+                      [ Emph+                          [ Str "This"+                          , Space+                          , Str "content"+                          , Space+                          , Str "is"+                          , Space+                          , Str "emphasized."+                          ]+                      ]+                  ]+              ]+          , Row+              ( "" , [] , [] )+              [ Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ CodeBlock+                      ( "" , [] , [] )+                      "This content is aligned to the top of the cell and literal.\n\n"+                  ]+              ]+          ]+      ]+      (TableFoot+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ CodeBlock+                     ( "" , [] , [] ) "puts \"This is a source block!\""+                 ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 []+             ]+         ])+  , Header+      3+      ( "_column_styles" , [] , [] )+      [ Str "Column" , Space , Str "styles" ]+  , Table+      ( "" , [] , [] )+      (Caption Nothing [])+      [ ( AlignDefault , ColWidthDefault )+      , ( AlignDefault , ColWidthDefault )+      ]+      (TableHead+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Code ( "" , [] , [] ) "monospace" ] ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Code ( "" , [] , [] ) "mono" ] ]+             ]+         ])+      [ TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [] ]+      (TableFoot+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Str "default" ] ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Code ( "" , [] , [] ) "mono" ] ]+             ]+         ])+  , Header+      3+      ( "_block_elements_in_cells" , [] , [] )+      [ Str "Block"+      , Space+      , Str "elements"+      , Space+      , Str "in"+      , Space+      , Str "cells"+      ]+  , Table+      ( "" , [] , [] )+      (Caption Nothing [])+      [ ( AlignDefault , ColWidthDefault )+      , ( AlignDefault , ColWidthDefault )+      ]+      (TableHead+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Str "Normal" , Space , Str "Style" ] ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Str "AsciiDoc" , Space , Str "Style" ] ]+             ]+         ])+      [ TableBody+          ( "" , [] , [] )+          (RowHeadColumns 0)+          []+          [ Row+              ( "" , [] , [] )+              [ Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Para+                      [ Str "This"+                      , Space+                      , Str "cell"+                      , Space+                      , Str "isn\8217t"+                      , Space+                      , Str "prefixed"+                      , Space+                      , Str "with"+                      , Space+                      , Str "an"+                      , Space+                      , Code ( "" , [] , [] ) "a"+                      , Str ","+                      , Space+                      , Str "so"+                      , Space+                      , Str "the"+                      , Space+                      , Str "processor"+                      , Space+                      , Str "doesn\8217t"+                      , Space+                      , Str "interpret"+                      , Space+                      , Str "the"+                      , SoftBreak+                      , Str "following"+                      , Space+                      , Str "lines"+                      , Space+                      , Str "as"+                      , Space+                      , Str "an"+                      , Space+                      , Str "AsciiDoc"+                      , Space+                      , Str "list."+                      ]+                  , Para+                      [ Str "*"+                      , Space+                      , Str "List"+                      , Space+                      , Str "item"+                      , Space+                      , Str "1"+                      , SoftBreak+                      , Str "*"+                      , Space+                      , Str "List"+                      , Space+                      , Str "item"+                      , Space+                      , Str "2"+                      , SoftBreak+                      , Str "*"+                      , Space+                      , Str "List"+                      , Space+                      , Str "item"+                      , Space+                      , Str "3"+                      ]+                  ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Para+                      [ Str "This"+                      , Space+                      , Str "cell"+                      , Space+                      , Str "is"+                      , Space+                      , Str "prefixed"+                      , Space+                      , Str "with"+                      , Space+                      , Str "an"+                      , Space+                      , Code ( "" , [] , [] ) "a"+                      , Str ","+                      , Space+                      , Str "so"+                      , Space+                      , Str "the"+                      , Space+                      , Str "processor"+                      , Space+                      , Str "interprets"+                      , Space+                      , Str "the"+                      , Space+                      , Str "following"+                      , Space+                      , Str "lines"+                      , SoftBreak+                      , Str "as"+                      , Space+                      , Str "an"+                      , Space+                      , Str "AsciiDoc"+                      , Space+                      , Str "list."+                      ]+                  , BulletList+                      [ [ Para+                            [ Str "List"+                            , Space+                            , Str "item"+                            , Space+                            , Str "1"+                            ]+                        ]+                      , [ Para+                            [ Str "List"+                            , Space+                            , Str "item"+                            , Space+                            , Str "2"+                            ]+                        ]+                      , [ Para+                            [ Str "List"+                            , Space+                            , Str "item"+                            , Space+                            , Str "3"+                            ]+                        ]+                      ]+                  ]+              ]+          ]+      ]+      (TableFoot+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Str "This"+                     , Space+                     , Str "cell"+                     , Space+                     , Str "isn\8217t"+                     , Space+                     , Str "prefixed"+                     , Space+                     , Str "with"+                     , Space+                     , Str "an"+                     , Space+                     , Code ( "" , [] , [] ) "a"+                     , Str ","+                     , Space+                     , Str "so"+                     , Space+                     , Str "the"+                     , Space+                     , Str "processor"+                     , Space+                     , Str "doesn\8217t"+                     , Space+                     , Str "interpret"+                     , Space+                     , Str "the"+                     , Space+                     , Str "listing"+                     , SoftBreak+                     , Str "block"+                     , Space+                     , Str "delimiters"+                     , Space+                     , Str "or"+                     , Space+                     , Str "the"+                     , Space+                     , Code ( "" , [] , [] ) "source"+                     , Space+                     , Str "style."+                     ]+                 , Para+                     [ Str "----"+                     , SoftBreak+                     , Str "import"+                     , Space+                     , Str "os"+                     , SoftBreak+                     , Str "print"+                     , Space+                     , Str "(\"%s\""+                     , Space+                     , Str "%(os.uname()))"+                     , SoftBreak+                     , Str "----"+                     ]+                 ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Str "This"+                     , Space+                     , Str "cell"+                     , Space+                     , Str "is"+                     , Space+                     , Str "prefixed"+                     , Space+                     , Str "with"+                     , Space+                     , Str "an"+                     , Space+                     , Code ( "" , [] , [] ) "a"+                     , Str ","+                     , Space+                     , Str "so"+                     , Space+                     , Str "the"+                     , Space+                     , Str "listing"+                     , Space+                     , Str "block"+                     , Space+                     , Str "is"+                     , Space+                     , Str "processed"+                     , Space+                     , Str "and"+                     , Space+                     , Str "rendered"+                     , SoftBreak+                     , Str "according"+                     , Space+                     , Str "to"+                     , Space+                     , Str "the"+                     , Space+                     , Code ( "" , [] , [] ) "source"+                     , Space+                     , Str "style"+                     , Space+                     , Str "rules."+                     ]+                 , CodeBlock+                     ( "" , [ "python" ] , [] )+                     "import os\nprint \"%s\" %(os.uname())"+                 ]+             ]+         ])+  , Header+      3+      ( "_col_and_rowspan" , [] , [] )+      [ Str "Col" , Space , Str "and" , Space , Str "rowspan" ]+  , Table+      ( "" , [] , [] )+      (Caption Nothing [])+      [ ( AlignDefault , ColWidthDefault )+      , ( AlignDefault , ColWidthDefault )+      , ( AlignDefault , ColWidthDefault )+      ]+      (TableHead+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Str "Column"+                     , Space+                     , Str "1,"+                     , Space+                     , Str "header"+                     , Space+                     , Str "row"+                     ]+                 ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Str "Column"+                     , Space+                     , Str "2,"+                     , Space+                     , Str "header"+                     , Space+                     , Str "row"+                     ]+                 ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para+                     [ Str "Column"+                     , Space+                     , Str "3,"+                     , Space+                     , Str "header"+                     , Space+                     , Str "row"+                     ]+                 ]+             ]+         ])+      [ TableBody+          ( "" , [] , [] )+          (RowHeadColumns 0)+          []+          [ Row+              ( "" , [] , [] )+              [ Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 2)+                  (ColSpan 2)+                  [ Para+                      [ Str "This"+                      , Space+                      , Str "cell"+                      , Space+                      , Str "spans"+                      , Space+                      , Str "2"+                      , Space+                      , Str "cols"+                      , Space+                      , Str "and"+                      , Space+                      , Str "2"+                      , Space+                      , Str "rows"+                      ]+                  ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Para+                      [ Str "Cell"+                      , Space+                      , Str "in"+                      , Space+                      , Str "column"+                      , Space+                      , Str "3,"+                      , Space+                      , Str "row"+                      , Space+                      , Str "2"+                      ]+                  ]+              ]+          , Row+              ( "" , [] , [] )+              [ Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Para+                      [ Str "Cell"+                      , Space+                      , Str "in"+                      , Space+                      , Str "column"+                      , Space+                      , Str "3,"+                      , Space+                      , Str "row"+                      , Space+                      , Str "3"+                      ]+                  ]+              ]+          ]+      ]+      (TableFoot+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 3)+                 [ Para+                     [ Str "Cell"+                     , Space+                     , Str "in"+                     , Space+                     , Str "column"+                     , Space+                     , Str "1-3,"+                     , Space+                     , Str "row"+                     , Space+                     , Str "4"+                     ]+                 ]+             ]+         ])+  , Header+      3+      ( "_csv_table" , [] , [] )+      [ Str "CSV" , Space , Str "table" ]+  , Table+      ( "" , [] , [] )+      (Caption Nothing [])+      [ ( AlignDefault , ColWidthDefault )+      , ( AlignDefault , ColWidthDefault )+      , ( AlignDefault , ColWidthDefault )+      ]+      (TableHead+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Str "Artist" ] ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Str "Track" ] ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Str "Genre" ] ]+             ]+         ])+      [ TableBody+          ( "" , [] , [] )+          (RowHeadColumns 0)+          []+          [ Row+              ( "" , [] , [] )+              [ Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Para [ Str "Baauer" ] ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Para [ Str "Harlem" , Space , Str "Shake" ] ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Para [ Str "Hip" , Space , Str "Hop" ] ]+              ]+          ]+      ]+      (TableFoot+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Str "The" , Space , Str "Lumineers" ] ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Str "Ho" , Space , Str "Hey" ] ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Str "Folk" , Space , Str "Rock" ] ]+             ]+         ])+  , Para [ Str "or" ]+  , Table+      ( "" , [] , [] )+      (Caption Nothing [])+      [ ( AlignDefault , ColWidthDefault )+      , ( AlignDefault , ColWidthDefault )+      , ( AlignDefault , ColWidthDefault )+      ]+      (TableHead+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Str "Artist" ] ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Str "Track" ] ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Str "Genre" ] ]+             ]+         ])+      [ TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [] ]+      (TableFoot+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Str "Baauer" ] ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Str "Harlem" , Space , Str "Shake" ] ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Str "Hip" , Space , Str "Hop" ] ]+             ]+         ])+  , Header+      3+      ( "_dsv_table" , [] , [] )+      [ Str "DSV" , Space , Str "table" ]+  , Table+      ( "" , [] , [] )+      (Caption Nothing [])+      [ ( AlignDefault , ColWidthDefault )+      , ( AlignDefault , ColWidthDefault )+      , ( AlignDefault , ColWidthDefault )+      ]+      (TableHead+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Str "a" ] ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Str "b" ] ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Str "c" ] ]+             ]+         ])+      [ TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [] ]+      (TableFoot+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Str "d" ] ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Str "e" ] ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Str "f" ] ]+             ]+         ])+  , Para [ Str "or" ]+  , Table+      ( "" , [] , [] )+      (Caption Nothing [])+      [ ( AlignDefault , ColWidthDefault )+      , ( AlignDefault , ColWidthDefault )+      , ( AlignDefault , ColWidthDefault )+      ]+      (TableHead+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Str "Artist" ] ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Str "Track" ] ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Str "Genre" ] ]+             ]+         ])+      [ TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [] ]+      (TableFoot+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Str "Robyn" ] ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Str "Indestructible" ] ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Para [ Str "Dance" ] ]+             ]+         ])+  , Header+      2+      ( "_definition_list" , [] , [] )+      [ Str "Definition" , Space , Str "list" ]+  , DefinitionList+      [ ( [ Str "CPU" ]+        , [ [ Para+                [ Str "The"+                , Space+                , Str "brain"+                , Space+                , Str "of"+                , Space+                , Str "the"+                , Space+                , Str "computer."+                ]+            ]+          ]+        )+      , ( [ Str "Hard" , Space , Str "drive" ]+        , [ [ Para+                [ Str "Permanent"+                , Space+                , Str "storage"+                , Space+                , Str "for"+                , Space+                , Str "operating"+                , Space+                , Str "system"+                , Space+                , Str "and/or"+                , Space+                , Str "user"+                , Space+                , Str "files."+                ]+            ]+          ]+        )+      ]+  , Para [ Str "Mixed" ]+  , DefinitionList+      [ ( [ Str "Dairy" ]+        , [ [ BulletList+                [ [ Para [ Str "Milk" ] ]+                , [ Para [ Str "Eggs" ]+                  , DefinitionList [ ( [ Str "Bakery" ] , [ [] ] ) ]+                  ]+                , [ Para [ Str "Bread" ]+                  , DefinitionList [ ( [ Str "Produce" ] , [ [] ] ) ]+                  ]+                , [ Para [ Str "Bananas" ] ]+                ]+            ]+          ]+        )+      ]+  , Para [ Str "With" , Space , Str "spaces" ]+  , DefinitionList [ ( [ Str "Dairy" ] , [ [] ] ) ]+  , BulletList+      [ [ Para [ Str "Milk" ] ] , [ Para [ Str "Eggs" ] ] ]+  , DefinitionList [ ( [ Str "Bakery" ] , [ [] ] ) ]+  , BulletList [ [ Para [ Str "Bread" ] ] ]+  , DefinitionList [ ( [ Str "Produce" ] , [ [] ] ) ]+  , BulletList [ [ Para [ Str "Bananas" ] ] ]+  , Para [ Str "Nested" ]+  , DefinitionList+      [ ( [ Str "Operating" , Space , Str "Systems" ]+        , [ [ DefinitionList+                [ ( [ Str "Linux" ]+                  , [ [ OrderedList+                          ( 1 , DefaultStyle , DefaultDelim )+                          [ [ Para [ Str "Fedora" ]+                            , BulletList [ [ Para [ Str "Desktop" ] ] ]+                            ]+                          , [ Para [ Str "Ubuntu" ]+                            , BulletList+                                [ [ Para [ Str "Desktop" ] ]+                                , [ Para [ Str "Server" ] ]+                                ]+                            ]+                          ]+                      ]+                    ]+                  )+                , ( [ Str "BSD" ]+                  , [ [ OrderedList+                          ( 1 , DefaultStyle , DefaultDelim )+                          [ [ Para [ Str "FreeBSD" ] ]+                          , [ Para [ Str "NetBSD" ]+                            , DefinitionList+                                [ ( [ Str "Cloud"+                                    , Space+                                    , Str "Providers"+                                    ]+                                  , [ [ DefinitionList+                                          [ ( [ Str "PaaS" ] , [ [] ] )+                                          ]+                                      ]+                                    ]+                                  )+                                ]+                            ]+                          , [ Para [ Str "OpenShift" ] ]+                          , [ Para [ Str "CloudBees" ] ]+                          ]+                      ]+                    ]+                  )+                , ( [ Str "IaaS" ]+                  , [ [ OrderedList+                          ( 1 , DefaultStyle , DefaultDelim )+                          [ [ Para [ Str "Amazon" , Space , Str "EC2" ]+                            ]+                          ]+                      ]+                    ]+                  )+                ]+            , Para+                [ Str "This"+                , Space+                , Str "just"+                , Space+                , Str "affects"+                , Space+                , Str "the"+                , Space+                , Str "output:"+                ]+            ]+          ]+        )+      ]+  , Div+      ( ""+      , []+      , [ ( "wrapper" , "1" )+        , ( "itemwidth" , "75" )+        , ( "labelwidth" , "25" )+        ]+      )+      [ DefinitionList+          [ ( [ Str "CPU" ]+            , [ [ Para+                    [ Str "The"+                    , Space+                    , Str "brain"+                    , Space+                    , Str "of"+                    , Space+                    , Str "the"+                    , Space+                    , Str "computer."+                    ]+                ]+              ]+            )+          , ( [ Str "RAM" ]+            , [ [ Para+                    [ Str "Temporarily"+                    , Space+                    , Str "stores"+                    , Space+                    , Str "information"+                    , Space+                    , Str "the"+                    , Space+                    , Str "CPU"+                    , Space+                    , Str "uses"+                    , Space+                    , Str "during"+                    , Space+                    , Str "operation."+                    ]+                ]+              ]+            )+          ]+      ]+  , Para [ Str "Q&A" , Space , Str "list" ]+  , DefinitionList+      [ ( [ Str "What"+          , Space+          , Str "is"+          , Space+          , Str "the"+          , Space+          , Str "answer?"+          ]+        , [ [ Para+                [ Str "This"+                , Space+                , Str "is"+                , Space+                , Str "the"+                , Space+                , Str "answer."+                ]+            ]+          ]+        )+      , ( [ Str "Are"+          , Space+          , Str "cameras"+          , Space+          , Str "allowed?"+          ]+        , [ [] ]+        )+      , ( [ Str "Are"+          , Space+          , Str "backpacks"+          , Space+          , Str "allowed?"+          ]+        , [ [ Para [ Str "No." ] ] ]+        )+      ]+  , Para+      [ Str "Ordered"+      , Space+      , Str "description"+      , Space+      , Str "list"+      , Space+      , Str "(with"+      , Space+      , Str "numbers)"+      ]+  , OrderedList+      ( 1 , DefaultStyle , DefaultDelim )+      [ [ DefinitionList+            [ ( [ Str "&" ] , [ [ Para [ Str "ampersand" ] ] ] ) ]+        ]+      , [ DefinitionList+            [ ( [ Str ">" ]+              , [ [ Para [ Str "greater" , Space , Str "than" ] ] ]+              )+            ]+        ]+      ]+  , Header+      2+      ( "_block_macros" , [] , [] )+      [ Str "Block" , Space , Str "macros" ]+  , Figure+      ( "" , [] , [] )+      (Caption Nothing [])+      [ Plain+          [ Image+              ( ""+              , []+              , [ ( "width" , "300px" ) , ( "height" , "200px" ) ]+              )+              [ Str "Sunset" ]+              ( "sunset.jpg" , "" )+          ]+      ]+  , Plain+      [ Image+          ( "" , [] , [] )+          [ Str "mymovie.mp4" ]+          ( "mymovie.mp4" , "" )+      ]+  , Plain+      [ Image+          ( "" , [] , [] ) [ Str "mysong.mp3" ] ( "mysong.mp3" , "" )+      ]+  , Div ( "toc" , [] , [] ) []+  , Div+      ( ""+      , [ "included" ]+      , [ ( "path" , "asciidoc-reader-include.adoc" ) ]+      )+      [ Para+          [ Str "This"+          , Space+          , Str "is"+          , Space+          , Str "a"+          , Space+          , Str "test!"+          ]+      , OrderedList+          ( 1 , DefaultStyle , DefaultDelim )+          [ [ Para [ Str "one" ]+            , OrderedList+                ( 1 , DefaultStyle , DefaultDelim )+                [ [ Para [ Str "two" ] ] ]+            ]+          ]+      ]+  ]
+ test/command/10002.md view
@@ -0,0 +1,203 @@+````+% pandoc -f native -t opendocument+[ Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 3)+               [ Plain+                   [ Str "First"+                   , Space+                   , Str "Header"+                   , Space+                   , Str "Row"+                   ]+               ]+           ]+       , Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Second" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Header" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Row" ] ]+           ]+       ])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Header - Table" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Header - Body" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Header - Row" ] ]+            ]+        ]+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Table" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Body" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Row" ] ]+            ]+        ]+    ]+    (TableFoot+        ( "" , [] , [] )+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 3)+                [ Plain+                    [ Str "First"+                    , Space+                    , Str "Footer"+                    , Space+                    , Str "Row"+                    ]+                ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Second" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Footer" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Row" ] ]+            ]+        ])+]+^D+<table:table table:name="Table1" table:style-name="Table1">+  <table:table-column table:style-name="Table1.A" />+  <table:table-column table:style-name="Table1.B" />+  <table:table-column table:style-name="Table1.C" />+  <table:table-header-rows>+    <table:table-row>+      <table:table-cell table:style-name="TableHeaderRowCell" office:value-type="string" table:number-columns-spanned="3">+        <text:p text:style-name="Table_20_Heading">First Header+        Row</text:p>+      </table:table-cell>+    </table:table-row>+    <table:table-row>+      <table:table-cell table:style-name="TableHeaderRowCell" office:value-type="string">+        <text:p text:style-name="Table_20_Heading">Second</text:p>+      </table:table-cell>+      <table:table-cell table:style-name="TableHeaderRowCell" office:value-type="string">+        <text:p text:style-name="Table_20_Heading">Header</text:p>+      </table:table-cell>+      <table:table-cell table:style-name="TableHeaderRowCell" office:value-type="string">+        <text:p text:style-name="Table_20_Heading">Row</text:p>+      </table:table-cell>+    </table:table-row>+  </table:table-header-rows>+  <table:table-row>+    <table:table-cell table:style-name="TableRowCell" office:value-type="string">+      <text:p text:style-name="Table_20_Heading">Header - Table</text:p>+    </table:table-cell>+    <table:table-cell table:style-name="TableRowCell" office:value-type="string">+      <text:p text:style-name="Table_20_Heading">Header - Body</text:p>+    </table:table-cell>+    <table:table-cell table:style-name="TableRowCell" office:value-type="string">+      <text:p text:style-name="Table_20_Heading">Header - Row</text:p>+    </table:table-cell>+  </table:table-row>+  <table:table-row>+    <table:table-cell table:style-name="TableRowCell" office:value-type="string">+      <text:p text:style-name="Table_20_Contents">Table</text:p>+    </table:table-cell>+    <table:table-cell table:style-name="TableRowCell" office:value-type="string">+      <text:p text:style-name="Table_20_Contents">Body</text:p>+    </table:table-cell>+    <table:table-cell table:style-name="TableRowCell" office:value-type="string">+      <text:p text:style-name="Table_20_Contents">Row</text:p>+    </table:table-cell>+  </table:table-row>+  <table:table-row>+    <table:table-cell table:style-name="TableRowCell" office:value-type="string" table:number-columns-spanned="3">+      <text:p text:style-name="Table_20_Contents">First Footer+      Row</text:p>+    </table:table-cell>+  </table:table-row>+  <table:table-row>+    <table:table-cell table:style-name="TableRowCell" office:value-type="string">+      <text:p text:style-name="Table_20_Contents">Second</text:p>+    </table:table-cell>+    <table:table-cell table:style-name="TableRowCell" office:value-type="string">+      <text:p text:style-name="Table_20_Contents">Footer</text:p>+    </table:table-cell>+    <table:table-cell table:style-name="TableRowCell" office:value-type="string">+      <text:p text:style-name="Table_20_Contents">Row</text:p>+    </table:table-cell>+  </table:table-row>+</table:table>+````
+ test/command/10057.md view
@@ -0,0 +1,6 @@+```+% pandoc --natbib -t latex+We all love the famous proof by @BenjaminHornigold [p. 42].+^D+We all love the famous proof by \citet[p.~42]{BenjaminHornigold}.+```
+ test/command/10062.md view
@@ -0,0 +1,10 @@+```+% pandoc -t asciidoc+### section++##### five+^D+==== section++====== five+```
+ test/command/10071.md view
@@ -0,0 +1,15 @@+Leading tabs must be preserved in org mode *src* blocks with the `-i`+flag when pandoc is called with `-p`/`--preserve-tabs`.++```+% pandoc -f org -t native --preserve-tabs+#+begin_src makefile -i+%.o: %.cpp+	$(CXX)	-o	$@	$<+#+end_src+^D+[ CodeBlock+    ( "" , [ "makefile" ] , [] )+    "%.o: %.cpp\n\t$(CXX)\t-o\t$@\t$<\n"+]+```
+ test/command/10093.md view
@@ -0,0 +1,53 @@+```+% pandoc -f rst+========== ====+Function   1   +========== ====+a          yes +b              +========== ====+^D+<table>+<thead>+<tr>+<th>Function</th>+<th>1</th>+</tr>+</thead>+<tbody>+<tr>+<td>a</td>+<td>yes</td>+</tr>+<tr>+<td>b</td>+<td></td>+</tr>+</tbody>+</table>+```++```+% pandoc -f rst+========== ====+Function   1   +========== ====+a          yes +           & no+========== ====+^D+<table>+<thead>+<tr>+<th>Function</th>+<th>1</th>+</tr>+</thead>+<tbody>+<tr>+<td>a</td>+<td>yes &amp; no</td>+</tr>+</tbody>+</table>+```
+ test/command/10094.md view
@@ -0,0 +1,47 @@+```+% pandoc -f rst -t markdown_strict+.. table:: Test Table++   ================================== ====+   Functions for tests                1   +   ================================== ====+   a                                  yes +   b                                      +   c                                      +   d                                  yes+   e                                      +   ================================== ====+^D+<table>+<caption>Test Table</caption>+<thead>+<tr>+<th>Functions for tests</th>+<th>1</th>+</tr>+</thead>+<tbody>+<tr>+<td>a</td>+<td>yes</td>+</tr>+<tr>+<td>b</td>+<td></td>+</tr>+<tr>+<td>c</td>+<td></td>+</tr>+<tr>+<td>d</td>+<td>yes</td>+</tr>+<tr>+<td>e</td>+<td></td>+</tr>+</tbody>+</table>++```
+ test/command/10105.md view
@@ -0,0 +1,8 @@+```+% pandoc -t asciidoc --wrap=preserve+[link](https://example.com)+[link](ftps://example.com)+^D+https://example.com[link]+link:ftps://example.com[link]+```
+ test/command/10127.md view
@@ -0,0 +1,713 @@+RST Reader++```+% pandoc -f rst -t native+=====  =====  ======+   Inputs     Output+------------  ------+  A      B    A or B+=====  =====  ======+False  False  False+True   False  True+False  True   True+True   True   True+=====  =====  ======++Table with trailing whitespaces to ensure they don't interfere with col span parsing.++===============  ============  =====================  +Full column header+---------------------------------------------------- +Header One       Header Two    Header 3+===============  ============  =====================   +Row              With col span 2 on the right+---------------  -----------------------------------   +Full column row+----------------------------------------------------+Row with         Col spans     For visual separation+---------------  ------------  ---------------------  +Row with col span 2            On the left+-----------------------------  ---------------------+Final row+===============  ============  =====================+^D+[ Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 2)+               [ Plain [ Str "Inputs" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Output" ] ]+           ]+       , Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "A" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "B" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "A" , Space , Str "or" , Space , Str "B" ]+               ]+           ]+       ])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "False" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "False" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "False" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "True" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "False" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "True" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "False" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "True" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "True" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "True" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "True" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "True" ] ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+, Para+    [ Str "Table"+    , Space+    , Str "with"+    , Space+    , Str "trailing"+    , Space+    , Str "whitespaces"+    , Space+    , Str "to"+    , Space+    , Str "ensure"+    , Space+    , Str "they"+    , Space+    , Str "don't"+    , Space+    , Str "interfere"+    , Space+    , Str "with"+    , Space+    , Str "col"+    , Space+    , Str "span"+    , Space+    , Str "parsing."+    ]+, Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 3)+               [ Plain+                   [ Str "Full"+                   , Space+                   , Str "column"+                   , Space+                   , Str "header"+                   ]+               ]+           ]+       , Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Header" , Space , Str "One" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Header" , Space , Str "Two" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Header" , Space , Str "3" ] ]+           ]+       ])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Row" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 2)+                [ Plain+                    [ Str "With"+                    , Space+                    , Str "col"+                    , Space+                    , Str "span"+                    , Space+                    , Str "2"+                    , Space+                    , Str "on"+                    , Space+                    , Str "the"+                    , Space+                    , Str "right"+                    ]+                ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 3)+                [ Plain+                    [ Str "Full"+                    , Space+                    , Str "column"+                    , Space+                    , Str "row"+                    ]+                ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Row" , Space , Str "with" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Col" , Space , Str "spans" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain+                    [ Str "For"+                    , Space+                    , Str "visual"+                    , Space+                    , Str "separation"+                    ]+                ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 2)+                [ Plain+                    [ Str "Row"+                    , Space+                    , Str "with"+                    , Space+                    , Str "col"+                    , Space+                    , Str "span"+                    , Space+                    , Str "2"+                    ]+                ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain+                    [ Str "On"+                    , Space+                    , Str "the"+                    , Space+                    , Str "left"+                    ]+                ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Final" , Space , Str "row" ] ]+            , Cell+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+            , Cell+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+]+```++RST Writer+```+% pandoc -f native -t rst+[ Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 2)+               [ Plain [ Str "Inputs" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Output" ] ]+           ]+       , Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "A" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "B" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "A" , Space , Str "or" , Space , Str "B" ]+               ]+           ]+       ])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "False" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "False" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "False" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "True" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "False" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "True" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "False" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "True" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "True" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "True" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "True" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "True" ] ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+, Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 3)+               [ Plain+                   [ Str "Full"+                   , Space+                   , Str "column"+                   , Space+                   , Str "header"+                   ]+               ]+           ]+       , Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Header" , Space , Str "One" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Header" , Space , Str "Two" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Header" , Space , Str "3" ] ]+           ]+       ])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Row" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 2)+                [ Plain+                    [ Str "With"+                    , Space+                    , Str "col"+                    , Space+                    , Str "span"+                    , Space+                    , Str "2"+                    , Space+                    , Str "on"+                    , Space+                    , Str "the"+                    , Space+                    , Str "right"+                    ]+                ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 3)+                [ Plain+                    [ Str "Full"+                    , Space+                    , Str "column"+                    , Space+                    , Str "row"+                    ]+                ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 2)+                [ Plain+                    [ Str "Row"+                    , Space+                    , Str "with"+                    , Space+                    , Str "col"+                    , Space+                    , Str "span"+                    , Space+                    , Str "2"+                    ]+                ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain+                    [ Str "On"+                    , Space+                    , Str "the"+                    , Space+                    , Str "left"+                    ]+                ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Final" , Space , Str "row" ] ]+            , Cell+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+            , Cell+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+            ]+        ]+    ]+    (TableFoot+      ( "" , [] , [] ) +      [ Row+          ( "" , [] , [] )+          [ Cell+              ( "" , [] , [] )+              AlignDefault+              (RowSpan 1)+              (ColSpan 1)+              [ Plain [ Str "Footer" , Space , Str "Row" ] ]+          , Cell+              ( "" , [] , [] )+              AlignDefault+              (RowSpan 1)+              (ColSpan 1)+              [ Plain [ Str "at" , Space , Str "the" ] ]+          , Cell+              ( "" , [] , [] )+              AlignDefault+              (RowSpan 1)+              (ColSpan 1)+              [ Plain [ Str "bottom" ] ]+          ]+      ])+]+^D+====== ===== ======+Inputs       Output+------------ ------+A      B     A or B+====== ===== ======+False  False False+True   False True+False  True  True+True   True  True+====== ===== ======++=================== ============================ ===========+Full column header                               +------------------------------------------------------------+Header One          Header Two                   Header 3+=================== ============================ ===========+Row                 With col span 2 on the right +------------------- ----------------------------------------+Full column row                                  +------------------------------------------------------------+Row with col span 2                              On the left+------------------------------------------------ -----------+Final row                                        +Footer Row          at the                       bottom+=================== ============================ ===========+```
+ test/command/10145.md view
@@ -0,0 +1,24 @@+```+% pandoc -f rtf -t native+{\rtf1\ansi\deff0{\fonttbl{\f0 \fswiss Helvetica;}{\f1 \fmodern Courier;}}+{\colortbl;\red255\green0\blue0;\red0\green0\blue255;}+\widowctrl\hyphauto++{\pard \ql \f0 \sa0 \li0 \fi0 {\shp{\*\shpinst\shpwr2\shpwrk3\shpbypara\shpbyignore\shptop1320\shpbottom7745\shpbxcolumn\shpbxignore\shpleft0\shpright9638{\sp{\sn shapeType}{\sv 75}}{\sp{\sn wzDescription}{\sv }}{\sp{\sn wzName}{\sv }}{\sp{\sn pib}{\sv {\pict\jpegblip\picw20\pich22\picwgoal400\pichgoal440 ffd8ffe000104a46494600010101004800480000fffe0050546869732061727420697320696e20746865207075626c696320646f6d61696e2e204b6576696e204875676865732c206b6576696e68406569742e636f6d2c2053657074656d6265722031393935ffdb00430001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101ffdb00430101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101ffc00011080016001403012200021101031101ffc4001a000100020301000000000000000000000000080905060a07ffc400231000010501000300010500000000000000060304050708020001090a11153976b7ffc400160101010100000000000000000000000000060800ffc400261101000102050109000000000000000000010200030405061121b33134365154717475b4ffda000c03010002110311003f00a90cf388f366a62aa720ed6ae07f96901f3831d973452b8cf36fe3570fc908e46d466433e5dd954f2e96992d9e498c7753faa44916e016ca91cc7d88b38fe60a5b97737defcbcc539c98d336a57f4fc2ca9a486bf07ab575ad9a3af4df221d8215e36df86c4504ff0024574551b3d687ee0575757b3ad64e311ee62bd94158d37e24198c43973099f1fc0c41614d950246513a081abf76cfe7061f6863281e6352fd1670949c148dd6dfb0d25f5b3689b1d5c965b0eacbf4e0932ad28e22ab9ae945633f4744bd3c8cee0a7fdf085b9000f449c5f7afa30b83e0b6fd7b0c8429c9467ff9715347c891e25fa24a205861aa715e6a09bd0488237dc2723414d9891381524e8ca7c0894664f835653631ab55ee7e3de433e4ff001b30949124e4c10c8b6ad0a479b3f9c937b2cf5bc0095ad600a0a41a0e9faee174a1c605e161c6c7a313539650b0113190f1a8368e60d5b24f30ff008ea7f0bf867fa6595feeb6978f1fe0f9c26177f4d63a51a9235184750e7d18811339cd000000c75f000e00380380ae390c350def826ed42ad051fa6f501c50f9b699c3b69cbeb76476d202bf3ac985b6e0e968be66572893e6a744540bd9722e5c87956848629bc2559306bd113e8653d3b6aff651dfad7a3ac8b02958cba02a93ccf525757039bae6cff090e1d90688e8aa233ee86a4c4a3e0586d6b2340522e47dcb7d0046d8a5acb05a123ee25d2b230b2ada6e2e2f9ede3c05202520ec2487b0d56562529d8b3393bca76adca4ec1bca508abb001babc007915d84fe3dd14e207e3c62f8379da2a3b861fb6629d28dba53b6ea388ebfed866bf6dfb553455e91ed547ae92e9445253a4fdf3efb4f8ebdfbe7d3c78f1ee0bb9e13e358e942a4ed49e22cff00eeb35fdd7ebfffd9}}}}}\par}+{\pard \ql \f0 \sa0 \li0 \fi0 moon\par}+}+^D+[ Para+    [ Image+        ( ""+        , []+        , [ ( "width" , "0.2777777777777778in" )+          , ( "height" , "0.3055555555555556in" )+          ]+        )+        [ Str "image" ]+        ( "9ea9761885249909bcd8a610706eef51b54dc351.jpg" , "" )+    ]+, Para [ Str "moon" ]+]+```
+ test/command/10148.md view
@@ -0,0 +1,18 @@+```+% pandoc -t typst+See [@MyPaper].++See [@MyPaper, Equation 1] for details.++See [@MyPaper, Equation 1].++See [@MyPaper, Equation 1; @Other, Figure 1].+^D+See @MyPaper.++See @MyPaper[Equation 1] for details.++See @MyPaper[Equation 1].++See @MyPaper[Equation 1]@Other[Figure 1].+```
+ test/command/10149.md view
@@ -0,0 +1,296 @@+Row spans+```+% pandoc -f html --columns 24 -t ansi+<table>+  <thead>+    <tr>+      <td rowspan="3">1</td>+      <td>2</td>+      <td>3</td>+      <td>4</td>+      <td rowspan="4">5</td>+      <td>6</td>+    </tr>+    <tr>+      <td>2</td>+      <td colspan="2" rowspan="2">3</td>+      <td>6</td>+    </tr>+    <tr>+      <td rowspan="2">2</td>+      <td>6</td>+    </tr>+    <tr>+      <td>1</td>+      <td>3</td>+      <td>4</td>+      <td>6</td>+    </tr>+  </thead>+  <tbody>+    <tr>+      <td colspan="2">a</td>+      <td rowspan="2">c</td>+      <td>d</td>+      <td>e</td>+      <td>f</td>+    </tr>+    <tr>+      <td>a</td>+      <td>b</td>+      <td colspan="3" rowspan="2">d</td>+    </tr>+    <tr>+      <td>a</td>+      <td>b</td>+      <td>c</td>+    </tr>+  </tbody>+  <tfoot>+    <tr>+      <td colspan="2" rowspan="4">A</td>+      <td>C</td>+      <td>D</td>+      <td colspan="2" rowspan="3">E</td>+    </tr>+    <tr>+      <td>C</td>+      <td>D</td>+    </tr>+    <tr>+      <td>C</td>+      <td>D</td>+    </tr>+    <tr>+      <td>C</td>+      <td>D</td>+      <td>E</td>+      <td>F</td>+    </tr>+  </tfoot>+</table>+^D+1   2   3   4   5   6+    2   3           6+    2               6+1       3   4       6+─── ─── ─── ─── ─── ───+a       c   d   e   f+a   b       d+a   b   c+─── ─── ─── ─── ─── ───+A       C   D   E+        C   D+        C   D+        C   D   E   F[0m]8;;\+```++Empty rows+```+% pandoc -f native --columns 12 -t ansi+[ Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 3)+               (ColSpan 2)+               [ Plain [ Str "1" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "3" ] ]+           ]+       , Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "3" ] ]+           ]+       , Row ( "" , [] , [] ) []+       , Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "1" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "2" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "3" ] ]+           ]+       ])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 2)+                (ColSpan 1)+                [ Plain [ Str "3" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 4)+                (ColSpan 1)+                [ Plain [ Str "2" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "3" ] ]+            ]+        , Row ( "" , [] , [] ) []+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "3" ] ]+            ]+        ]+    ]+    (TableFoot+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "1" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "2" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 2)+               (ColSpan 1)+               [ Plain [ Str "3" ] ]+           ]+       , Row ( "" , [] , [] ) []+       , Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "1" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "2" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 3)+               (ColSpan 1)+               [ Plain [ Str "3" ] ]+           ]+       , Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "1" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "2" ] ]+           ]+       , Row ( "" , [] , [] ) []+       ])+]+^D+1       3+        3+1   2   3+─── ─── ───+1   2   3+1   2+1       3+1       3+─── ─── ───+1   2   3+1   2   3+1   2[0m]8;;\+```
+ test/command/10152.md view
@@ -0,0 +1,446 @@+# CRediT Roles++This document contains tests and examples for enabling+export of roles to JATS. It was added for+[Issue #10152](https://github.com/jgm/pandoc/issues/10152)+and corresponding [Pull Request #10153](https://github.com/jgm/pandoc/pull/10153).++In the first example, we show a fully qualified CRediT role.+An explicit name isn't given, so the CRediT name is used.++```+% pandoc -s -t jats+---+title: CRediT Test+author:+  - name: Max Mustermann+    affiliation: [ 1 ]+    roles:+      - credit: software+        credit-name: Software+        degree: Lead+affiliation:+- id: 1+  name: Silverlight University+---+^D+<?xml version="1.0" encoding="utf-8" ?>+<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.2 20190208//EN"+                  "JATS-archivearticle1.dtd">+<article xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" dtd-version="1.2" article-type="other">+<front>+<journal-meta>+<journal-id></journal-id>+<journal-title-group>+</journal-title-group>+<issn></issn>+<publisher>+<publisher-name></publisher-name>+</publisher>+</journal-meta>+<article-meta>+<title-group>+<article-title>CRediT Test</article-title>+</title-group>+<contrib-group>+<contrib contrib-type="author">+<string-name>Max Mustermann</string-name>+<role vocab="credit" degree-contribution="Lead"+      vocab-identifier="https://credit.niso.org/"+      vocab-term-identifier="https://credit.niso.org/contributor-roles/software/"+      vocab-term="Software"+>Software</role>+<xref ref-type="aff" rid="aff-1"/>+</contrib>+<aff id="aff-1">+<institution-wrap>+<institution>Silverlight University</institution>+</institution-wrap>+</aff>+</contrib-group>+<permissions>+</permissions>+</article-meta>+</front>+<body>++</body>+<back>+</back>+</article>+```++In the second example, we show a fully qualified CRediT role.+An explicit name is given in a different language.++```+% pandoc -s -t jats+---+title: CRediT Test+author:+  - name: Max Mustermann+    affiliation: [ 1 ]+    roles:+      - credit: software+        credit-name: Software+        degree: Lead+        name: Programas+affiliation:+- id: 1+  name: Silverlight University+---+^D+<?xml version="1.0" encoding="utf-8" ?>+<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.2 20190208//EN"+                  "JATS-archivearticle1.dtd">+<article xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" dtd-version="1.2" article-type="other">+<front>+<journal-meta>+<journal-id></journal-id>+<journal-title-group>+</journal-title-group>+<issn></issn>+<publisher>+<publisher-name></publisher-name>+</publisher>+</journal-meta>+<article-meta>+<title-group>+<article-title>CRediT Test</article-title>+</title-group>+<contrib-group>+<contrib contrib-type="author">+<string-name>Max Mustermann</string-name>+<role vocab="credit" degree-contribution="Lead"+      vocab-identifier="https://credit.niso.org/"+      vocab-term-identifier="https://credit.niso.org/contributor-roles/software/"+      vocab-term="Software"+>Programas</role>+<xref ref-type="aff" rid="aff-1"/>+</contrib>+<aff id="aff-1">+<institution-wrap>+<institution>Silverlight University</institution>+</institution-wrap>+</aff>+</contrib-group>+<permissions>+</permissions>+</article-meta>+</front>+<body>++</body>+<back>+</back>+</article>+```++In this example, we show a partially qualified CRediT role+that does not have a `degree`:++```+% pandoc -s -t jats+---+title: CRediT Test+author:+  - name: Max Mustermann+    affiliation: [ 1 ]+    roles:+      - credit: software+        credit-name: Software+affiliation:+- id: 1+  name: Silverlight University+---+^D+<?xml version="1.0" encoding="utf-8" ?>+<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.2 20190208//EN"+                  "JATS-archivearticle1.dtd">+<article xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" dtd-version="1.2" article-type="other">+<front>+<journal-meta>+<journal-id></journal-id>+<journal-title-group>+</journal-title-group>+<issn></issn>+<publisher>+<publisher-name></publisher-name>+</publisher>+</journal-meta>+<article-meta>+<title-group>+<article-title>CRediT Test</article-title>+</title-group>+<contrib-group>+<contrib contrib-type="author">+<string-name>Max Mustermann</string-name>+<role vocab="credit"+      vocab-identifier="https://credit.niso.org/"+      vocab-term-identifier="https://credit.niso.org/contributor-roles/software/"+      vocab-term="Software"+>Software</role>+<xref ref-type="aff" rid="aff-1"/>+</contrib>+<aff id="aff-1">+<institution-wrap>+<institution>Silverlight University</institution>+</institution-wrap>+</aff>+</contrib-group>+<permissions>+</permissions>+</article-meta>+</front>+<body>++</body>+<back>+</back>+</article>+```++In this example, we show a more stripped-down data that requires automatic lookup of the+`credit-name`.++```+% pandoc -s -t jats+---+title: CRediT Test+author:+  - name: Max Mustermann+    affiliation: [ 1 ]+    roles:+      - credit: software+affiliation:+- id: 1+  name: Silverlight University+---+^D+<?xml version="1.0" encoding="utf-8" ?>+<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.2 20190208//EN"+                  "JATS-archivearticle1.dtd">+<article xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" dtd-version="1.2" article-type="other">+<front>+<journal-meta>+<journal-id></journal-id>+<journal-title-group>+</journal-title-group>+<issn></issn>+<publisher>+<publisher-name></publisher-name>+</publisher>+</journal-meta>+<article-meta>+<title-group>+<article-title>CRediT Test</article-title>+</title-group>+<contrib-group>+<contrib contrib-type="author">+<string-name>Max Mustermann</string-name>+<role vocab="credit"+      vocab-identifier="https://credit.niso.org/"+      vocab-term-identifier="https://credit.niso.org/contributor-roles/software/"+      vocab-term="Software"+>Software</role>+<xref ref-type="aff" rid="aff-1"/>+</contrib>+<aff id="aff-1">+<institution-wrap>+<institution>Silverlight University</institution>+</institution-wrap>+</aff>+</contrib-group>+<permissions>+</permissions>+</article-meta>+</front>+<body>++</body>+<back>+</back>+</article>+```++In this example, we test the correct XML encoding of+the CRediT role [Writing – review & editing](https://credit.niso.org/contributor-roles/writing-review-editing/),+which annoyingly contains an ampersand in its label.++```+% pandoc -s -t jats+---+title: CRediT Test+author:+  - name: Max Mustermann+    affiliation: [ 1 ]+    roles:+      - credit: writing-review-editing+        credit-name: Writing – review & editing+        degree: Lead+affiliation:+- id: 1+  name: Silverlight University+---+^D+<?xml version="1.0" encoding="utf-8" ?>+<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.2 20190208//EN"+                  "JATS-archivearticle1.dtd">+<article xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" dtd-version="1.2" article-type="other">+<front>+<journal-meta>+<journal-id></journal-id>+<journal-title-group>+</journal-title-group>+<issn></issn>+<publisher>+<publisher-name></publisher-name>+</publisher>+</journal-meta>+<article-meta>+<title-group>+<article-title>CRediT Test</article-title>+</title-group>+<contrib-group>+<contrib contrib-type="author">+<string-name>Max Mustermann</string-name>+<role vocab="credit" degree-contribution="Lead"+      vocab-identifier="https://credit.niso.org/"+      vocab-term-identifier="https://credit.niso.org/contributor-roles/writing-review-editing/"+      vocab-term="Writing – review &amp; editing"+>Writing – review &amp; editing</role>+<xref ref-type="aff" rid="aff-1"/>+</contrib>+<aff id="aff-1">+<institution-wrap>+<institution>Silverlight University</institution>+</institution-wrap>+</aff>+</contrib-group>+<permissions>+</permissions>+</article-meta>+</front>+<body>++</body>+<back>+</back>+</article>+```++In this example, we show a role that isn't qualified with CRediT.++```+% pandoc -s -t jats+---+title: CRediT Test+author:+  - name: Max Mustermann+    affiliation: [ 1 ]+    roles:+      - name: Dolphin Catcher+affiliation:+- id: 1+  name: Silverlight University+---+^D+<?xml version="1.0" encoding="utf-8" ?>+<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.2 20190208//EN"+                  "JATS-archivearticle1.dtd">+<article xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" dtd-version="1.2" article-type="other">+<front>+<journal-meta>+<journal-id></journal-id>+<journal-title-group>+</journal-title-group>+<issn></issn>+<publisher>+<publisher-name></publisher-name>+</publisher>+</journal-meta>+<article-meta>+<title-group>+<article-title>CRediT Test</article-title>+</title-group>+<contrib-group>+<contrib contrib-type="author">+<string-name>Max Mustermann</string-name>+<role>Dolphin Catcher</role>+<xref ref-type="aff" rid="aff-1"/>+</contrib>+<aff id="aff-1">+<institution-wrap>+<institution>Silverlight University</institution>+</institution-wrap>+</aff>+</contrib-group>+<permissions>+</permissions>+</article-meta>+</front>+<body>++</body>+<back>+</back>+</article>+```++In this example, we show a role that neither has a CRediT identifer,+nor a name, so it's ignored.++```+% pandoc -s -t jats+---+title: CRediT Test+author:+  - name: Max Mustermann+    affiliation: [ 1 ]+    roles:+      - irrelevant-key: Dolphin Catcher+affiliation:+- id: 1+  name: Silverlight University+---+^D+<?xml version="1.0" encoding="utf-8" ?>+<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.2 20190208//EN"+                  "JATS-archivearticle1.dtd">+<article xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" dtd-version="1.2" article-type="other">+<front>+<journal-meta>+<journal-id></journal-id>+<journal-title-group>+</journal-title-group>+<issn></issn>+<publisher>+<publisher-name></publisher-name>+</publisher>+</journal-meta>+<article-meta>+<title-group>+<article-title>CRediT Test</article-title>+</title-group>+<contrib-group>+<contrib contrib-type="author">+<string-name>Max Mustermann</string-name>+<xref ref-type="aff" rid="aff-1"/>+</contrib>+<aff id="aff-1">+<institution-wrap>+<institution>Silverlight University</institution>+</institution-wrap>+</aff>+</contrib-group>+<permissions>+</permissions>+</article-meta>+</front>+<body>++</body>+<back>+</back>+</article>+```
+ test/command/10160.md view
@@ -0,0 +1,15 @@+```+% pandoc -f latex -t native+\begin{equation}+  [0,1)+\end{equation}++\begin{table}[h]+\end{table}+^D+[ Para+    [ Math+        DisplayMath "\\begin{equation}\n  [0,1)\n\\end{equation}"+    ]+]+```
+ test/command/10185.md view
@@ -0,0 +1,46 @@+```+% pandoc -t latex --citeproc+Lorem ipsum++# References++::: {#refs}+:::+^D+Lorem ipsum++\section{References}\label{references}++\protect\phantomsection\label{refs}+```++```+% pandoc -t latex --citeproc+---+references:+- id: foo+  type: book+  title: The Title+  author: John Doe+...++Lorem ipsum [@foo].++# References++::: {#refs}+:::+^D+Lorem ipsum (John Doe, n.d.).++\section{References}\label{references}++\protect\phantomsection\label{refs}+\begin{CSLReferences}{1}{1}+\bibitem[\citeproctext]{ref-foo}+John Doe. n.d. \emph{The Title}.++\end{CSLReferences}++```+
+ test/command/10236.md view
@@ -0,0 +1,80 @@+```+% pandoc -t rst+- > test+  >+  > para 2+^D+- ..++     test++     para 2+```++```+% pandoc -t rst+1. > test+   >+   > para 2+^D+1. ..++      test++      para 2+```++```+% pandoc -t rst+::: caution+> test+:::+^D+.. caution::++   ..++      test+```++```+% pandoc -f native -t rst --list-tables+[ Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidth 0.26 ) ]+    (TableHead ( "" , [] , [] ) [])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ BlockQuote+                  [ Para [ Emph [ Str "Level" , Space , Str "0:" ] ]+                  , Para+                      [ Emph [ Str "Incomplete" , Space , Str "process" ]+                      ]+                  ]+                ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+]+^D+.. list-table::+   :widths: 19++   * - ..++          *Level 0:*++          *Incomplete process*+```+
+ test/command/10271.md view
@@ -0,0 +1,29 @@+```+% pandoc -f markdown+smart -t typst+smart+"don't do it---"+^D+"don't do it---"++```+```+% pandoc -f markdown+smart -t typst-smart+"don't do it---"+^D+“don’t do it—”++```+```+% pandoc -f markdown-smart -t typst+smart+"don't do it---"+^D+\"don\'t do it-\-\-\"++```+```+% pandoc -f markdown-smart -t typst-smart+"don't do it---"+^D+"don't do it---"++```+
+ test/command/10279.md view
@@ -0,0 +1,9 @@+```+% pandoc -f rst+See `the full compatibility guidelines <https://+example.com>`_ for more information.+^D+<p>See <a href="https://example.com">the full compatibility+guidelines</a> for more information.</p>++```
+ test/command/10281.md view
@@ -0,0 +1,68 @@+```+% pandoc -f rst -t native+`Want Speed? Pass by Value`_++.. note::+  For more information about the pass-by-value idiom, read: `Want Speed? Pass by Value`_.++  .. _Want Speed? Pass by Value: https://web.archive.org/web/20140205194657/http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/+^D+[ Para+    [ Link+        ( "" , [] , [] )+        [ Str "Want"+        , Space+        , Str "Speed?"+        , Space+        , Str "Pass"+        , Space+        , Str "by"+        , Space+        , Str "Value"+        ]+        ( "https://web.archive.org/web/20140205194657/http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/"+        , ""+        )+    ]+, Div+    ( "" , [ "note" ] , [] )+    [ Div ( "" , [ "title" ] , [] ) [ Para [ Str "Note" ] ]+    , Para+        [ Str "For"+        , Space+        , Str "more"+        , Space+        , Str "information"+        , Space+        , Str "about"+        , Space+        , Str "the"+        , Space+        , Str "pass-by-value"+        , Space+        , Str "idiom,"+        , Space+        , Str "read:"+        , Space+        , Link+            ( "" , [] , [] )+            [ Str "Want"+            , Space+            , Str "Speed?"+            , Space+            , Str "Pass"+            , Space+            , Str "by"+            , Space+            , Str "Value"+            ]+            ( "https://web.archive.org/web/20140205194657/http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/"+            , ""+            )+        , Str "."+        ]+    ]+]++```+
+ test/command/10318.md view
@@ -0,0 +1,84 @@+```+% pandoc -f rst -t html5+-a         Output all.+-c arg     Output just arg.+--long     Output all day long.+/V         A VMS/DOS-style option.++-p         This option has two paragraphs in the description.+           This is the first.++           This is the second.+           Blank lines may be omitted between options+           (as above) or left in (as here and below).++--very-long-option  A VMS-style option.  Note the adjustment+                    for the required two spaces.++--an-even-longer-option+           The description can also start on the next line.++-2, --two  This option has two variants.++-f FILE, --file=FILE  These two options are synonyms; both have+                      arguments.++-f <[path]file>  Option argument placeholders must start with+                 a letter or be wrapped in angle brackets.++-d <src dest>    Angle brackets are also required if an option+                 expects more than one argument.+^D+<dl>+<dt><code>-a</code></dt>+<dd>+<p>Output all.</p>+</dd>+<dt><code>-c arg</code></dt>+<dd>+<p>Output just arg.</p>+</dd>+<dt><code>--long</code></dt>+<dd>+<p>Output all day long.</p>+</dd>+<dt><code>/V</code></dt>+<dd>+<p>A VMS/DOS-style option.</p>+</dd>+<dt><code>-p</code></dt>+<dd>+<p>This option has two paragraphs in the description. This is the+first.</p>+<p>This is the second. Blank lines may be omitted between options (as+above) or left in (as here and below).</p>+</dd>+<dt><code>--very-long-option</code></dt>+<dd>+<p>A VMS-style option. Note the adjustment for the required two+spaces.</p>+</dd>+<dt><code>--an-even-longer-option</code></dt>+<dd>+<p>The description can also start on the next line.</p>+</dd>+<dt><code>-2, --two</code></dt>+<dd>+<p>This option has two variants.</p>+</dd>+<dt><code>-f FILE, --file=FILE</code></dt>+<dd>+<p>These two options are synonyms; both have arguments.</p>+</dd>+<dt><code>-f &lt;[path]file&gt;</code></dt>+<dd>+<p>Option argument placeholders must start with a letter or be wrapped+in angle brackets.</p>+</dd>+<dt><code>-d &lt;src dest&gt;</code></dt>+<dd>+<p>Angle brackets are also required if an option expects more than one+argument.</p>+</dd>+</dl>+```
+ test/command/10328.md view
@@ -0,0 +1,37 @@+Unwrap divs if they only have the `nonincremental` or `incremental` classes.++```+% pandoc --incremental --from=markdown --to=revealjs+## First slide++::: nonincremental++1.  Note 1+2.  Note 2+3.  Note 3++:::++## Second Slide++1.  Note 1+2.  Note 2+3.  Note 3+^D+<section id="first-slide" class="slide level2">+<h2>First slide</h2>+<ol type="1">+<li>Note 1</li>+<li>Note 2</li>+<li>Note 3</li>+</ol>+</section>+<section id="second-slide" class="slide level2">+<h2>Second Slide</h2>+<ol type="1">+<li class="fragment">Note 1</li>+<li class="fragment">Note 2</li>+<li class="fragment">Note 3</li>+</ol>+</section>+```
+ test/command/10338-rst-multiple-header-rows.md view
@@ -0,0 +1,155 @@+```+% pandoc -f rst -t native+Multiple Headers+================++========== =========+Header A1  Header A2+Header B1  Header B2+========== =========+body a1    body a1+body b1    body b2+========== =========++Headless+========++========== =========+body a1    body a1+body b1    body b2+========== =========++End Section+===========+^D+[ Header+    1+    ( "multiple-headers" , [] , [] )+    [ Str "Multiple" , Space , Str "Headers" ]+, Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Header" , Space , Str "A1" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Header" , Space , Str "A2" ] ]+           ]+       , Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Header" , Space , Str "B1" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Header" , Space , Str "B2" ] ]+           ]+       ])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "body" , Space , Str "a1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "body" , Space , Str "a1" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "body" , Space , Str "b1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "body" , Space , Str "b2" ] ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+, Header 1 ( "headless" , [] , [] ) [ Str "Headless" ]+, Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    ]+    (TableHead ( "" , [] , [] ) [])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "body" , Space , Str "a1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "body" , Space , Str "a1" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "body" , Space , Str "b1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "body" , Space , Str "b2" ] ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+, Header+    1+    ( "end-section" , [] , [] )+    [ Str "End" , Space , Str "Section" ]+]+```
+ test/command/10385.md view
@@ -0,0 +1,22 @@+````+% pandoc -t asciidoc+C+ C++ C+++ `++`++`` ` `` \`hi\`++`hi\there`` ok`++```+++`+```+^D+C{plus} C{plus}{plus} C{plus}{plus}{plus} `{plus}{plus}`++`++`++` ++`++hi++`++++`hi++\++there++``++ ok`++....+++`+....+````
+ test/command/10390.md view
@@ -0,0 +1,23 @@+```+% pandoc -f mediawiki+ {| class="wikitable"+ |+ Overview of basic table markup+ ! Key+ |-+ | Value+ |}+^D+<table>+<caption>Overview of basic table markup</caption>+<thead>+<tr>+<th><p>Key</p></th>+</tr>+</thead>+<tbody>+<tr>+<td><p>Value</p></td>+</tr>+</tbody>+</table>+```
+ test/command/10414.md view
@@ -0,0 +1,6 @@+```+% pandoc -f textile -t html+from 30.-100. text, inside - after dash+^D+<p>from 30.–100. text, inside - after dash</p>+```
+ test/command/10459.md view
@@ -0,0 +1,11 @@+```+% pandoc -s --shift-heading-level-by=-1 -f djot -t native+# hi+^D+Pandoc+  Meta+    { unMeta =+        fromList [ ( "title" , MetaInlines [ Str "hi" ] ) ]+    }+  [ Div ( "hi" , [ "section" ] , [] ) [] ]+```
+ test/command/10484.md view
@@ -0,0 +1,22 @@+```+% pandoc -frst -tmarkdown_strict+- One issue fixed: `issue 123`_.++- One change merged: `Big change <pull 234_>`_.++- Improved the `home page <https://example.com/homepage>`_.++- One more `small change`__.++.. _issue 123: https://github.com/joe/project/issues/123+.. _pull 234: https://github.com/joe/project/pull/234+__ https://github.com/joe/project/issues/999++^D+- One issue fixed: [issue+  123](https://github.com/joe/project/issues/123).+- One change merged: [Big+  change](https://github.com/joe/project/pull/234).+- Improved the [home page](https://example.com/homepage).+- One more [small change](https://github.com/joe/project/issues/999).+```
+ test/command/10490.md view
@@ -0,0 +1,50 @@+```+% pandoc -f mediawiki -t html+{|class="wikitable" style="text-align: center;"+|-+!rowspan=3 style=""|Witness program version+!colspan=4 style=""|Hash size+|-+!Mainnet+!Testnet+!Mainnet+!Testnet+|-+|0||p2||QW||7Xh||T7n+|-+|1||p4||QY||7Xq||T7w+|}+^D+<table>+<thead>+<tr>+<th style=""><p>Witness program version</p></th>+<th colspan="4" style=""><p>Hash size</p></th>+</tr>+</thead>+<tbody>+<tr>+<td><p>Mainnet</p></td>+<td><p>Testnet</p></td>+<td><p>Mainnet</p></td>+<td><p>Testnet</p></td>+<td></td>+</tr>+<tr>+<td><p>0</p></td>+<td><p>p2</p></td>+<td><p>QW</p></td>+<td><p>7Xh</p></td>+<td><p>T7n</p></td>+</tr>+<tr>+<td><p>1</p></td>+<td><p>p4</p></td>+<td><p>QY</p></td>+<td><p>7Xq</p></td>+<td><p>T7w</p></td>+</tr>+</tbody>+</table>++```
+ test/command/10491.md view
@@ -0,0 +1,35 @@+```+% pandoc -f mediawiki -t gfm+{| class="wikitable"+|-+!+!0+!1+!2+!3+!4+!5+!6+!7+|-+!+0+|q||p||z||r||y||9||x||8+|-+!+8+|g||f||2||t||v||d||w||0+|-+!+16+|s||3||j||n||5||4||k||h+|-+!+24+|c||e||6||m||u||a||7||l+|}+^D+|     | 0   | 1   | 2   | 3   | 4   | 5   | 6   | 7   |+|-----|-----|-----|-----|-----|-----|-----|-----|-----|+| +0  | q   | p   | z   | r   | y   | 9   | x   | 8   |+| +8  | g   | f   | 2   | t   | v   | d   | w   | 0   |+| +16 | s   | 3   | j   | n   | 5   | 4   | k   | h   |+| +24 | c   | e   | 6   | m   | u   | a   | 7   | l   |++```
+ test/command/10497.md view
@@ -0,0 +1,13 @@+```+% pandoc -f rst+a.__b__++a__b__++__foo__+^D+<p>a.__b__</p>+<p>a__b__</p>+<p>__foo__</p>+```+
+ test/command/10537.md view
@@ -0,0 +1,24 @@+```+% pandoc -f pod -t html+=encoding utf8++=head1 NAME++Test document+^D+<h1>NAME</h1>+<p>Test document</p>+```++```+% pandoc -f pod -t html+=encoding utf8+++=head1 NAME++Test document+^D+<h1>NAME</h1>+<p>Test document</p>+```
+ test/command/10594.md view
@@ -0,0 +1,28 @@+```+% pandoc -f docbook -t native+<orderedlist numeration="loweralpha">+<title>header inside listing</title>   // not rendered in any output format!+<listitem>+<simpara>first step</simpara>+</listitem>+</orderedlist>+^D+[ Div+    ( "" , [] , [] )+    [ Div+        ( "" , [ "title" ] , [] )+        [ Plain+            [ Str "header"+            , Space+            , Str "inside"+            , Space+            , Str "listing"+            ]+        ]+    , OrderedList+        ( 1 , LowerAlpha , DefaultDelim )+        [ [ Para [ Str "first" , Space , Str "step" ] ] ]+    ]+]++```
+ test/command/10621.md view
@@ -0,0 +1,7 @@+```+% pandoc -f markdown -t html+[test](url+"title")+^D+<p><a href="url" title="title">test</a></p>+```
+ test/command/10631.md view
@@ -0,0 +1,8 @@+GFM has funny treatment of escaped braces, requiring `\\{` instead of `\{`.++```+% pandoc -f gfm -t markdown+$\\{x,y\\}$+^D+$\{x,y\}$+```
+ test/command/10635.md view
@@ -0,0 +1,24 @@+# Support for KOMA's `\minisec` command++```+% pandoc -f latex -t native+\minisec{Montage}+Zunächst suche man das Mauseloch.+^D+[ Header+    6+    ( "montage" , [ "unnumbered" , "unlisted" ] , [] )+    [ Str "Montage" ]+, Para+    [ Str "Zun\228chst"+    , Space+    , Str "suche"+    , Space+    , Str "man"+    , Space+    , Str "das"+    , Space+    , Str "Mauseloch."+    ]+]+```
+ test/command/10643.md view
@@ -0,0 +1,11 @@+```+% pandoc -f html -t native+<p>A<style></style>B</p>+^D+[ Para+    [ Str "A"+    , RawInline (Format "html") "<style></style>"+    , Str "B"+    ]+]+```
+ test/command/10650.md view
@@ -0,0 +1,9 @@+```+% pandoc -t typst --wrap=preserve+1\. I don't want this to be an enumerated list.+2\. No, I don't: only a number before a paragraph.+^D+\1. I don't want this to be an enumerated list.+\2. No, I don't: only a number before a paragraph.+```+
+ test/command/10659.md view
@@ -0,0 +1,45 @@+```+% pandoc -f latex -t native+\includegraphics[+width=5cm,+]{abc.jpg}+^D+[ Para+    [ Image+        ( "" , [] , [ ( "width" , "5cm" ) ] )+        [ Str "image" ]+        ( "abc.jpg" , "" )+    ]+]+```++```+% pandoc -f latex -t native+\includegraphics[%+width=5cm,%+]{abc.jpg}+^D+[ Para+    [ Image+        ( "" , [] , [ ( "width" , "5cm" ) ] )+        [ Str "image" ]+        ( "abc.jpg" , "" )+    ]+]+```++```+% pandoc -f latex -t native+\includegraphics[width=5cm]{%+abc.jpg%+}+^D+[ Para+    [ Image+        ( "" , [] , [ ( "width" , "5cm" ) ] )+        [ Str "image" ]+        ( "abc.jpg" , "" )+    ]+]+```+
+ test/command/10672.md view
@@ -0,0 +1,26 @@+```+% pandoc+| This | Is |+|:-----|:---|+| With \+| Cells+^D+<table>+<thead>+<tr>+<th style="text-align: left;">This</th>+<th style="text-align: left;">Is</th>+</tr>+</thead>+<tbody>+<tr>+<td style="text-align: left;">With \</td>+<td style="text-align: left;"></td>+</tr>+<tr>+<td style="text-align: left;">Cells</td>+<td style="text-align: left;"></td>+</tr>+</tbody>+</table>+```
+ test/command/10708.md view
@@ -0,0 +1,24 @@+```+% pandoc -f html -t mediawiki+<dl>+<dt>Case 1: Both subsets are non-empty</dt>+<dd>+In this case, …+</dd>+</dl>+^D+; Case 1<nowiki>:</nowiki> Both subsets are non-empty+: In this case, …+```++```+% pandoc -f mediawiki -t html+; term : definition+^D+<dl>+<dt>term</dt>+<dd>+definition+</dd>+</dl>+```
+ test/command/10730.md view
@@ -0,0 +1,7 @@+```+% pandoc -f org -t native+=hi+there=+^D+[ Para [ Code ( "" , [ "verbatim" ] , [] ) "hi there" ] ]+```
+ test/command/10747.md view
@@ -0,0 +1,6 @@+```+% pandoc -t typst+[Mark]{.mark}+^D+#highlight[Mark]+```
+ test/command/10755.md view
@@ -0,0 +1,71 @@+```+% pandoc -f native -t markdown+[ Figure+    ( "" , [] , [] )+    (Caption+       Nothing [ Para [ Str "An" , Space , Str "image." ] ])+    [ Plain+        [ Image+            ( ""+            , []+            , []+            )+            [ Str "An" , Space , Str "image." ]+            ( "media/rId20.jpg" , "" )+        ]+    ]+]+^D+![An image.](media/rId20.jpg)+```++```+% pandoc -f native -t markdown -t markdown-implicit_figures+[ Figure+    ( "" , [] , [] )+    (Caption+       Nothing [ Para [ Str "An" , Space , Str "image." ] ])+    [ Plain+        [ Image+            ( ""+            , []+            , []+            )+            [ Str "An" , Space , Str "image." ]+            ( "media/rId20.jpg" , "" )+        ]+    ]+]+^D+<figure>+<img src="media/rId20.jpg" alt="An image." />+<figcaption aria-hidden="true"><p>An image.</p></figcaption>+</figure>+```++```+% pandoc -f native -t markdown -t markdown-implicit_figures-raw_html+[ Figure+    ( "" , [] , [] )+    (Caption+       Nothing [ Para [ Str "An" , Space , Str "image." ] ])+    [ Plain+        [ Image+            ( ""+            , []+            , []+            )+            [ Str "An" , Space , Str "image." ]+            ( "media/rId20.jpg" , "" )+        ]+    ]+]+^D+:::: figure+![An image.](media/rId20.jpg)++::: caption+An image.+:::+::::+```
+ test/command/10758.md view
@@ -0,0 +1,21 @@+```+% pandoc -f native -t markdown+[ Figure+    ( "" , [] , [] )+    (Caption+       Nothing+       [ Para [ Str "Foo" , Space , Emph [ Str "emphasis" ] ] ])+    [ Plain+        [ Image+            ( ""+            , []+            , []+            )+            [ Str "Foo" , Space , Str "emphasis" ]+            ( "media/rId20.jpg" , "" )+        ]+    ]+]+^D+![Foo *emphasis*](media/rId20.jpg)+```
+ test/command/10781.md view
@@ -0,0 +1,8 @@+```+% pandoc -f latex -t markdown --wrap=preserve+This is \texttt{--flag} with dashes.+This is the same --flag without a code.+^D+This is `--flag` with dashes.+This is the same --flag without a code.+```
+ test/command/10791.md view
@@ -0,0 +1,15 @@+```+% pandoc -t opendocument+Aboard **the luxury cruise ship Heart of the Ocean[^1] in the Atlantic Ocean**...++[^1]: **Heart of the Ocean** (海洋之心) – The Heart of the Ocean+^D+<text:p text:style-name="Text_20_body">Aboard+<text:span text:style-name="Strong_20_Emphasis">the luxury cruise ship+Heart of the+Ocean</text:span><text:note text:id="ftn0" text:note-class="footnote"><text:note-citation>1</text:note-citation><text:note-body><text:p text:style-name="Footnote"><text:span text:style-name="Strong_20_Emphasis">Heart+of the Ocean</text:span> (海洋之心) – The Heart of the+Ocean</text:p></text:note-body></text:note><text:span text:style-name="Strong_20_Emphasis">+in the Atlantic Ocean</text:span>…</text:p>++```
+ test/command/10805.md view
@@ -0,0 +1,19 @@+```+% pandoc -t typst -f latex+\begin{equation}+  \label{eq:U}+  U = A+\end{equation}+^D+$ U = A $<eq:U>+```++```+% pandoc -t typst -f latex+\begin{equation}+  \label{eq:U 2}+  U = A+\end{equation}+^D+$ U = A $#label("eq:U 2")+```
+ test/command/10812.md view
@@ -0,0 +1,41 @@+Check that the `four_space_rule` extension works for plain writer.++```+% pandoc -f markdown -t plain+four_space_rule+This is the title++Here we fix:++- a+- b+- c+^D+This is the title++Here we fix:++-   a+-   b+-   c+```++Check that the `four_space_rule` extension is off by default.++```+% pandoc -f markdown -t plain+This is the title++Here we fix:++- a+- b+- c+^D+This is the title++Here we fix:++- a+- b+- c+```
+ test/command/10816.md view
@@ -0,0 +1,7 @@+```+% pandoc -f markdown -t typst+# Test①+^D+= Test①+#label("test①")+```
+ test/command/10825.md view
@@ -0,0 +1,39 @@+```+% pandoc -f docbook -t html+<?xml version="1.0" encoding="utf-8"?>+<book xmlns="http://docbook.org/ns/docbook" version="5.0">+  <info><title>Literallayout test</title></info>+  <chapter>+    <info><title>Literallayout without class</title></info>+    <literallayout>First line.+Second line.+  Third line, indented two spaces.</literallayout>+  </chapter>+  <chapter>+    <info><title>Literallayout with normal class</title></info>+    <literallayout class="normal">First line.+Second line.+  Third line, indented two spaces.</literallayout>+  </chapter>+  <chapter>+    <info><title>Literallayout with monospaced</title></info>+    <literallayout class="monospaced">First line.+Second line.+  Third line, indented two spaces.</literallayout>+  </chapter>+</book>+^D+<h1>Literallayout without class</h1>+<div class="line-block">First line.<br />+Second line.<br />+  Third line, indented two spaces.</div>+<h1>Literallayout with normal class</h1>+<div class="line-block">First line.<br />+Second line.<br />+  Third line, indented two spaces.</div>+<h1>Literallayout with monospaced</h1>+<pre><code>First line.+Second line.+  Third line, indented two spaces.</code></pre>++```
+ test/command/10836.md view
@@ -0,0 +1,12 @@+```+% pandoc -f org -t latex+Some equation here+\begin{equation}+x = y+\end{equation}+where $x$ is something important.+^D+Some equation here \begin{equation}+x = y+\end{equation} where \(x\) is something important.+```
+ test/command/10848.md view
@@ -0,0 +1,82 @@+```+% pandoc -f html -t markdown+<table>+<tr>+<td colspan="3">A</td>+<td rowspan="1" colspan="2">F</td>+</tr>+<tr>+<td>C</td>+<td colspan="2">B</td>+<td colspan="2">H</td>+</tr>+<tr>+<td colspan="2">D</td>+<td colspan="2">E</td>+<td>G</td>+</tr>+</table>+^D++---+---+---+---+---++| A         | F     |++---+-------+-------++| C | B     | H     |++---+---+---+---+---++| D     | E     | G |++-------+-------+---++```++```+% pandoc -f html -t markdown+<table>+<tr>+<td colspan="2">A</td>+<td colspan="2">J</td>+<td rowspan="3">F</td>+</tr>+<tr>+<td rowspan="3">C</td>+<td>B</td>+<td rowspan="2" colspan="2">H</td>+</tr>+<tr>+<td>D</td>+</tr>+<tr>+<td colspan="4">K</td>+</tr>+</table>+^D++---+---+-------+---++| A     | J     | F |++---+---+-------+   |+| C | B | H     |   |+|   +---+       |   |+|   | D |       |   |+|   +---+-------+---++|   | K             |++---+---------------++```++```+% pandoc -f html -t markdown-simple_tables-multiline_tables-pipe_tables+<table>+  <tbody>+    <tr>+      <td>a</td>+      <td></td>+    </tr>+    <tr>+      <td></td>+      <td></td>+    </tr>+  </tbody>+</table>+^D++---+---++| a |   |++---+---++|   |   |++---+---++```+
+ test/command/10855.md view
@@ -0,0 +1,71 @@+```+% pandoc -t markdown++----------+----++| h1       | h2 |++:===:+===:+:===++| A        | B  |++-----+----+----++| C   | D  | E  |++-----+----+----++^D++-------------+----++| h1          | h2 |++:====:+=====:+:===++| A           | B  |++------+------+----++| C    | D    | E  |++------+------+----+++```++```+% pandoc -t markdown++-----+----+----++| h1  | h2 | h3 |++:===:+===:+:===++| A        | B  |++-----+----+----++| C   | D  | E  |++-----+----+----++^D++------+------+----++| h1   | h2   | h3 |++:====:+=====:+:===++| A           | B  |++------+------+----++| C    | D    | E  |++------+------+----+++```++```+% pandoc -t markdown++:------:+:-----------:++| hello  | ![a](b.png) |++--------+-------------++| hello  | ![c](b.png) |++--------+-------------++^D++:------:+:-----------:++| hello  | ![a](b.png) |++--------+-------------++| hello  | ![c](b.png) |++--------+-------------+++```++```+% pandoc -t markdown++:------:+:-----------:++| hello  | ![a](b.png) |++--------+-------------++| hello  | ![c](b.png) |++--------+-------------++^D++:------:+:-----------:++| hello  | ![a](b.png) |++--------+-------------++| hello  | ![c](b.png) |++--------+-------------+++```
+ test/command/10862.md view
@@ -0,0 +1,6 @@+```+% pandoc --embed-resources+<script></script>+^D+<script></script>+```
+ test/command/10867.md view
@@ -0,0 +1,26 @@+```+% pandoc -f native -t markdown-raw_html+[ Figure+    ( "fig:foo" , [] , [ ( "label" , "1.1" ) ] )+    (Caption+       Nothing+       [ Plain+           [ Str "Figure" , Space , Str "1.1:" , Space , Str "Figure" ]+       ])+    [ Plain+        [ Image+            ( "" , [] , [] )+            [ Str "Figure" , Space , Str "1.1:" , Space , Str "Figure" ]+            ( "./image.png" , "" )+        ]+    ]+]+^D+:::: {#fig:foo .figure label="1.1"}+![Figure 1.1: Figure](./image.png)++::: caption+Figure 1.1: Figure+:::+::::+```
+ test/command/10884.md view
@@ -0,0 +1,17 @@+```+% pandoc -f markdown -t markdown+  header1   header2+  --------- ---------+  r1c1      r1c2+  r2c1      r2c2++  : mycaption {#myid .myclass key="value"}+^D+  header1   header2+  --------- ---------+  r1c1      r1c2+  r2c1      r2c2++  : mycaption {#myid .myclass key="value"}++```
+ test/command/10889.md view
@@ -0,0 +1,16 @@+```+% pandoc+apple++: pomaceous++  fruit+^D+<dl>+<dt>apple</dt>+<dd>+<p>pomaceous</p>+<p>fruit</p>+</dd>+</dl>+```
+ test/command/10890.md view
@@ -0,0 +1,15 @@+```+% pandoc --tab-stop=2 --from=native --to=markdown+[ DefinitionList+    [ ( [ Str "apple" ]+      , [ [ Para [ Str "pomaceous" ] , Para [ Str "fruit" ] ] ]+      )+    ]+]+^D+apple++: pomaceous++  fruit+```
+ test/command/10912.md view
@@ -0,0 +1,16 @@+```+% pandoc -f docbook -t native+<orderedlist numeration="arabic" startingnumber="4">+<listitem>+<simpara>Para1</simpara>+</listitem>+<listitem>+<simpara>Para2</simpara>+</listitem>+</orderedlist>+^D+[ OrderedList+    ( 4 , Decimal , DefaultDelim )+    [ [ Para [ Str "Para1" ] ] , [ Para [ Str "Para2" ] ] ]+]+```
+ test/command/10915.md view
@@ -0,0 +1,8 @@+```+% pandoc -f latex+\newcommand{\a}{\ifmmode x \else y \fi}+$\a$ and \a+^D+<p><span class="math inline"><em>x</em></span> and y</p>+```+
+ test/command/10919.md view
@@ -0,0 +1,21 @@+# Org output with smart quotes turned on++```+% pandoc -t org+smart_quotes -s+"It's nice" she said.+^D+#+options: ':t++"It's nice" she said.+```++Same test, but with special strings turned off.+```+% pandoc -t org+smart_quotes-special_strings -s+"It's nice" she said.+^D+#+options: ':t+#+options: -:nil++"It’s nice" she said.+```
+ test/command/10926.md view
@@ -0,0 +1,19 @@+````+% pandoc -f html -t gfm+<div class="sourceCode" id="cb1"><pre+class="sourceCode ruby"><code class="sourceCode ruby"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="fu">test</span></span></code></pre></div>+^D+``` ruby+test+```+````++````+% pandoc -f html -t gfm+<pre+class="border language-ruby"><code class="sourceCode ruby"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="fu">test</span></span></code></pre>+^D+``` ruby+test+```+````
+ test/command/10942.md view
@@ -0,0 +1,97 @@+Ungrouped field instruction:+```+% pandoc -f rtf -t native+{\rtf1\ansi\deff0+{\fonttbl{\f0\froman Times New Roman;}}+{\colortbl;\red0\green0\blue0;}+\deftab720++\trowd\trleft0\cellx2000\cellx4000+\pard\intbl+{{\field{\*\fldinst HYPERLINK "https://example.com" }{\fldrslt {\hich\af0\loch\hich\af0\loch\cf0\f0\cf0\f0\loch+{\*\bkmkstart _dx_frag_StartFragment}{\*\bkmkend _dx_frag_StartFragment}Problem Text}}}}\cell+\pard\intbl Normal Text\cell+\row++\trowd\trleft0\cellx2000\cellx4000+\pard\intbl Simple Text\cell+\pard\intbl More Text\cell+\row+}+^D+[ Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    ]+    (TableHead ( "" , [] , [] ) [])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Para+                    [ Link+                        ( "" , [] , [] )+                        [ Str "Problem" , Space , Str "Text" ]+                        ( "https://example.com" , "" )+                    ]+                ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Para [ Str "Normal" , Space , Str "Text" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Para [ Str "Simple" , Space , Str "Text" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Para [ Str "More" , Space , Str "Text" ] ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+]+```++Additionally, ungrouped field result:+```+% pandoc -f rtf -t native+{\rtf1\ansi\ansicpg1252\cocoartf2867+\cocoatextscaling0\cocoaplatform1{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}+{\*\expandedcolortbl;;\cssrgb\c0\c0\c0;}+\paperw11905\paperh16837\margl1133\margr1133\margb1133\margt1133+\deftab720+\pard\pardeftab720\partightenfactor0+{\field{\*\fldinst{HYPERLINK "https://example.com"}}{\fldrslt +\f0\fs22 \cf2 \up0 \nosupersub \ul \ulc2 link}}}+^D+[ Para+    [ Underline+        [ Link+            ( "" , [] , [] )+            [ Str "link" ]+            ( "https://example.com" , "" )+        ]+    ]+]+```
+ test/command/10965.md view
@@ -0,0 +1,50 @@+```+% pandoc -f markdown -t typst+::: {lang="en"}+This text should be in English.+:::+^D+#block[+#set text(lang: "en");+This text should be in English.++]+```++```+% pandoc -f markdown -t typst+::: {lang="fr"}+Ce texte devrait être en français.+:::+^D+#block[+#set text(lang: "fr");+Ce texte devrait être en français.++]+```++```+% pandoc -f markdown -t typst+::: {lang="de-DE"}+Dieser Text sollte auf Deutsch sein.+:::+^D+#block[+#set text(lang: "de");+Dieser Text sollte auf Deutsch sein.++]+```++```+% pandoc -f markdown -t typst+::: {lang=""}+This should not have lang set.+:::+^D+#block[+This should not have lang set.++]+```
+ test/command/10983.md view
@@ -0,0 +1,22 @@+```+% pandoc --citeproc --csl command/chicago-fullnote-bibliography.csl -t plain+---+references:+- id: test4+  type: blog-post+  title: "Username as author"+  author:+  - brtw+  container-title: "Reddit"+  issued:+    year: 2004+suppress-bibliography: true+...++[@test4]+^D+[1]++[1] brtw, “Username as Author,” Reddit, 2004.++```
+ test/command/10984.md view
@@ -0,0 +1,16 @@+ ```+ % pandoc -f html -t djot+<h1 id="foo" class="a b">Hi</hi>+^D+{#foo .a .b}+# Hi+```++In this one the id is suppressed by the djot writer because+the same one would be automatically generated by the djot reader:+```+% pandoc -f html -t djot+<h2 id="Introduction">Introduction</h2>+^D+## Introduction+```
+ test/command/11006.md view
@@ -0,0 +1,56 @@+```+% pandoc -f html -t asciidoc+<ul>+  <li>+    <p>Paragraph one</p>+    <p>Paragraph two to force a list continuation</p>+    <ul>+      <li>First nested</li>+      <li>Second nested</li>+    </ul>+  </li>+</ul>++<p>How about ordered lists?</p>++<ol>+  <li>+    <p>Paragraph one</p>+    <p>Paragraph two to force a list continuation</p>+    <ol><li>Nested item</li></ol>+  </li>+</ol>++<p>With non-default attributes:</p>++<ol>+  <li>+    <p>Paragraph one</p>+    <p>Paragraph two to force a list continuation</p>+    <ol start=5><li>Nested item</li></ol>+  </li>+</ol>+^D+* Paragraph one+++Paragraph two to force a list continuation++** First nested+** Second nested++How about ordered lists?++. Paragraph one+++Paragraph two to force a list continuation++.. Nested item++With non-default attributes:++. Paragraph one+++Paragraph two to force a list continuation+[start=5]+.. Nested item+```
+ test/command/11013.md view
@@ -0,0 +1,23 @@+```+% pandoc --csl command/chicago-fullnote-bibliography.csl -C --wrap=none -t plain+---+references:+- id: test10+  type: blog-post+  title: "Test 10: Lowercase username in brackets, Works!"+  author:+  - literal: "[deleted]"+  container-title: "Reddit"+  issued:+    year: 2009+...++blah [@test10].+^D+blah.[1]++[deleted]. “Test 10: Lowercase Username in Brackets, Works!” Reddit, 2009.++[1] [deleted], “Test 10: Lowercase Username in Brackets, Works!” Reddit, 2009.++```
+ test/command/11014.md view
@@ -0,0 +1,9 @@+```+% pandoc -f djot -t html+{.foo}+- bar+^D+<ul class="foo">+<li>bar</li>+</ul>+```
+ test/command/11017.md view
@@ -0,0 +1,9 @@+```+% pandoc -t markdown -f typst+#show heading: smallcaps++= Introduction+^D+# [Introduction]{.smallcaps}++```
+ test/command/11046.md view
@@ -0,0 +1,19 @@+```+% pandoc --citeproc -t plain+smart --csl command/chicago-note-bibliography.csl+---+references:+- id: doe+  title: Title+  type: book+  date: 2006+  author: John Doe+...++blah blah [@doe]---blah blah.+^D+blah blah[1]---blah blah.++John Doe. Title, n.d.++[1] John Doe, Title.+```
+ test/command/11047.md view
@@ -0,0 +1,7 @@+```+% pandoc -t typst --wrap=auto+Full-time study: 2001-2003; Thesis submission: Nov 2005; Award: Jul 2006.+^D+Full-time study: 2001-2003; Thesis submission: Nov 2005; Award: Jul+\2006.+```
+ test/command/11048.md view
@@ -0,0 +1,48 @@+```+% pandoc -f biblatex -t markdown -s+@article{khatri2021spooky,+    title = {Spooky action at a global distance: analysis of space-based+             entanglement distribution for the quantum internet},+    author = {Khatri, Sumeet and Brady, Anthony J and Desporte, Ren{\'e}e A and+              Bart, Manon P and Dowling, Jonathan P},+    journal = {{npj} Quantum Information},+    volume = {7},+    number = {1},+    pages = {4},+    doi = {10.1038/s41534-020-00327-5},+    url = {https://doi.org/10.1038/s41534-020-00327-5},+    year = {2021},+    publisher = {Nature Publishing Group UK London},+}+^D+---+nocite: "[@*]"+references:+- author:+  - family: Khatri+    given: Sumeet+  - family: Brady+    given: Anthony J+  - family: Desporte+    given: Renée A+  - family: Bart+    given: Manon P+  - family: Dowling+    given: Jonathan P+  container-title: "[npj]{.nocase} Quantum Information"+  doi: 10.1038/s41534-020-00327-5+  id: khatri2021spooky+  issue: 1+  issued: 2021+  page: 4+  publisher: Nature Publishing Group UK London+  title: "Spooky action at a global distance: Analysis of space-based+    entanglement distribution for the quantum internet"+  title-short: Spooky action at a global distance+  type: article-journal+  url: "https://doi.org/10.1038/s41534-020-00327-5"+  volume: 7+---+++```
+ test/command/11090.md view
@@ -0,0 +1,49 @@+```+% pandoc -f typst -t native+#include "command/11090/ch1.typ"++== Chapter Two++#figure(+  image("command/11090/media/image1.png"),+  caption: [This is an image.] +)+^D+[ Header+    2 ( "" , [] , [] ) [ Str "Chapter" , Space , Str "One" ]+, Figure+    ( "" , [] , [] )+    (Caption+       Nothing [ Para [ Str "An" , Space , Str "image." ] ])+    [ Para+        [ Image+            ( "" , [] , [] )+            []+            ( "command/11090/media/image1.png" , "" )+        ]+    ]+, Header+    2 ( "" , [] , [] ) [ Str "Chapter" , Space , Str "Two" ]+, Figure+    ( "" , [] , [] )+    (Caption+       Nothing+       [ Para+           [ Str "This"+           , Space+           , Str "is"+           , Space+           , Str "an"+           , Space+           , Str "image."+           ]+       ])+    [ Para+        [ Image+            ( "" , [] , [] )+            []+            ( "command/11090/media/image1.png" , "" )+        ]+    ]+]+```
+ test/command/11090/ch1.typ view
@@ -0,0 +1,6 @@+== Chapter One++#figure(+  image("media/image1.png"),+  caption: [An image.]+)
+ test/command/11101.md view
@@ -0,0 +1,15 @@+```+% pandoc -f typst -t native+First paragraph.++#pagebreak()++Second paragraph.+^D+[ Para [ Str "First" , Space , Str "paragraph." ]+, Div+    ( "" , [ "page-break" ] , [ ( "wrapper" , "1" ) ] )+    [ HorizontalRule ]+, Para [ Str "Second" , Space , Str "paragraph." ]+]+```
+ test/command/11113.docx view

binary file changed (absent → 14206 bytes)

+ test/command/11113.md view
@@ -0,0 +1,7 @@+```+% pandoc command/11113.docx -t plain+^D+Colored:❤️😏📖👌😒🤍++BW: 😊︎+```
+ test/command/11124.md view
@@ -0,0 +1,10 @@+The heading is "unlinked" before adding it to the TOC.++```+% pandoc --to=latex+<http://example.com/> {-}+=========================+^D+\section*{\texorpdfstring{\url{http://example.com/}}{http://example.com/}}\label{httpexample.com}+\addcontentsline{toc}{section}{{http://example.com/}}+```
+ test/command/11128.md view
@@ -0,0 +1,23 @@+```+% pandoc -f html -t markdown_strict+pipe_tables-raw_html+<table>+<tr>+<th class="" colspan="2" rowspan="1"><b>Subject</b></th>+<th class=""><b>Grade</b></th>+</tr>+<tr>+<td class="" colspan="1" rowspan="2">Physics</td>+<td class="">Practical</td>+<td class="">A</td>+</tr>+<tr>+<td class="">Theory</td>+<td class="">B+</td>+</tr>+</table>+^D+| **Subject** |           | **Grade** |+|-------------|-----------|-----------|+| Physics     | Practical | A         |+|             | Theory    | B+        |+```
+ test/command/11140.md view
@@ -0,0 +1,71 @@+```+% pandoc -f rst -t native+.. figure:: image.png+   :alt: my alt++   Caption+^D+[ Figure+    ( "" , [] , [] )+    (Caption Nothing [ Plain [ Str "Caption" ] ])+    [ Plain+        [ Image+            ( "" , [] , [] )+            [ Str "my" , Space , Str "alt" ]+            ( "image.png" , "" )+        ]+    ]+]+```++```+% pandoc -f rst -t native+.. figure:: image.png++   Caption+^D+[ Figure+    ( "" , [] , [] )+    (Caption Nothing [ Plain [ Str "Caption" ] ])+    [ Plain+        [ Image+            ( "" , [] , [] ) [ Str "Caption" ] ( "image.png" , "" )+        ]+    ]+]+```++```+% pandoc -f native -t markdown+[ Figure+    ( "" , [] , [] )+    (Caption+       Nothing [ Plain [ Str "Caption" ] ])+    [ Plain+        [ Image ( "" , [] , [] ) [ Str "my", Space, Str "alt" ] ( "image.png" , "" )+        ]+    ]+]+^D+![Caption](image.png){alt="my alt"}+```++Ignore `\pandocbounded`:+```+% pandoc -f latex -t native+\begin{figure}+\centering+\pandocbounded{\includegraphics[keepaspectratio,alt={Caption}]{image.png}}+\caption{Caption}+\end{figure}+^D+[ Figure+    ( "" , [] , [] )+    (Caption Nothing [ Plain [ Str "Caption" ] ])+    [ Para+        [ Image+            ( "" , [] , [] ) [ Str "Caption" ] ( "image.png" , "" )+        ]+    ]+]+```
+ test/command/11150.md view
@@ -0,0 +1,29 @@+```+% pandoc -f rst+===  =====+int  float+===  =====+10   9.90+-10  9.90+===  =====+^D+<table>+<thead>+<tr>+<th>int</th>+<th>float</th>+</tr>+</thead>+<tbody>+<tr>+<td>10</td>+<td>9.90</td>+</tr>+<tr>+<td>-10</td>+<td>9.90</td>+</tr>+</tbody>+</table>++```
+ test/command/11162.md view
@@ -0,0 +1,19 @@+```+% pandoc -f native -t rst+[ BulletList+    [ [ Plain [ Str "list" ]+      , CodeBlock ( "" , [ "ruby" ] , [] ) "code = 7 # comment"+      ]+    , [ Plain [ Str "second" , Space , Str "item" ] ]+    ]+]+^D+- list++  .. code:: ruby++     code = 7 # comment++- second item++```
+ test/command/11188.md view
@@ -0,0 +1,80 @@+Parsing PARAMETERS of Org-mode blocks++```+% pandoc -f org --to=native+#+attr_html: :width 10px+#+BEGIN_myex :this that+huhu+#+END_myex+^D+[ Div+    ( ""+    , [ "myex" ]+    , [ ( "width" , "10px" ) , ( "this" , "that" ) ]+    )+    [ Para [ Str "huhu" ] ]+]+```++Python-style parameters are accepted, too.++```+% pandoc -f org --to=native+#+BEGIN_myblock width=10px+[[image.svg][logo]]+#+END_myblock+^D+[ Div+    ( "" , [ "myblock" ] , [ ( "width" , "10px" ) ] )+    [ Para+        [ Span+            ( ""+            , [ "spurious-link" ]+            , [ ( "target" , "image.svg" ) ]+            )+            [ Emph [ Str "logo" ] ]+        ]+    ]+]+```++The fallback is to put the remainder of the line into a `parameters`+attribute.++```+% pandoc -f org --to=native+#+BEGIN_myblock these are parameters in an unsupported format+/OK/+#+END_myblock+^D+[ Div+    ( ""+    , [ "myblock" ]+    , [ ( "parameters"+        , "these are parameters in an unsupported format"+        )+      ]+    )+    [ Para [ Emph [ Str "OK" ] ] ]+]+```++Also works on dynamic blocks.++```+% pandoc -f org --to=markdown+#+BEGIN: clocktable :scope subtree :maxlevel 3+#+CAPTION: Clock summary at [2025-10-18 Sat 17:23]+| Headline     | Time   |+|--------------+--------|+| *Total time* | *0:00* |+#+END:+^D+::: {.clocktable scope="subtree" maxlevel="3"}+  Headline         Time+  ---------------- ----------+  **Total time**   **0:00**++  : Clock summary at \[2025-10-18 Sat 17:23\]+:::+```
+ test/command/11210.md view
@@ -0,0 +1,13 @@+```+% pandoc -t typst -f man+.PP+.IR login (1)+.PP+and a regular (paren) that should not be escaped.+^D+#emph[login]\(1)++and a regular (paren) that should not be escaped.++```+
+ test/command/11211.md view
@@ -0,0 +1,16 @@+```+% pandoc -f rtf -t native+{\field{\*\fldinst{\rtlch\ab0\ai0\af2\alang1025\afs22\ltrch\b0\i0\fs22\lang1033\langnp1033\langfe1033\langfenp1033+\loch\af2\dbch\af2\hich\f2\insrsid10976062\strike0\ulnone\cf1 HYPERLINK "https://example.com"}{\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b28000000680074007400700073003a002f002f006500780061006d0070006c0065002e0063006f006d000000}}+{\fldrslt{\rtlch\ab0\ai0\af2\alang1025\afs22\ltrch\b0\i0\fs22\lang1033\langnp1033\langfe1033\langfenp1033\loch\af2\dbch\af2\hich\f2\strike0\ul\cf2 link}}}+^D+[ Para+    [ Underline+        [ Link+            ( "" , [] , [] )+            [ Str "link" ]+            ( "https://example.com" , "" )+        ]+    ]+]+```
+ test/command/11253.md view
@@ -0,0 +1,27 @@+```+% pandoc -f markdown -t native+\ifstrequal{hello}{hello}{TRUE}{FALSE}+\ifstrequal{hello}{world}{TRUE}{FALSE}+^D+[ Para+    [ RawInline (Format "tex") "TRUE"+    , SoftBreak+    , RawInline (Format "tex") "FALSE"+    ]+]+```++```+% pandoc -f markdown-latex_macros -t native+\ifstrequal{hello}{hello}{TRUE}{FALSE}+\ifstrequal{hello}{world}{TRUE}{FALSE}+^D+[ Para+    [ RawInline+        (Format "tex") "\\ifstrequal{hello}{hello}{TRUE}{FALSE}"+    , SoftBreak+    , RawInline+        (Format "tex") "\\ifstrequal{hello}{world}{TRUE}{FALSE}"+    ]+]+```
+ test/command/11266.md view
@@ -0,0 +1,19 @@+```+% pandoc -t latex+$$+\begin{eqnarray}+S &\rightarrow& a A                      \nonumber \\+A &\rightarrow& d B \ | \ b A \ | \ c A  \nonumber \\+B &\rightarrow& a c \ | \ b C \ | \ c A  \nonumber \\+C &\rightarrow& \epsilon                 \nonumber+\end{eqnarray}+$$+^D++\begin{eqnarray}+S &\rightarrow& a A                      \nonumber \\+A &\rightarrow& d B \ | \ b A \ | \ c A  \nonumber \\+B &\rightarrow& a c \ | \ b C \ | \ c A  \nonumber \\+C &\rightarrow& \epsilon                 \nonumber+\end{eqnarray}+```
+ test/command/11270.md view
@@ -0,0 +1,25 @@+```+% pandoc -f markdown -t native -s+---+header-includes: |+    \makeatletter+    \beamer@ignorenonframefalse+    \makeatother+...++^D+Pandoc+  Meta+    { unMeta =+        fromList+          [ ( "header-includes"+            , MetaBlocks+                [ RawBlock+                    (Format "tex")+                    "\\makeatletter\n\\beamer@ignorenonframefalse\n\\makeatother"+                ]+            )+          ]+    }+  []+```
+ test/command/11299.md view
@@ -0,0 +1,28 @@+```+% pandoc -f mediawiki -t native+<foo>++<samp>x</samp>++<kbd>x</kbd>++<var>x</var>++<mark>This is ''highlighted''</mark>+^D+[ Para [ Str "<foo>" ]+, Para [ Code ( "" , [ "sample" ] , [] ) "x" ]+, Para [ Span ( "" , [ "kbd" ] , [] ) [ Str "x" ] ]+, Para [ Code ( "" , [ "variable" ] , [] ) "x" ]+, Para+    [ Span+        ( "" , [ "mark" ] , [] )+        [ Str "This"+        , Space+        , Str "is"+        , Space+        , Emph [ Str "highlighted" ]+        ]+    ]+]+```
+ test/command/11300.md view
@@ -0,0 +1,67 @@+```+% pandoc -f docbook -t native -s+<?xml version="1.0"?>+<book xmlns="http://docbook.org/ns/docbook" version="5.0" dir="ltr">+  <info>+    <title>Book title</title>+    <subtitle>Book subtitle</subtitle>+  </info>+  <chapter>+    <info>+      <title>Chapter title</title>+    </info>+    <para>My sentence</para>+  </chapter>+</book>+^D+Pandoc+  Meta+    { unMeta =+        fromList+          [ ( "subtitle"+            , MetaInlines [ Str "Book" , Space , Str "subtitle" ]+            )+          , ( "title"+            , MetaInlines [ Str "Book" , Space , Str "title" ]+            )+          ]+    }+  [ Header+      1 ( "" , [] , [] ) [ Str "Chapter" , Space , Str "title" ]+  , Para [ Str "My" , Space , Str "sentence" ]+  ]+```++```+% pandoc -f docbook -t native -s+<?xml version="1.0"?>+<book xmlns="http://docbook.org/ns/docbook" version="5.0" dir="ltr">+  <chapter>+    <info>+      <title>Chapter title</title>+    </info>+    <para>My sentence</para>+  </chapter>+  <info>+    <title>Book title</title>+    <subtitle>Book subtitle</subtitle>+  </info>+</book>+^D+Pandoc+  Meta+    { unMeta =+        fromList+          [ ( "subtitle"+            , MetaInlines [ Str "Book" , Space , Str "subtitle" ]+            )+          , ( "title"+            , MetaInlines [ Str "Book" , Space , Str "title" ]+            )+          ]+    }+  [ Header+      1 ( "" , [] , [] ) [ Str "Chapter" , Space , Str "title" ]+  , Para [ Str "My" , Space , Str "sentence" ]+  ]+```
+ test/command/11309.md view
@@ -0,0 +1,6 @@+```+% pandoc -f rst -t native+Cho\ **co**\ late+^D+[ Para [ Str "Cho" , Strong [ Str "co" ] , Str "late" ] ]+```
+ test/command/11312.md view
@@ -0,0 +1,21 @@+```+% pandoc -f mediawiki -t texinfo+foofoo++ bar+ baz++foofoo+^D+@node Top+@top Top++foofoo++@example+bar+baz+@end example++foofoo+```
+ test/command/11323.md view
@@ -0,0 +1,12 @@+```+% pandoc -f rst+foo-+   bar+^D+<dl>+<dt>foo-</dt>+<dd>+<p>bar</p>+</dd>+</dl>+```
+ test/command/11341.md view
@@ -0,0 +1,9 @@+```+% pandoc -t commonmark -f html+<h1>The Hobbit<br>or<br>There and Back Again</h1>+^D+The Hobbit\+or\+There and Back Again+====================+```
+ test/command/11342.md view
@@ -0,0 +1,33 @@+Subfigures should be converted to *fig-group* elements.++```+% pandoc -f latex -t jats+\begin{figure}[H]+  \begin{subfigure}+    \centering+    \includegraphics[height=1.5in]{assets/A.png}+    \caption{Graph for function *A*.}+    \label{fig:A}+  \end{subfigure}+  \begin{subfigure}+    \centering+    \includegraphics[height=1.5in]{assets/B.png}+    \caption{Graph for function *B*.}+    \label{fig:B}+  \end{subfigure}+  \label{fig:graphs}+  \caption{Function graphs.}+\end{figure}+^D+<fig-group id="figU003Agraphs">+  <caption><p>Function graphs.</p></caption>+  <fig id="figU003AA">+    <caption><p>Graph for function *A*.</p></caption>+    <graphic mimetype="image" mime-subtype="png" xlink:href="assets/A.png" />+  </fig>+  <fig id="figU003AB">+    <caption><p>Graph for function *B*.</p></caption>+    <graphic mimetype="image" mime-subtype="png" xlink:href="assets/B.png" />+  </fig>+</fig-group>+```
+ test/command/11348.md view
@@ -0,0 +1,61 @@+```+% pandoc -f markdown -t native+$ invalid opening inline math$++$+invalid opening inline math$++$invalid closing inline math $++$invalid closing inline math+$++$valid inline math$+^D+[ Para+    [ Str "$"+    , Space+    , Str "invalid"+    , Space+    , Str "opening"+    , Space+    , Str "inline"+    , Space+    , Str "math$"+    ]+, Para+    [ Str "$"+    , SoftBreak+    , Str "invalid"+    , Space+    , Str "opening"+    , Space+    , Str "inline"+    , Space+    , Str "math$"+    ]+, Para+    [ Str "$invalid"+    , Space+    , Str "closing"+    , Space+    , Str "inline"+    , Space+    , Str "math"+    , Space+    , Str "$"+    ]+, Para+    [ Str "$invalid"+    , Space+    , Str "closing"+    , Space+    , Str "inline"+    , Space+    , Str "math"+    , SoftBreak+    , Str "$"+    ]+, Para [ Math InlineMath "valid inline math" ]+]+```
+ test/command/11362.md view
@@ -0,0 +1,17 @@+```+% pandoc -f markdown -t asciidoc+This is a _test_[^1].++And yet another **one**[^1].++We can also try to write #hashtags [this]{.test}.++[^1]: Test footnote.+^D+This is a __test__footnote:[Test footnote.].++And yet another **one**footnote:[Test footnote.].++We can also try to write ++#++hashtags [.test]#this#.++```
+ test/command/11364.md view
@@ -0,0 +1,75 @@+```+% pandoc -f rtf -t native+{\rtf1\ansi\deff3\adeflang1025+{\fonttbl{\f0\froman\fprq2\fcharset0 Times New Roman;}{\f1\froman\fprq2\fcharset2 Symbol;}{\f2\fswiss\fprq2\fcharset0 Arial;}{\f3\froman\fprq2\fcharset0 Liberation Serif{\*\falt Times New Roman};}{\f4\fnil\fprq0\fcharset2 OpenSymbol{\*\falt Arial Unicode MS};}{\f5\fswiss\fprq2\fcharset0 Liberation Sans{\*\falt Arial};}{\f6\fnil\fprq2\fcharset0 Noto Sans CJK SC;}{\f7\fnil\fprq2\fcharset0 Matangi Light;}{\f8\fnil\fprq0\fcharset128 Matangi Light;}{\f9\fnil\fprq0\fcharset128 OpenSymbol{\*\falt Arial Unicode MS};}}+{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}+{\stylesheet{\s0\snext0\widctlpar\hyphpar0\ltrpar\kerning1\cf0\rtlch\af7\afs24\alang1081\ltrch\hich\af3\afs24\alang1033\dbch\af10\langfe2052\loch\f3\fs24\lang1033 Normal;}+{\*\cs15\snext15\rtlch\af4\ltrch\hich\af4\dbch\af4\loch\f4 Bullets;}+{\s16\sbasedon0\snext17\sb240\sa120\keepn\rtlch\af7\afs28\ltrch\hich\af5\afs28\dbch\af6\loch\f5\fs28 Heading;}+{\s17\sbasedon0\snext17\sl276\slmult1\sb0\sa140 Body Text;}+{\s18\sbasedon17\snext18\rtlch\af8\ltrch List;}+{\s19\sbasedon0\snext19\sb120\sa120\noline\rtlch\af8\afs24\ai\ltrch\fs24\i caption;}+{\s20\sbasedon0\snext20\noline\rtlch\af8\ltrch Index;}+{\s21\sbasedon0\snext21\nowidctlpar\noline Table Contents;}+}{\*\listtable{\list\listtemplateid1+{\listlevel\levelnfc23\leveljc0\levelstartat1\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f9\rtlch\af4\ltrch\fi-360\li720}+{\listlevel\levelnfc23\leveljc0\levelstartat1\levelfollow0{\leveltext \'01\u9702 ?;}{\levelnumbers;}\f9\rtlch\af4\ltrch\fi-360\li1080}+{\listlevel\levelnfc23\leveljc0\levelstartat1\levelfollow0{\leveltext \'01\u9642 ?;}{\levelnumbers;}\f9\rtlch\af4\ltrch\fi-360\li1440}+{\listlevel\levelnfc23\leveljc0\levelstartat1\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f9\rtlch\af4\ltrch\fi-360\li1800}+{\listlevel\levelnfc23\leveljc0\levelstartat1\levelfollow0{\leveltext \'01\u9702 ?;}{\levelnumbers;}\f9\rtlch\af4\ltrch\fi-360\li2160}+{\listlevel\levelnfc23\leveljc0\levelstartat1\levelfollow0{\leveltext \'01\u9642 ?;}{\levelnumbers;}\f9\rtlch\af4\ltrch\fi-360\li2520}+{\listlevel\levelnfc23\leveljc0\levelstartat1\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f9\rtlch\af4\ltrch\fi-360\li2880}+{\listlevel\levelnfc23\leveljc0\levelstartat1\levelfollow0{\leveltext \'01\u9702 ?;}{\levelnumbers;}\f9\rtlch\af4\ltrch\fi-360\li3240}+{\listlevel\levelnfc23\leveljc0\levelstartat1\levelfollow0{\leveltext \'01\u9642 ?;}{\levelnumbers;}\f9\rtlch\af4\ltrch\fi-360\li3600}\listid1}+{\list\listtemplateid2+{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0}+{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0}+{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0}+{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0}+{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0}+{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0}+{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0}+{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0}+{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0}\listid2}+}{\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}{\listoverride\listid2\listoverridecount0\ls2}}{\*\generator LibreOffice/25.8.4.2$Linux_X86_64 LibreOffice_project/580$Build-2}{\info{\creatim\yr2025\mo12\dy28\hr10\min51}{\revtim\yr2025\mo12\dy28\hr10\min53}{\printim\yr0\mo0\dy0\hr0\min0}}{\*\userprops}\deftab709+\hyphauto1\viewscale140\formshade\nobrkwrptbl\paperh15840\paperw12240\margl1134\margr1134\margt1134\margb1134\sectd\sbknone\sftnnar\saftnnrlc\sectunlocked1\pgwsxn12240\pghsxn15840\marglsxn1134\margrsxn1134\margtsxn1134\margbsxn1134\ftnbj\ftnstart1\ftnrstcont\ftnnar\fet\aftnrstcont\aftnstart1\aftnnrlc+{\*\ftnsep\chftnsep}\pgndec\pard\plain \s0\widctlpar\hyphpar0\ltrpar\kerning1\cf0\rtlch\af7\afs24\alang1081\ltrch\hich\af3\afs24\alang1033\dbch\af10\langfe2052\loch\f3\fs24\lang1033{\listtext\pard\plain \rtlch\af4\ltrch\hich\af4\dbch\af4\loch\f4 \u8226\'95\tab}\ilvl0\ls1 \fi-360\li720\lin720\ql\ltrpar{+List item}+\par \trowd\trql\ltrrow\trpaddft3\trpaddt0\trpaddfl3\trpaddl0\trpaddfb3\trpaddb0\trpaddfr3\trpaddr0\clbrdrt\brdrs\brdrw10\brdrcf1\clpadfl3\clpadl55\clbrdrl\brdrs\brdrw10\brdrcf1\clpadft3\clpadt55\clbrdrb\brdrs\brdrw10\brdrcf1\clpadfb3\clpadb55\clpadfr3\clpadr55\cellx4986\clbrdrt\brdrs\brdrw10\brdrcf1\clpadfl3\clpadl55\clbrdrl\brdrs\brdrw10\brdrcf1\clpadft3\clpadt55\clbrdrb\brdrs\brdrw10\brdrcf1\clpadfb3\clpadb55\clbrdrr\brdrs\brdrw10\brdrcf1\clpadfr3\clpadr55\cellx9972\pard\plain \s21\nowidctlpar\noline\intbl\ql\ltrpar{+A}\cell\pard\plain \s21\nowidctlpar\noline\intbl\ql\ltrpar{+B}\cell\row\pard \pard\plain \s0\widctlpar\hyphpar0\ltrpar\kerning1\cf0\rtlch\af7\afs24\alang1081\ltrch\hich\af3\afs24\alang1033\dbch\af10\langfe2052\loch\f3\fs24\lang1033\ql\ltrpar+\par }+^D+[ BulletList+    [ [ Para [ Str "List" , Space , Str "item" ] ] ]+, Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    ]+    (TableHead ( "" , [] , [] ) [])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Para [ Str "A" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Para [ Str "B" ] ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+]+```
+ test/command/11374.md view
@@ -0,0 +1,6 @@+```+% pandoc -f native -t asciidoc+[ Para [ SmallCaps [ Str "foo" ] ] ]+^D+[smallcaps]#foo#+```
+ test/command/11384.md view
@@ -0,0 +1,17 @@+```+% pandoc -t markdown -f native+[ Para [ Math DisplayMath "\ne = mc^2\n" ] ]+^D+$$+e = mc^2+$$+```++But we need to collapse spaces around inline math:++```+% pandoc -t markdown -f native+[ Para [ Math InlineMath "\ne=mc\n" ]]+^D+$e=mc$+```
+ test/command/11409.md view
@@ -0,0 +1,11 @@+```+% pandoc -t native+text^[sup]{.class}^+^D+[ Para+    [ Str "text"+    , Superscript+        [ Span ( "" , [ "class" ] , [] ) [ Str "sup" ] ]+    ]+]+```
+ test/command/11420.md view
@@ -0,0 +1,15 @@+````+% pandoc -t revealjs --syntax-highlighting=idiomatic+# Slide++```python+def hello():+    print("Hello")+```+^D+<section id="slide" class="slide level1">+<h1>Slide</h1>+<pre><code class="language-python">def hello():+    print(&quot;Hello&quot;)</code></pre>+</section>+````
+ test/command/11422.md view
@@ -0,0 +1,12 @@+```+% pandoc -f docbook -t markdown+<example>+    <para>+      Example without a title.+    </para>+</example>+^D+::: example+Example without a title.+:::+```
+ test/command/11450.md view
@@ -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." ] ]+    ]+]+```
+ test/command/11455.md view
@@ -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>+```
+ test/command/11463.md view
@@ -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 \'+```
+ test/command/11479.md view
@@ -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.+```
+ test/command/11486.md view
@@ -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',+```
+ test/command/11486/scroll.revealjs view
@@ -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$
+ test/command/11490.md view
@@ -0,0 +1,13 @@+```+% pandoc -t markdown+&lt;&amp;lt;+^D+\<\&lt;+```++```+% pandoc -t markdown+&amp;#xa0;+^D+\&#xa0;+```
+ test/command/11494.md view
@@ -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>+```
+ test/command/11498.md view
@@ -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>+```
+ test/command/11498.png view

binary file changed (absent → 1306 bytes)

+ test/command/11511.md view
@@ -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+```
+ test/command/11534.md view
@@ -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" ] ]+    ]+]++```+
+ test/command/11542.md view
@@ -0,0 +1,47 @@+```+% pandoc -f native -t markdown+[ DefinitionList+    [ ( [ Str "Input" ]+      , [ [ CodeBlock ( "" , [] , [] ) "Term\n\n  : Def" ] ]+      )+    ]+]+^D+Input++:     Term++        : Def+```++```+% pandoc -f markdown -t native+Input++:     Term++        : Def+^D+[ DefinitionList+    [ ( [ Str "Input" ]+      , [ [ CodeBlock ( "" , [] , [] ) "Term\n\n  : Def" ] ]+      )+    ]+]+```++```+% pandoc -f native -t markdown+four_space_rule+[ DefinitionList+    [ ( [ Str "Input" ]+      , [ [ CodeBlock ( "" , [] , [] ) "Term\n\n  : Def" ] ]+      )+    ]+]+^D+Input++:       Term++          : Def+```
+ test/command/11562.md view
@@ -0,0 +1,10 @@+```+% pandoc -t mediawiki+[example](https://example.com/#/#room)++[example](https://example.com/##)+^D+[https://example.com/#/#room example]++[https://example.com/## example]+```
+ test/command/11571.md view
@@ -0,0 +1,18 @@+```+% pandoc -t markdown+:::+A+:::+^D+\::: A \:::+```++```+% pandoc -t commonmark+fenced_divs+:::+A+:::+^D+\::: A \:::+```+
+ test/command/11583.md view
@@ -0,0 +1,16 @@+```+% pandoc -t typst+::: {lang=en}+1. item+2. item+3. item+:::+^D+#block[+#set text(lang: "en");++ item++ item++ item++]+```
+ test/command/11588.md view
@@ -0,0 +1,10 @@+```+% pandoc --typst-input foo=FOO --typst-input bar="bar bim" -f typst -t plain+#sys.inputs.at("foo");++#sys.inputs.at("bar");+^D+FOO++bar bim+```
+ test/command/11589.md view
@@ -0,0 +1,20 @@+```+% pandoc -f markdown -t native+t^[a]{.cb}\ b^+t^[a]{fg=yellow bg=blue}\ b^+^D+[ Para+    [ Str "t"+    , Superscript+        [ Span ( "" , [ "cb" ] , [] ) [ Str "a" ] , Str "\160b" ]+    , SoftBreak+    , Str "t"+    , Superscript+        [ Span+            ( "" , [] , [ ( "fg" , "yellow" ) , ( "bg" , "blue" ) ] )+            [ Str "a" ]+        , Str "\160b"+        ]+    ]+]+```
+ test/command/11598.md view
@@ -0,0 +1,16 @@+```+% pandoc -f typst --wrap=none+#rotate(90deg, figure(+  [body text here inside rotate],+  caption: "Figure 1: How a caption gets lost when rotating",+  supplement: none,+))+^D+<div class="rotate" data-angle="90.0">+<figure>+<p>body text here inside rotate</p>+<figcaption><p>Figure 1: How a caption gets lost when rotating</p></figcaption>+</figure>+</div>++```
+ test/command/11604.md view
@@ -0,0 +1,22 @@+```+% pandoc -f latex -t typst+\begin{table}+  \caption{Caption}\label{tab}+  \begin{tabular}{cc}+    a & b \\ c & d+  \end{tabular}+\end{table}+^D+#figure(+  align(center)[#table(+    columns: 2,+    align: (center,center,),+    [a], [b],+    [c], [d],+  )]+  , caption: [Caption]+  , kind: table+  )+<tab>++```
+ test/command/11608.md view
@@ -0,0 +1,54 @@+```+% pandoc -f latex -t plain+\documentclass[english]{article}+\usepackage[T1]{fontenc}+\usepackage[utf8]{inputenc}+\usepackage{amsthm}+\theoremstyle{plain}+\newtheorem{thm}{\protect\theoremname}+\newtheorem{prop}[thm]{\protect\propositionname}+\usepackage{babel}+\providecommand{\propositionname}{Proposition}+\providecommand{\theoremname}{Theorem}++\begin{document}+\begin{thm}+first theorem+\end{thm}+\begin{prop}+first proposition+\end{prop}++\end{document}+<div class="thm">+<p><strong>Theorem 1</strong>. <em>first theorem</em></p>+</div>+<div class="prop">+<p><strong>Proposition 2</strong>. <em>first proposition</em></p>+</div>+jgm@Johns-MacBook-Air:~/src/pandoc % `make binpath` -f latex -t plain+\documentclass[english]{article}+\usepackage[T1]{fontenc}+\usepackage[utf8]{inputenc}+\usepackage{amsthm}+\theoremstyle{plain}+\newtheorem{thm}{\protect\theoremname}+\newtheorem{prop}[thm]{\protect\propositionname}+\usepackage{babel}+\providecommand{\propositionname}{Proposition}+\providecommand{\theoremname}{Theorem}++\begin{document}+\begin{thm}+first theorem+\end{thm}+\begin{prop}+first proposition+\end{prop}++\end{document}+^D+Theorem 1. first theorem++Proposition 2. first proposition+```
+ test/command/11635.md view
@@ -0,0 +1,28 @@+```+% pandoc -f man -t html+.TH "TEST" "1" "2026-05-08"  "test v1.0.0" "test manual"+.SH HEADING+.TS+tab(;);+l l.+this is a table element \+written in two lines;abcdefg+another \+one;123456+.TE+^D+<h1 id="heading">HEADING</h1>+<table>+<tbody>+<tr>+<td style="text-align: left;">this is a table element written in two+lines</td>+<td style="text-align: left;">abcdefg</td>+</tr>+<tr>+<td style="text-align: left;">another one</td>+<td style="text-align: left;">123456</td>+</tr>+</tbody>+</table>+```
test/command/1166.md view
@@ -17,28 +17,28 @@ ^D <table> <thead>-<tr class="header">+<tr> <th>col 1</th> <th>col 2</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>1</td> <td>Second column of row 1.</td> </tr>-<tr class="even">-<td><p>2</p></td>-<td><p>Second column of row 2. Second line of paragraph.</p></td>+<tr>+<td>2</td>+<td>Second column of row 2. Second line of paragraph.</td> </tr>-<tr class="odd">-<td><p>3</p></td>+<tr>+<td>3</td> <td><ul> <li>Second column of row 3.</li> <li>Second item in bullet list (row 3, column 2).</li> </ul></td> </tr>-<tr class="even">+<tr> <td></td> <td>Row 4; column 1 will be empty.</td> </tr>
+ test/command/11664.md view
@@ -0,0 +1,35 @@+```+% pandoc -t markdown -f html+<table>+        <colgroup>+                <col width="1%"/>+                <col />+        </colgroup>+        <tbody>+                <tr>+                        <td>+                                <p>A</p><p>B</p>+                        </td>+                        <td>+                                Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do+                                eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut+                                enim ad minim veniam, quis nostrud exercitation ullamco laboris+                                nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor+                                in reprehenderit in voluptate velit esse cillum dolore eu fugiat+                                nulla pariatur. Excepteur sint occaecat cupidatat non proident,+                                sunt in culpa qui officia deserunt mollit anim id est laborum.+                        </td>+                </tr>+        </tbody>+</table>+^D++---+------------------------------------------------------------------++| A | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do  |+|   | eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut   |+| B | enim ad minim veniam, quis nostrud exercitation ullamco laboris  |+|   | nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor   |+|   | in reprehenderit in voluptate velit esse cillum dolore eu fugiat |+|   | nulla pariatur. Excepteur sint occaecat cupidatat non proident,  |+|   | sunt in culpa qui officia deserunt mollit anim id est laborum.   |++---+------------------------------------------------------------------++```
+ test/command/11668.md view
@@ -0,0 +1,42 @@+```+% pandoc -f man -t html+TH "TEST" "1" "2026-05-25" "test v1.0.0" "test manual"+.SH HEADING+.TP 4+This is the unindented tag.+This text, along with the table, should be indented.+.TS+tab(;);+l l.+aaa;bbb+ccc;ddd+.TE+This should still be indented, until some other macro is called to change it.+.PP+Like this.+^D+<p>TH "TEST" "1" "2026-05-25" "test v1.0.0" "test manual"</p>+<h1 id="heading">HEADING</h1>+<dl>+<dt>This is the unindented tag.</dt>+<dd>+<p>This text, along with the table, should be indented.</p>+<table>+<tbody>+<tr>+<td style="text-align: left;">aaa</td>+<td style="text-align: left;">bbb</td>+</tr>+<tr>+<td style="text-align: left;">ccc</td>+<td style="text-align: left;">ddd</td>+</tr>+</tbody>+</table>+<p>This should still be indented, until some other macro is called to+change it.</p>+</dd>+</dl>+<p>Like this.</p>++```
+ test/command/11682.md view
@@ -0,0 +1,81 @@+Cell paragraphs that use `\plain` after `\intbl`, together with a single+`\trowd` and `\row` row terminators, should produce a flat table rather+than deeply nested tables.++```+% pandoc -f rtf -t native+{\rtf1\ansi\deff0+{\fonttbl{\f0 Times;}{\f1 Times;}{\f2 Times;}}+\trowd\trgaph60\trleft0+\clvertalt\cellx3245+\clvertalt\cellx6490+\clvertalt\cellx9735+\pard\intbl\s0\ql\plain\f0\fs20\plain\f2\fs22 A\plain\f1\fs22\cell+\pard\intbl\s0\ql\plain\f0\fs20\plain\f2\fs22 B\plain\f1\fs22\cell+\pard\intbl\s0\ql\plain\f0\fs20\plain\f2\fs22 C\plain\f1\fs22\cell+\intbl\row+\pard\intbl\s0\ql\plain\f0\fs20\plain\f2\fs22 1\plain\f1\fs22\cell+\pard\intbl\s0\ql\plain\f0\fs20\plain\f2\fs22 2\plain\f1\fs22\cell+\pard\intbl\s0\ql\plain\f0\fs20\plain\f2\fs22 3\plain\f1\fs22\cell+\intbl\row+}+^D+[ Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    ]+    (TableHead ( "" , [] , [] ) [])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Para [ Str "A" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Para [ Str "B" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Para [ Str "C" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Para [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Para [ Str "2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Para [ Str "3" ] ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+]+```
test/command/1629.md view
@@ -1,5 +1,5 @@ ```-% pandoc -t latex --listings+% pandoc -t latex --syntax-highlighting=idiomatic bla bla `a % b`  *bla bla `a % b`*
test/command/1710.md view
@@ -55,9 +55,9 @@ </div> ^D \begin{frame}{Slide one}-\phantomsection\label{slide-one}+\protect\phantomsection\label{slide-one} \begin{columns}[T]-\begin{column}{0.4\textwidth}+\begin{column}{0.4\linewidth} \begin{itemize} \tightlist \item@@ -67,7 +67,7 @@ \end{itemize} \end{column} -\begin{column}{0.4\textwidth}+\begin{column}{0.4\linewidth} \begin{itemize} \tightlist \item@@ -77,7 +77,7 @@ \end{itemize} \end{column} -\begin{column}{0.1\textwidth}+\begin{column}{0.1\linewidth} ok \end{column} \end{columns}
test/command/1881.md view
@@ -3,7 +3,7 @@ <table> <caption>Demonstration of simple table syntax.</caption> <thead>-<tr class="header">+<tr> <th align="right">Right</th> <th align="left">Left</th> <th align="center">Center</th>@@ -11,7 +11,7 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td align="right">12</td> <td align="left">12</td> <td align="center">12</td>@@ -44,7 +44,7 @@     (TableHead        ( "" , [] , [] )        [ Row-           ( "" , [ "header" ] , [] )+           ( "" , [] , [] )            [ Cell                ( "" , [] , [] )                AlignRight@@ -76,7 +76,7 @@         (RowHeadColumns 0)         []         [ Row-            ( "" , [ "odd" ] , [] )+            ( "" , [] , [] )             [ Cell                 ( "" , [] , [] )                 AlignRight@@ -111,7 +111,7 @@ ``` % pandoc -f html -t native <table>-<tr class="odd">+<tr> <td style="text-align: right;">12</td> <td style="text-align:left;">12</td> <td style="text-align:  center">12</td>@@ -133,7 +133,7 @@         (RowHeadColumns 0)         []         [ Row-            ( "" , [ "odd" ] , [] )+            ( "" , [] , [] )             [ Cell                 ( "" , [] , [] )                 AlignRight
test/command/2118.md view
@@ -8,7 +8,7 @@ \end{figure} ^D [ Figure-    ( "fig:setminus" , [] , [] )+    ( "fig:setminus" , [] , [ ( "latex-placement" , "ht" ) ] )     (Caption        Nothing [ Plain [ Str "Set" , Space , Str "subtraction" ] ])     [ Plain
+ test/command/2337.md view
@@ -0,0 +1,6 @@+```+% pandoc -t asciidoc -f html+<a href="http://example.com">][</a>+^D+http://example.com[++][++]+```
test/command/2434.md view
@@ -6,23 +6,23 @@     2. beta     * gamma ^D-<text:list text:style-name="L1">+<text:list text:style-name="Numbering_20_1">   <text:list-item>-    <text:p text:style-name="P1">a</text:p>+    <text:p text:style-name="List_20_Number_20_Tight">a</text:p>   </text:list-item>   <text:list-item>-    <text:p text:style-name="P1">b</text:p>-    <text:list>+    <text:p text:style-name="List_20_Number_20_Tight">b</text:p>+    <text:list text:style-name="Numbering_20_1">       <text:list-item>-        <text:p text:style-name="P1">alpha</text:p>+        <text:p text:style-name="List_20_Number_20_Tight">alpha</text:p>       </text:list-item>       <text:list-item>-        <text:p text:style-name="P1">beta</text:p>+        <text:p text:style-name="List_20_Number_20_Tight">beta</text:p>       </text:list-item>     </text:list>-    <text:list text:style-name="L2">+    <text:list text:style-name="List_20_1">       <text:list-item>-        <text:p text:style-name="P2">gamma</text:p>+        <text:p text:style-name="List_20_Bullet_20_Tight">gamma</text:p>       </text:list-item>     </text:list>   </text:list-item>@@ -40,20 +40,23 @@      more text -- this line is missing in the odt output ^D-<text:list text:style-name="L1">+<text:list text:style-name="Pandoc_5f_Numbering_5f_1">   <text:list-item>-    <text:p text:style-name="P1">text</text:p>-    <text:p text:style-name="P1">some text</text:p>-    <text:list>+    <text:p text:style-name="List_20_Number">text</text:p>+    <text:p text:style-name="List_20_Number">some text</text:p>+    <text:list text:style-name="Pandoc_5f_Numbering_5f_2">       <text:list-item>-        <text:p text:style-name="P1">sub item 1</text:p>+        <text:p text:style-name="List_20_Number_20_Tight">sub item+        1</text:p>       </text:list-item>       <text:list-item>-        <text:p text:style-name="P1">sub item 2</text:p>+        <text:p text:style-name="List_20_Number_20_Tight">sub item+        2</text:p>       </text:list-item>     </text:list>-    <text:p text:style-name="P1">more text – this line is missing in the-    odt output</text:p>+    <text:p text:style-name="List_20_Number">more text – this line is+    missing in the odt output</text:p>   </text:list-item> </text:list> ```+
test/command/2606.md view
@@ -6,7 +6,7 @@ ^D <table> <tbody>-<tr class="odd">+<tr> <td><p>* hello</p></td> </tr> </tbody>@@ -22,7 +22,7 @@ ^D <table> <tbody>-<tr class="odd">+<tr> <td><ul> <li>hello</li> </ul></td>@@ -40,7 +40,7 @@ ^D <table> <tbody>-<tr class="odd">+<tr> <td><p><code>* hello</code></p></td> </tr> </tbody>
test/command/2649.md view
@@ -7,7 +7,7 @@ ^D <table> <tbody>-<tr class="odd">+<tr> </tr> </tbody> </table>@@ -17,7 +17,7 @@ % pandoc -f mediawiki -t html5 {| border="4" cellspacing="2" cellpadding="0" WIDTH="100%" |------| peildatum Simbase || november 2005 || colspan=2 | '''uitslagen Flohrgambiet''' ||+| peildatum Simbase || november 2005 || colspan=2 | '''uitslagen Flohrgambiet''' |----- | totaal aantal partijen Simbase || 7.316.773 | wit wint || 53%@@ -31,24 +31,24 @@ ^D <table> <tbody>-<tr class="odd">+<tr> <td><p>peildatum Simbase</p></td> <td><p>november 2005</p></td> <td colspan="2"><p><strong>uitslagen Flohrgambiet</strong></p></td> </tr>-<tr class="even">+<tr> <td><p>totaal aantal partijen Simbase</p></td> <td><p>7.316.773</p></td> <td><p>wit wint</p></td> <td><p>53%</p></td> </tr>-<tr class="odd">+<tr> <td><p>percentage (en partijen) Flohrgambiet</p></td> <td><p>0.023 % (1.699)</p></td> <td><p>zwart wint</p></td> <td><p>27%</p></td> </tr>-<tr class="even">+<tr> <td><p>percentage Flohrgambiet in aug 2003</p></td> <td><p>0.035 %</p></td> <td><p>remise</p></td>@@ -80,29 +80,30 @@ ^D <table> <thead>-<tr class="header">+<tr> <th><p>Plaats</p></th> <th><p>Rijder</p></th> <th><p>Aantal</p></th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td><p>1</p></td> <td style="text-align: left;"><p><a href="Sébastien_Loeb"-title="wikilink">Sébastien Loeb</a></p></td>+class="wikilink" title="Sébastien Loeb">Sébastien Loeb</a></p></td> <td><p>78</p></td> </tr>-<tr class="even">+<tr> <td><p>2</p></td> <td style="text-align: left;"><p><strong><a href="Sébastien_Ogier"-title="wikilink">Sébastien Ogier</a></strong></p></td>+class="wikilink" title="Sébastien Ogier">Sébastien+Ogier</a></strong></p></td> <td><p>38</p></td> </tr>-<tr class="odd">+<tr> <td><p>10</p></td> <td style="text-align: left;"><p><a href="Hannu_Mikkola"-title="wikilink">Hannu Mikkola</a></p></td>+class="wikilink" title="Hannu Mikkola">Hannu Mikkola</a></p></td> <td><p>18</p></td> </tr> </tbody>
test/command/2834.md view
@@ -19,11 +19,11 @@   </tr> </table> ^D-+-----------------------------------------------------------------------+-| +------------------------------------------------------------------+  |-| |   -----------                                                    |  |-| |   some text                                                      |  |-| |   -----------                                                    |  |-| +------------------------------------------------------------------+  |-+-----------------------------------------------------------------------+++---------------------------------------------------------------------------++| +-----------------------------------------------------------------------+ |+| |   -----------                                                         | |+| |   some text                                                           | |+| |   -----------                                                         | |+| +-----------------------------------------------------------------------+ |++---------------------------------------------------------------------------+ ```
test/command/2874.md view
@@ -10,5 +10,5 @@ % pandoc -f html -t latex <a name="foo"></a><br/> ^D-\phantomsection\label{foo}{}\strut \\+\protect\phantomsection\label{foo}{}\strut \\ ```
test/command/3113.md view
@@ -11,7 +11,7 @@ [ Para     [ Math         DisplayMath-        "\\begin{aligned}\nA&=&B,\\\\\nC&=&D,\\\\\n%\\end{eqnarray}\n%\\begin{eqnarray}\nE&=&F\n\\end{aligned}"+        "\\begin{eqnarray}\nA&=&B,\\\\\nC&=&D,\\\\\n%\\end{eqnarray}\n%\\begin{eqnarray}\nE&=&F\n\\end{eqnarray}"     ] ] ```
test/command/3314.md view
@@ -18,12 +18,12 @@ <col style="width: 15%" /> </colgroup> <tbody>-<tr class="odd">+<tr> <td>First</td> <td>12.0</td> <td>Example row spanning lines</td> </tr>-<tr class="even">+<tr> <td>Second</td> <td>5.0</td> <td>Another</td>
test/command/3422.md view
@@ -1,7 +1,7 @@ See #3422  ```-% pandoc -t latex --listings+% pandoc -t latex --syntax-highlighting=idiomatic `int main(int argc, const char *argv[]);`{.c} ^D \passthrough{\lstinline[language=C]!int main(int argc, const char *argv[]);!}
test/command/3432.md view
@@ -28,24 +28,24 @@ <col style="width: 54%" /> </colgroup> <thead>-<tr class="header">+<tr> <th>Treat</th> <th>Quantity</th> <th>Description</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>Albatross</td> <td>2.99</td> <td>On a stick!</td> </tr>-<tr class="even">+<tr> <td>Crunchy Frog</td> <td>1.49</td> <td>If we took the bones out, it wouldn't be crunchy, now would it?</td> </tr>-<tr class="odd">+<tr> <td>Gannet Ripple</td> <td>1.99</td> <td>On a stick!</td>@@ -79,24 +79,24 @@ <table> <caption>Frozen Delights!</caption> <thead>-<tr class="header">+<tr> <th>Treat</th> <th>Quantity</th> <th>Description</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>Albatross</td> <td>2.99</td> <td>On a stick!</td> </tr>-<tr class="even">+<tr> <td>Crunchy Frog</td> <td>1.49</td> <td>If we took the bones out, it wouldn't be crunchy, now would it?</td> </tr>-<tr class="odd">+<tr> <td>Gannet Ripple</td> <td>1.99</td> <td>On a stick!</td>@@ -130,24 +130,24 @@ <table> <caption>Frozen Delights!</caption> <thead>-<tr class="header">+<tr> <th>Treat</th> <th>Quantity</th> <th>Description</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>Albatross</td> <td>2.99</td> <td>On a stick!</td> </tr>-<tr class="even">+<tr> <td>Crunchy Frog</td> <td>1.49</td> <td>If we took the bones out, it wouldn't be crunchy, now would it?</td> </tr>-<tr class="odd">+<tr> <td>Gannet Ripple</td> <td>1.99</td> <td>On a stick!</td>@@ -176,17 +176,17 @@ <table> <caption>Frozen Delights!</caption> <tbody>-<tr class="odd">+<tr> <td>Albatross</td> <td>2.99</td> <td>On a stick!</td> </tr>-<tr class="even">+<tr> <td>Crunchy Frog</td> <td>1.49</td> <td>If we took the bones out, it wouldn't be crunchy, now would it?</td> </tr>-<tr class="odd">+<tr> <td>Gannet Ripple</td> <td>1.99</td> <td>On a stick!</td>@@ -219,24 +219,24 @@ <table> <caption>Frozen Delights!</caption> <thead>-<tr class="header">+<tr> <th>Treat</th> <th>Quantity</th> <th>Description</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>Albatross</td> <td>2.99</td> <td></td> </tr>-<tr class="even">+<tr> <td>Crunchy Frog</td> <td></td> <td>If we took the bones out, it wouldn't be crunchy, now would it?</td> </tr>-<tr class="odd">+<tr> <td>Gannet Ripple</td> <td>1.99</td> <td>On a stick!</td>@@ -266,7 +266,7 @@ <table> <caption>Frozen Delights!</caption> <tbody>-<tr class="odd">+<tr> <td>Albatross</td> <td>2.99</td> <td><ul>@@ -274,12 +274,12 @@ <li>In a cup!</li> </ul></td> </tr>-<tr class="even">+<tr> <td>Crunchy Frog</td> <td>1.49</td> <td>If we took the bones out, it wouldn't be crunchy, now would it?</td> </tr>-<tr class="odd">+<tr> <td>Gannet Ripple</td> <td>1.99</td> <td>On a stick!</td>
test/command/3450.md view
@@ -8,5 +8,5 @@ % pandoc -fmarkdown-implicit_figures -t latex ![image](lalune.jpg){height=2em} ^D-\includegraphics[width=\textwidth,height=2em]{lalune.jpg}+\includegraphics[width=\linewidth,height=2em,keepaspectratio,alt={image}]{lalune.jpg} ```
test/command/3487.md view
@@ -7,5 +7,5 @@ ^D Some text --   element+- element ```
test/command/3494.md view
@@ -14,22 +14,22 @@ ^D <table> <tbody>-<tr class="odd">+<tr> <td style="text-align: right;"><span><strong>ﺍ</strong></span></td> <td style="text-align: left;"></td> <td style="text-align: left;"></td> </tr>-<tr class="even">+<tr> <td style="text-align: right;"><strong>ﺄﺤﺴﻨﺘـ(ﻭﺍ) IV</strong></td> <td style="text-align: left;"><em><span>ʾaḥsant(ū)</span></em></td> <td style="text-align: left;">thank you</td> </tr>-<tr class="odd">+<tr> <td style="text-align: right;"><em>blah</em></td> <td style="text-align: left;"><em>blah</em></td> <td style="text-align: left;"><em>blah</em></td> </tr>-<tr class="even">+<tr> <td style="text-align: right;">blah</td> <td style="text-align: left;">blah</td> <td style="text-align: left;">blah</td>
test/command/3499.md view
@@ -9,7 +9,7 @@ <li>|something|</li> <li><table> <tbody>-<tr class="odd">+<tr> <td>else</td> </tr> </tbody>
test/command/3516.md view
@@ -91,6 +91,8 @@  [])] ^D +---+---++|   |   |++===+===+ | 1 | 2 | +---+---+ |   |   |
test/command/3577.md view
@@ -15,7 +15,7 @@     \caption{Subfigure with Subfloat} \end{figure} ^D-<figure>+<figure data-latex-placement="ht"> <figure> <img src="img1.jpg" /> <figcaption>Caption 1</figcaption>@@ -34,7 +34,7 @@     \caption{Caption 3} \end{figure} ^D-<figure>+<figure data-latex-placement="ht"> <img src="img1.jpg" /> <figcaption>Caption 3</figcaption> </figure>
test/command/3596.md view
@@ -6,9 +6,9 @@ <li>baz</li> </ul> ^D--   foo--   bar--   baz+- foo+- bar+- baz ```  ```@@ -19,10 +19,10 @@ <li>baz</li> </ul> ^D--   foo--   bar-    -   subbar--   baz+- foo+- bar+  - subbar+- baz ```  @@ -34,9 +34,9 @@ <li>baz</li> </ul> ^D--   foo--   [bar]{#id}--   baz+- foo+- [bar]{#id}+- baz ```  @@ -48,12 +48,12 @@ <li><p>baz</p></li> </ul> ^D--   foo+- foo --   ::: {#id}-    bar-    :::+- ::: {#id}+  bar+  ::: --   baz+- baz  ```
test/command/3667.md view
@@ -4,7 +4,7 @@ ^D <table> <tbody>-<tr class="odd">+<tr> <td><a href="http://example.com/">link text</a></td> </tr> </tbody>
test/command/3734.md view
@@ -4,9 +4,9 @@ |--------------|-------|--------------------------------------------------------------------------| | aaaaaaaaaaaa |       | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc | ^D-| aaaaaaaaaaaa | bbbbb | ccccccccccc                                                              |+| aaaaaaaaaaaa | bbbbb | ccccccccccc | |------------|-------|------------------------------------------------------|-| aaaaaaaaaaaa |       | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc |+| aaaaaaaaaaaa |  | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc | ```  ```@@ -15,9 +15,9 @@ |--------------|-------|--------------------------------------------------------------------------| | aaaaaaaaaaaa |       | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc | ^D-| aaaaaaaaaaaa | bbbbb | ccccccccccc                                                              |+| aaaaaaaaaaaa | bbbbb | ccccccccccc | |------------|-------|------------------------------------------------------|-| aaaaaaaaaaaa |       | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc |+| aaaaaaaaaaaa |  | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc | ```  ```@@ -26,7 +26,7 @@ |--------------|-------|--------------------------------------------------------------------------| | aaaaaaaaaaaa |       | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc | ^D-| aaaaaaaaaaaa | bbbbb | ccccccccccc                                                              |-|--------------|-------|--------------------------------------------------------------------------|-| aaaaaaaaaaaa |       | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc |+| aaaaaaaaaaaa | bbbbb | ccccccccccc |+|----|----|----|+| aaaaaaaaaaaa |  | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc | ```
test/command/3958.md view
@@ -9,7 +9,7 @@ % pandoc -f latex -t native \texttt{``hi''} ^D-[ Para [ Code ( "" , [] , [] ) "\8220hi\8221" ] ]+[ Para [ Code ( "" , [] , [] ) "\8216\8216hi\8217\8217" ] ] ```  ```
test/command/4016.md view
@@ -14,11 +14,11 @@ </div> ^D \begin{frame}{Level 2 blocks}-\phantomsection\label{level-2-blocks}+\protect\phantomsection\label{level-2-blocks} \begin{columns}[T]-\begin{column}{0.4\textwidth}+\begin{column}{0.4\linewidth} \begin{block}{Block one}-\phantomsection\label{block-one}+\protect\phantomsection\label{block-one} \begin{itemize} \tightlist \item@@ -27,9 +27,9 @@ \end{block} \end{column} -\begin{column}{0.6\textwidth}+\begin{column}{0.6\linewidth} \begin{block}{Block two}-\phantomsection\label{block-two}+\protect\phantomsection\label{block-two} \begin{itemize} \tightlist \item
test/command/4164.md view
@@ -8,11 +8,9 @@  Here is inline html: -<div>-+::: {} `<balise>`{=html} bla bla--</div>+:::  ``` 
test/command/4186.md view
@@ -5,7 +5,7 @@ #+end_example ^D [ CodeBlock-    ( "" , [ "example" ] , [] )+    ( "" , [] , [] )     "    This should retain the four leading spaces\n" ] ```@@ -40,13 +40,13 @@ ^D <ul> <li><p>depth 1</p>-<pre id="bob" class="example"><code>    Vertical alignment is four spaces beyond the appearance of the word &quot;depth&quot;.+<pre id="bob"><code>    Vertical alignment is four spaces beyond the appearance of the word &quot;depth&quot;. </code></pre> <ul> <li><p>depth 2</p>-<pre class="example"><code>Vertically aligned with the second appearance of the word &quot;depth&quot;.+<pre><code>Vertically aligned with the second appearance of the word &quot;depth&quot;. </code></pre>-<pre class="example"><code>    Vertical alignment is four spaces beyond the second+<pre><code>    Vertical alignment is four spaces beyond the second     appearance of the word &quot;depth&quot;.     The &quot;begin&quot; portion is a component of     this deeper list element, so that guarantees@@ -55,7 +55,7 @@ </code></pre> <p>Still inside the inner list element</p></li> </ul>-<pre id="carrie" class="example"><code>This belongs to the outer list element, and is aligned accordingly, since the NAME attribute is not indented deeply enough. It is not enough for the BEGIN alone to be aligned deeply if the block is meant to have a NAME.+<pre id="carrie"><code>This belongs to the outer list element, and is aligned accordingly, since the NAME attribute is not indented deeply enough. It is not enough for the BEGIN alone to be aligned deeply if the block is meant to have a NAME. </code></pre> <p>Still in the shallower list element since the preceding example block forced the deeper list element to terminate.</p></li>
test/command/4235.md view
@@ -4,7 +4,7 @@ ^D <p>This.<a href="#foofn1" class="footnote-ref" id="foofnref1" role="doc-noteref"><sup>1</sup></a></p>-<section id="footnotes" class="footnotes footnotes-end-of-document"+<section id="foofootnotes" class="footnotes footnotes-end-of-document" role="doc-endnotes"> <hr /> <ol>
+ test/command/4470.md view
@@ -0,0 +1,27 @@+```+% pandoc -r latex -w plain+\newcommand{\foo}{123}\renewcommand\foo{456}\foo+^D+456+```++```+% pandoc -r latex -w plain+\newcommand\foo{123}\renewcommand\foo{456}\foo+^D+456+```++```+% pandoc -r latex -w plain+\newcommand{\foo}{123}\renewcommand{\foo}{456}\foo+^D+456+```++```+% pandoc -r latex -w plain+\newcommand\foo{123}\renewcommand{\foo}{456}\foo+^D+456+```
test/command/4545.md view
@@ -8,7 +8,7 @@ ^D Test 1 -{empty}[my text]+++[++my text++]++  Test 2 ```
test/command/4550.md view
@@ -3,5 +3,5 @@ A ‘simple’ example ^D .LP-A \[oq]simple\[cq] example+A \(oqsimple\(cq example ```
test/command/4564.md view
@@ -1,65 +1,58 @@ ``` % pandoc -f native -t rst --list-tables-[BlockQuote- [Table ("",[],[]) (Caption Nothing-  [])-  [(AlignDefault,ColWidth 0.1527777777777778)-  ,(AlignDefault,ColWidth 0.1388888888888889)-  ,(AlignDefault,ColWidth 0.16666666666666666)-  ,(AlignDefault,ColWidth 0.375)]-  (TableHead ("",[],[])+[Table ("",[],[]) (Caption Nothing+ [Plain [Str "Here",Space,Str "is",Space,Str "a",Space,Str "caption."]])+ [(AlignDefault,ColWidth 0.1527777777777778)+ ,(AlignDefault,ColWidth 0.1388888888888889)+ ,(AlignDefault,ColWidth 0.16666666666666666)+ ,(AlignDefault,ColWidth 0.375)]+ (TableHead ("",[],[])+ [Row ("",[],[])+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+   [Plain [Str "Centered",SoftBreak,Str "Header"]]+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+   [Plain [Str "Left",SoftBreak,Str "Aligned"]]+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+   [Plain [Str "Right",SoftBreak,Str "Aligned"]]+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+   [Plain [Str "Default",Space,Str "aligned"]]]])+ [(TableBody ("",[],[]) (RowHeadColumns 0)+  []   [Row ("",[],[])    [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "Centered",SoftBreak,Str "Header"]]+    [Plain [Str "First"]]    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "Left",SoftBreak,Str "Aligned"]]+    [Plain []]    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "Right",SoftBreak,Str "Aligned"]]+    [Plain [Str "12.0"]]    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "Default",Space,Str "aligned"]]]])-  [(TableBody ("",[],[]) (RowHeadColumns 0)-   []-   [Row ("",[],[])-    [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-     [Plain [Str "First"]]-    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-     [Plain [Str "row"]]-    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-     [Plain [Str "12.0"]]-    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-     [Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",SoftBreak,Str "spans",Space,Str "multiple",Space,Str "lines."]]]-   ,Row ("",[],[])-    [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-     [Plain [Str "Second"]]-    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-     [Plain [Str "row"]]-    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-     [Plain [Str "5.0"]]-    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-     [Plain [Str "Here\8217s",Space,Str "another",Space,Str "one.",Space,Str "Note",SoftBreak,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",SoftBreak,Str "rows."]]]])]-  (TableFoot ("",[],[])-  [])]]+    [Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",SoftBreak,Str "spans",Space,Str "multiple",Space,Str "lines."]]]+  ,Row ("",[],[])+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+    [Plain [Str "Second"]]+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+    [Plain [Str "row"]]+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+    [Plain [Str "5.0"]]+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+    [Plain [Str "Here\8217s",Space,Str "another",Space,Str "one.",Space,Str "Note",SoftBreak,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",SoftBreak,Str "rows."]]]])]+ (TableFoot ("",[],[])+ [])] ^D-   .. list-table::-      :widths: 11 10 12 27-      :header-rows: 1--      - --         - Centered Header-         - Left Aligned-         - Right Aligned-         - Default aligned-      - --         - First-         - row-         - 12.0-         - Example of a row that spans multiple lines.-      - +.. list-table:: Here is a caption.+   :widths: 11 10 12 27+   :header-rows: 1 -         - Second-         - row-         - 5.0-         - Here’s another one. Note the blank line between rows.+   * - Centered Header+     - Left Aligned+     - Right Aligned+     - Default aligned+   * - First+     - +     - 12.0+     - Example of a row that spans multiple lines.+   * - Second+     - row+     - 5.0+     - Here’s another one. Note the blank line between rows. ```
test/command/4690.md view
@@ -12,13 +12,13 @@ :::: ^D \begin{frame}{title}-\phantomsection\label{title}+\protect\phantomsection\label{title} \begin{columns}[T]-\begin{column}{0.08\textwidth}+\begin{column}{0.08\linewidth} content \end{column} -\begin{column}{0.84\textwidth}+\begin{column}{0.84\linewidth} content2 \end{column} \end{columns}
test/command/4742.md view
@@ -7,7 +7,7 @@ ^D [ Header     1-    ( "non-ascii--raksmorgas" , [] , [] )+    ( "non-ascii-warning-raksmorgas" , [] , [] )     [ Str "non"     , Space     , Str "ascii"@@ -29,7 +29,7 @@ ^D [ Header     1-    ( "non-ascii-\65039-r\228ksm\246rg\229s" , [] , [] )+    ( "non-ascii-warning-r\228ksm\246rg\229s" , [] , [] )     [ Str "non"     , Space     , Str "ascii"@@ -49,7 +49,7 @@ ^D [ Header     1-    ( "non-ascii-\65039-r\228ksm\246rg\229s" , [] , [] )+    ( "non-ascii-warning-r\228ksm\246rg\229s" , [] , [] )     [ Str "non"     , Space     , Str "ascii"
+ test/command/4746.md view
@@ -0,0 +1,56 @@+```+% pandoc -f latex -t native+\begin{tabular}{c c}+  \begin{tabular}{c} a \\ \end{tabular}+  &+  \\+\end{tabular}+^D+[ Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignCenter , ColWidthDefault )+    , ( AlignCenter , ColWidthDefault )+    ]+    (TableHead ( "" , [] , [] ) [])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Table+                    ( "" , [] , [] )+                    (Caption Nothing [])+                    [ ( AlignCenter , ColWidthDefault ) ]+                    (TableHead ( "" , [] , [] ) [])+                    [ TableBody+                        ( "" , [] , [] )+                        (RowHeadColumns 0)+                        []+                        [ Row+                            ( "" , [] , [] )+                            [ Cell+                                ( "" , [] , [] )+                                AlignDefault+                                (RowSpan 1)+                                (ColSpan 1)+                                [ Plain [ Str "a" ] ]+                            ]+                        ]+                    ]+                    (TableFoot ( "" , [] , [] ) [])+                ]+            , Cell+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+]+```
test/command/4805-beamer-columns-alignment.md view
@@ -19,18 +19,18 @@ ^D \begin{frame} \begin{columns}[T]-\begin{column}[c]{0.48\textwidth}+\begin{column}[c]{0.48\linewidth} \end{column} -\begin{column}[b]{0.48\textwidth}+\begin{column}[b]{0.48\linewidth} \end{column} \end{columns}  \begin{columns}[b,onlytextwidth]-\begin{column}[T]{0.48\textwidth}+\begin{column}[T]{0.48\linewidth} \end{column} -\begin{column}[t]{0.48\textwidth}+\begin{column}[t]{0.48\linewidth} \end{column} \end{columns} 
test/command/5071.md view
@@ -49,8 +49,8 @@ ^D <h2 data-number="2.3" id="first-section"><span class="header-section-number">2.3</span> First section</h2>-<h3 data-number="2.3.3" id="subhead"><span-class="header-section-number">2.3.3</span> Subhead</h3>+<h3 data-number="2.3.1" id="subhead"><span+class="header-section-number">2.3.1</span> Subhead</h3>  ``` @@ -62,7 +62,7 @@ ^D <h2 data-number="0.3" id="first-section"><span class="header-section-number">0.3</span> First section</h2>-<h3 data-number="0.3.3" id="subhead"><span-class="header-section-number">0.3.3</span> Subhead</h3>+<h3 data-number="0.3.1" id="subhead"><span+class="header-section-number">0.3.1</span> Subhead</h3>  ```
+ test/command/5081.md view
@@ -0,0 +1,8 @@+```+% pandoc -f rst+Go to `g`_ `g <www.example.com>`_.+^D+<p>Go to <a href="www.example.com">g</a> <a+href="www.example.com">g</a>.</p>++```
+ test/command/5116.md view
@@ -0,0 +1,107 @@+```+% pandoc -t latex+![This is a figure.](img.jpg)++  Right     Left     Center     Default+-------     ------ ----------   -------+     12     12        12            12+    123     123       123          123+      1     1          1             1++  :  Demonstration of simple table syntax.+^D+\begin{figure}+\centering+\pandocbounded{\includegraphics[keepaspectratio,alt={This is a figure.}]{img.jpg}}+\caption{This is a figure.}+\end{figure}++\begin{longtable}[]{@{}rlcl@{}}+\caption{Demonstration of simple table syntax.}\tabularnewline+\toprule\noalign{}+Right & Left & Center & Default \\+\midrule\noalign{}+\endfirsthead+\toprule\noalign{}+Right & Left & Center & Default \\+\midrule\noalign{}+\endhead+\bottomrule\noalign{}+\endlastfoot+12 & 12 & 12 & 12 \\+123 & 123 & 123 & 123 \\+1 & 1 & 1 & 1 \\+\end{longtable}++```++```+% pandoc -t latex --figure-caption-position=above --table-caption-position=above+![This is a figure.](img.jpg)++  Right     Left     Center     Default+-------     ------ ----------   -------+     12     12        12            12+    123     123       123          123+      1     1          1             1++  :  Demonstration of simple table syntax.+^D+\begin{figure}+\centering+\caption{This is a figure.}+\pandocbounded{\includegraphics[keepaspectratio,alt={This is a figure.}]{img.jpg}}+\end{figure}++\begin{longtable}[]{@{}rlcl@{}}+\caption{Demonstration of simple table syntax.}\tabularnewline+\toprule\noalign{}+Right & Left & Center & Default \\+\midrule\noalign{}+\endfirsthead+\toprule\noalign{}+Right & Left & Center & Default \\+\midrule\noalign{}+\endhead+\bottomrule\noalign{}+\endlastfoot+12 & 12 & 12 & 12 \\+123 & 123 & 123 & 123 \\+1 & 1 & 1 & 1 \\+\end{longtable}++```++```+% pandoc -t latex --figure-caption-position=below --table-caption-position=below+![This is a figure.](img.jpg)++  Right     Left     Center     Default+-------     ------ ----------   -------+     12     12        12            12+    123     123       123          123+      1     1          1             1++  :  Demonstration of simple table syntax.+^D+\begin{figure}+\centering+\pandocbounded{\includegraphics[keepaspectratio,alt={This is a figure.}]{img.jpg}}+\caption{This is a figure.}+\end{figure}++\begin{longtable}[]{@{}rlcl@{}}+\toprule\noalign{}+Right & Left & Center & Default \\+\midrule\noalign{}+\endhead+\bottomrule\noalign{}+\tabularnewline+\caption{Demonstration of simple table syntax.}+\endlastfoot+12 & 12 & 12 & 12 \\+123 & 123 & 123 & 123 \\+1 & 1 & 1 & 1 \\+\end{longtable}++```
test/command/512.md view
@@ -37,7 +37,7 @@  __ link1_ ^D-2> [WARNING] Circular reference 'link1' at line 1 column 15+2> [WARNING] Circular reference 'link1' at line 8 column 1 <p><a href="">click here</a></p> ``` 
test/command/5128.md view
@@ -7,20 +7,20 @@ | =^=     | Centered , the same amount of characters is added to the left and the right.                                                                                                                               | | ===      | Padding. If a numeric value is printed with a sign, then additional characters are added after the sign. Otherwise it behaves like "=>=". This option is only available for numbers (default for numbers). | ^D-+--------+------------------------------------------------------------------+-| Option | Meaning                                                          |-+========+==================================================================+-| ``<``  | Left alignment, additional characters are added to the right     |-|        | (default for string).                                            |-+--------+------------------------------------------------------------------+-| ``>``  | Right alignment, additional characters are added to the left.    |-+--------+------------------------------------------------------------------+-| ``^``  | Centered , the same amount of characters is added to the left    |-|        | and the right.                                                   |-+--------+------------------------------------------------------------------+-| ``=``  | Padding. If a numeric value is printed with a sign, then         |-|        | additional characters are added after the sign. Otherwise it     |-|        | behaves like "``>``". This option is only available for numbers  |-|        | (default for numbers).                                           |-+--------+------------------------------------------------------------------+++--------+-------------------------------------------------------------------++| Option | Meaning                                                           |++========+===================================================================++| ``<``  | Left alignment, additional characters are added to the right      |+|        | (default for string).                                             |++--------+-------------------------------------------------------------------++| ``>``  | Right alignment, additional characters are added to the left.     |++--------+-------------------------------------------------------------------++| ``^``  | Centered , the same amount of characters is added to the left and |+|        | the right.                                                        |++--------+-------------------------------------------------------------------++| ``=``  | Padding. If a numeric value is printed with a sign, then          |+|        | additional characters are added after the sign. Otherwise it      |+|        | behaves like "``>``". This option is only available for numbers   |+|        | (default for numbers).                                            |++--------+-------------------------------------------------------------------+ ```
test/command/5367.md view
@@ -21,7 +21,7 @@ hello\footnote{doc footnote}  \begin{longtable}[]{@{}-  >{\centering\arraybackslash}p{(\columnwidth - 0\tabcolsep) * \real{0.1667}}@{}}+  >{\centering\arraybackslash}p{(\linewidth - 0\tabcolsep) * \real{0.1667}}@{}} \caption[Sample table.]{Sample table.\footnote{caption footnote}}\tabularnewline \toprule\noalign{} \begin{minipage}[b]{\linewidth}\centering
test/command/5407.md view
@@ -6,9 +6,9 @@ hi there!‘ hi there! ^D-hi there?{}``-hi there!{}``-hi there?{}`-hi there!{}`+hi there?{\kern0pt}``+hi there!{\kern0pt}``+hi there?{\kern0pt}`+hi there!{\kern0pt}` hi there! ```
test/command/5420.md view
@@ -1,5 +1,5 @@ ```-% pandoc --listings -t latex+% pandoc --syntax-highlighting=idiomatic -t latex `int a = 1;`{.cpp style=cpp} ^D \passthrough{\lstinline[language={C++}, style=cpp]!int a = 1;!}
test/command/5476.md view
@@ -4,7 +4,7 @@ ^D \begin{figure} \centering-\includegraphics{test/lalune.jpg}+\pandocbounded{\includegraphics[keepaspectratio,alt={moon}]{test/lalune.jpg}} \caption[moon]{moon\footnotemark{}} \end{figure} \footnotetext{the moon}
test/command/5543.md view
@@ -4,5 +4,5 @@ :   description ^D 1\. item-:   description+: description ```
test/command/5619.md view
@@ -37,7 +37,28 @@     [ Plain         [ Image             ( "test" , [] , [ ( "width" , "1in" ) ] )-            [ Str "img1.jpg" ]+            [ Str "The"+            , Space+            , Str "caption."+            , Space+            , Str "Here's"+            , Space+            , Str "what"+            , Space+            , Str "piggybacking"+            , Space+            , Str "on"+            , Space+            , Str "caption"+            , Space+            , Str "would"+            , Space+            , Str "look"+            , Space+            , Str "like"+            , Space+            , Str "{#fig:1}"+            ]             ( "img1.jpg" , "" )         ]     ]
test/command/5705.md view
@@ -6,6 +6,6 @@    [[Plain [Str "Blah"]]]]]] ^D VIII. Blah-      -   Blah+      - Blah ``` 
+ test/command/5793.md view
@@ -0,0 +1,13 @@+```+% pandoc -f html -t djot+You can use <abbr title="Cascading Style Sheets">CSS</abbr>+^D+You can use [CSS]{.abbr title="Cascading Style Sheets"}+```++```+% pandoc -f djot -t html+You can use [CSS]{.abbr title="Cascading Style Sheets"}+^D+<p>You can use <abbr title="Cascading Style Sheets">CSS</abbr></p>+```
test/command/5857.md view
@@ -5,7 +5,7 @@  ,[]  ,[Plain [Str "b"]]]] ^D--   a--   --   b+- a+- +- b ```
test/command/5876.md view
@@ -48,13 +48,13 @@ % pandoc -s -t native --data-dir=command/5876 --metadata-file=does-not-exist.yaml Hello ^D-2> Could not find metadata file does-not-exist.yaml+2> Could not find metadata file 'does-not-exist.yaml' => 98 ``` ``` % pandoc -s -t native --metadata-file=does-not-exist.yaml Hello ^D-2> Could not find metadata file does-not-exist.yaml+2> Could not find metadata file 'does-not-exist.yaml' => 98 ```
test/command/5898.md view
@@ -24,13 +24,13 @@   </body> </html> ^D--  A list of stuff with a table inside+- A list of stuff with a table inside -   ===== ====== =====-   First Second Third-   ===== ====== =====-   First Second Third-   ===== ====== =====+  ===== ====== =====+  First Second Third+  ===== ====== =====+  First Second Third+  ===== ====== ===== --  Another list item+- Another list item ```
test/command/5899.md view
@@ -35,17 +35,17 @@   </body> </html> ^D--  A list of stuff with a table inside+- A list of stuff with a table inside -   +-------+----------------------------------------------------+-------+-   | First | Second                                             | Third |-   +=======+====================================================+=======+-   | First | The big long table cell. The big long table cell.  | Third |-   |       | The big long table cell. The big long table cell.  |       |-   |       | The big long table cell. The big long table cell.  |       |-   |       | The big long table cell. The big long table cell.  |       |-   |       | The big long table cell. The big long table cell.  |       |-   +-------+----------------------------------------------------+-------++  +-------+------------------------------------------------------+-------++  | First | Second                                               | Third |+  +=======+======================================================+=======++  | First | The big long table cell. The big long table cell.    | Third |+  |       | The big long table cell. The big long table cell.    |       |+  |       | The big long table cell. The big long table cell.    |       |+  |       | The big long table cell. The big long table cell.    |       |+  |       | The big long table cell. The big long table cell.    |       |+  +-------+------------------------------------------------------+-------+ --  Another list item+- Another list item  ```
test/command/5967.md view
@@ -4,8 +4,8 @@ ## Two #### Four ^D--   One-    -   Two+- One+  - Two  One 
+ test/command/6021.md view
@@ -0,0 +1,54 @@+```+% pandoc -t native+Oxide      石英+-------  ------+SiO2        100+^D+[ Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignLeft , ColWidthDefault )+    , ( AlignRight , ColWidthDefault )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Oxide" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "\30707\33521" ] ]+           ]+       ])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "SiO2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "100" ] ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+]+```
test/command/6030.md view
@@ -83,11 +83,11 @@ \end{frame}  \begin{frame}{Three}-\phantomsection\label{three}+\protect\phantomsection\label{three} Three  \begin{block}{Four}-\phantomsection\label{four}+\protect\phantomsection\label{four} Four \end{block} \end{frame}
test/command/6033.md view
@@ -38,7 +38,7 @@  \begin{frame}{One-A} \begin{columns}[T]-\begin{column}{0.48\textwidth}+\begin{column}{0.48\linewidth} \begin{itemize} \tightlist \item@@ -46,7 +46,7 @@ \end{itemize} \end{column} -\begin{column}{0.48\textwidth}+\begin{column}{0.48\linewidth} \begin{itemize} \tightlist \item
test/command/6034.md view
@@ -7,8 +7,13 @@   \end{overpic} \end{figure*} ^D-[ RawBlock-    (Format "latex")-    "\\begin{figure*}\n  \\centering\n  \\begin{overpic}{test_pic}\n    \\put (70,80) {Caption}\n  \\end{overpic}\n\\end{figure*}"+[ Figure+    ( "" , [] , [] )+    (Caption Nothing [])+    [ RawBlock (Format "latex") "\\centering"+    , RawBlock+        (Format "latex")+        "\\begin{overpic}{test_pic}\n    \\put (70,80) {Caption}\n  \\end{overpic}"+    ] ] ```
test/command/6107.md view
@@ -16,11 +16,11 @@ \section{A circus!}\label{a-circus}  \begin{frame}{Another silly title}-\phantomsection\label{another-silly-title}+\protect\phantomsection\label{another-silly-title} Not much to do about nothing. \end{frame}  \begin{frame}[standout]{Epilogue}-\phantomsection\label{epilogue}+\protect\phantomsection\label{epilogue} \end{frame} ```
test/command/6137.md view
@@ -38,79 +38,76 @@     , Space     , Str "work."     ]-, Div+, Table     ( "tbl:label" , [] , [] )-    [ Table+    (Caption+       Nothing+       [ Plain+           [ Str "This"+           , Space+           , Str "caption"+           , Space+           , Str "has"+           , Space+           , Str "no"+           , Space+           , Str "number."+           ]+       ])+    [ ( AlignLeft , ColWidthDefault )+    , ( AlignCenter , ColWidthDefault )+    , ( AlignRight , ColWidthDefault )+    ]+    (TableHead ( "" , [] , [] ) [])+    [ TableBody         ( "" , [] , [] )-        (Caption-           Nothing-           [ Plain-               [ Str "This"-               , Space-               , Str "caption"-               , Space-               , Str "has"-               , Space-               , Str "no"-               , Space-               , Str "number."-               ]-           ])-        [ ( AlignLeft , ColWidthDefault )-        , ( AlignCenter , ColWidthDefault )-        , ( AlignRight , ColWidthDefault )-        ]-        (TableHead ( "" , [] , [] ) [])-        [ TableBody+        (RowHeadColumns 0)+        []+        [ Row             ( "" , [] , [] )-            (RowHeadColumns 0)-            []-            [ Row+            [ Cell                 ( "" , [] , [] )-                [ Cell-                    ( "" , [] , [] )-                    AlignDefault-                    (RowSpan 1)-                    (ColSpan 1)-                    [ Plain [ Str "\8212\8212\8211" ] ]-                , Cell-                    ( "" , [] , [] )-                    AlignDefault-                    (RowSpan 1)-                    (ColSpan 1)-                    [ Plain [ Str "\8212\8212\8211" ] ]-                , Cell-                    ( "" , [] , [] )-                    AlignDefault-                    (RowSpan 1)-                    (ColSpan 1)-                    [ Plain [ Str "\8212\8212\8211" ] ]-                ]-            , Row+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "\8212\8212\8211" ] ]+            , Cell                 ( "" , [] , [] )-                [ Cell-                    ( "" , [] , [] )-                    AlignDefault-                    (RowSpan 1)-                    (ColSpan 1)-                    [ Plain [ Str "\8212\8212\8211" ] ]-                , Cell-                    ( "" , [] , [] )-                    AlignDefault-                    (RowSpan 1)-                    (ColSpan 1)-                    [ Plain [ Str "\8212\8212\8211" ] ]-                , Cell-                    ( "" , [] , [] )-                    AlignDefault-                    (RowSpan 1)-                    (ColSpan 1)-                    [ Plain [ Str "\8212\8212\8211" ] ]-                ]+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "\8212\8212\8211" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "\8212\8212\8211" ] ]             ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "\8212\8212\8211" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "\8212\8212\8211" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "\8212\8212\8211" ] ]+            ]         ]-        (TableFoot ( "" , [] , [] ) [])     ]+    (TableFoot ( "" , [] , [] ) []) , Para     [ Str "This"     , Space
+ test/command/6285.md view
@@ -0,0 +1,6 @@+```+% pandoc -t docx -f native -o - | pandoc -f docx -t native+[ HorizontalRule ]+^D+[ HorizontalRule ]+```
test/command/6360.md view
@@ -2,5 +2,5 @@ % pandoc -f native -t latex --wrap=none [Link ("test2",[],[]) [Str "link",Space,Str "to",Space,Str "text",Space,Str "test1"] ("#test1","")] ^D-\phantomsection\label{test2}\hyperref[test1]{link to text test1}+\protect\phantomsection\label{test2}\hyperref[test1]{link to text test1} ```
test/command/6384.md view
@@ -1,16 +1,12 @@ ``` % pandoc --wrap=preserve --file-scope command/file1.txt command/file2.txt ^D-<div id="command__file1.txt"> <h1 id="command__file1.txt__zed">Zed</h1> <p><a href="bar">foo</a> and <a href="#command__file1.txt__zed">Zed</a> and <a href="#command__file2.txt__zed">other Zed</a> and <a href="#command__file2.txt">other file</a> and <a href="c.md#zed">foreign Zed</a></p>-</div>-<div id="command__file2.txt"> <h2 id="command__file2.txt__zed">Zed</h2> <p><a href="baz">foo</a></p>-</div> ```
+ test/command/6424.md view
@@ -0,0 +1,6 @@+```+% pandoc -t asciidoc+test^[this is a note\]. and more]+^D+testfootnote:[this is a note++]++. and more]+```
test/command/6441.md view
@@ -7,13 +7,13 @@ ^D <table class="table-dark"> <thead>-<tr class="header">+<tr> <th>h1</th> <th>h2</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>c1</td> <td>c2</td> </tr>
test/command/6481.md view
@@ -18,7 +18,7 @@ <col style="width: 69%" /> </colgroup> <thead>-<tr class="header">+<tr> <th style="text-align: center;">Col 1</th> <th style="text-align: center;">Col 2</th> <th style="text-align: center;">Col 3</th>@@ -26,7 +26,7 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td style="text-align: center;">High</td> <td style="text-align: center;">Med</td> <td style="text-align: center;">Med</td>
test/command/6549.md view
@@ -8,13 +8,13 @@ <table> <caption>Test table</caption> <thead>-<tr class="header">+<tr> <th>Column1</th> <th>Column2</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>Data1</td> <td><ul> <li>data1</li>
+ test/command/6588.md view
@@ -0,0 +1,10 @@+```+% pandoc -f rst+I recommend you try |Python|_.++.. |Python| replace:: Python, *the* best language around+.. _Python: http://www.python.org/+^D+<p>I recommend you try <a href="http://www.python.org/"><span>Python,+<em>the</em> best language around</span></a>.</p>+```
test/command/6719.md view
@@ -4,7 +4,7 @@ <emphasis>emphasized </emphasis>text </para> ^D-[ Para [ Emph [ Str "emphasized" ] , Space , Str "text" ] ]+[ Para [ Emph [ Str "emphasized" , Space ] , Str "text" ] ] ```  ```@@ -13,6 +13,6 @@ <italic> hi  </italic>there </p> ^D-[ Para [ Emph [ Str "hi" ] , Space , Str "there" ] ]+[ Para [ Emph [ Space , Str "hi" , Space ] , Str "there" ] ] ``` 
test/command/6783.md view
@@ -20,7 +20,7 @@ This is a test(Jupyter 2018).  Jupyter, Project. 2018. “Binder 2.0 - Reproducible, Interactive,-Sharable Environments for Science at Scale.” In Proceedings of the 17th+Sharable Environments for Science at Scale.” Proceedings of the 17th Python in Science Conference. ``` 
+ test/command/6821.md view
@@ -0,0 +1,80 @@+```+% pandoc -f native -t latex+[ Para [ Code ( "" , [ "python" ] , [] ) "x = 5" ]+, Figure+    ( "" , [] , [] )+    (Caption+       Nothing+       [ Plain+           [ Str "This"+           , Space+           , Str "is"+           , Space+           , Str "a"+           , Space+           , Str "test"+           , Space+           , Code ( "" , [ "python" ] , [] ) "x = 5"+           ]+       ])+    [ Plain+        [ Image+            ( "" , [] , [] )+            [ Str "This"+            , Space+            , Str "is"+            , Space+            , Str "a"+            , Space+            , Str "test"+            , Space+            , Code ( "" , [ "python" ] , [] ) "x = 5"+            ]+            ( "test.png" , "" )+        ]+    ]+, Table+    ( "" , [] , [] )+    (Caption+       Nothing+       [ Plain [ Code ( "" , [ "cpp" ] , [] ) "caption" ] ])+    [ ( AlignDefault , ColWidthDefault ) ]+    (TableHead ( "" , [] , [] ) [])+    [ TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [] ]+    (TableFoot+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "A" ] ]+           ]+       ])+, Para [ Code ( "" , [ "cpp" ] , [] ) "caption" ]+]+^D+\VERB|\NormalTok{x }\OperatorTok{=} \DecValTok{5}|++\begin{figure}+\centering+\pandocbounded{\includegraphics[keepaspectratio,alt={This is a test x = 5}]{test.png}}+\caption{This is a test+\protect\VERB|\NormalTok{x }\OperatorTok{=} \DecValTok{5}|}+\end{figure}++\begin{longtable}[]{@{}l@{}}+\caption{\protect\VERB|\NormalTok{caption}|}\tabularnewline+\toprule\noalign{}+\endfirsthead+\endhead+\midrule\noalign{}+A \\+\bottomrule\noalign{}+\endlastfoot+\end{longtable}++\VERB|\NormalTok{caption}|+```
test/command/6858.md view
@@ -27,13 +27,13 @@  \*FvwmAnimate: Color color -:   Tells **FvwmAnimate** what color to draw with. The color is-    \"XOR\'ed\" (exclusive ORed) onto the background.+: Tells **FvwmAnimate** what color to draw with. The color is+  \"XOR\'ed\" (exclusive ORed) onto the background.  \*FvwmAnimate: Pixmap pixmap -:   Tells **FvwmAnimate** to use **pixmap** to draw with. This can be-    useful if **\*FvwmAnimate: Color** gives poor results.+: Tells **FvwmAnimate** to use **pixmap** to draw with. This can be+  useful if **\*FvwmAnimate: Color** gives poor results. ```  ```@@ -46,7 +46,7 @@  there ^D--   hi+- hi --   there+- there ```
test/command/6890.md view
@@ -38,13 +38,11 @@             , citationHash = 0             }         ]-        [ Str "Fr\252chtel,"-        , Space-        , Str "Budde,"+        [ Str "Fr\252chtel"         , Space-        , Str "and"+        , Str "et"         , Space-        , Str "Cyprian"+        , Str "al."         , Space         , Str "(2013)"         ]@@ -65,13 +63,11 @@                     , citationHash = 0                     }                 ]-                [ Str "Fr\252chtel,"-                , Space-                , Str "Budde,"+                [ Str "Fr\252chtel"                 , Space-                , Str "and"+                , Str "et"                 , Space-                , Str "Cyprian"+                , Str "al."                 , Space                 , Str "(2013)"                 ]@@ -81,7 +77,7 @@ , Div     ( "refs"     , [ "references" , "csl-bib-body" , "hanging-indent" ]-    , [ ( "entry-spacing" , "0" ) ]+    , []     )     [ Div         ( "ref-fruchtel-sozialer-2013a" , [ "csl-entry" ] , [] )@@ -126,10 +122,6 @@             , Str "3rd"             , Space             , Str "ed."-            , Space-            , Str "Wiesbaden,"-            , Space-            , Str "Germany:"             , Space             , Str "Springer"             , Space
test/command/6925.md view
@@ -23,12 +23,12 @@ ::: thm **Theorem 1**. *a* -![image](1.png)+![](1.png) :::  ::: thm2 **Theorem 1**. a -![image](1.png)+![](1.png) ::: ```
test/command/6951.md view
@@ -14,5 +14,5 @@  Crazy. n.d. -Doe, John. 2005. First Book. Cambridge: Cambridge University Press.+Doe, John. 2005. First Book. Cambridge University Press. ```
+ test/command/6959.md view
@@ -0,0 +1,12 @@+```+% pandoc -t docx -o - | pandoc -f docx -t markdown --track-changes=all+[This is the comment]{.comment-start id="1" author="Mike"+date="2020-12-17T16:53:00Z"} [Here is my reply]{.comment-start id="2"+author="Mike" date="2020-12-17T17:39:00Z"} This is the content being+commented on [[]{.comment-end id="2"}]{.comment-end id="1"}+^D+[This is the comment]{.comment-start id="1" author="Mike"+date="2020-12-17T16:53:00Z"} [Here is my reply]{.comment-start id="2"+author="Mike" date="2020-12-17T17:39:00Z"} This is the content being+commented on [[]{.comment-end id="2"}]{.comment-end id="1"}+```
+ test/command/6992.md view
@@ -0,0 +1,76 @@+```+% pandoc -f mediawiki -t native+{| class="wikitable"+!colspan=4 | template request+|-+| mode || No || String || MUST be "template" or omitted+|}+^D+[ Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 4)+               [ Para [ Str "template" , Space , Str "request" ] ]+           ]+       ])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Para [ Str "mode" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Para [ Str "No" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Para [ Str "String" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Para+                    [ Str "MUST"+                    , Space+                    , Str "be"+                    , Space+                    , Str "\"template\""+                    , Space+                    , Str "or"+                    , Space+                    , Str "omitted"+                    ]+                ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+]++```
test/command/7064.md view
@@ -15,14 +15,14 @@ <col style="width: 70%" /> </colgroup> <thead>-<tr class="header">+<tr> <th>Version</th> <th>Date</th> <th>Description</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>0.1.0</td> <td>18/02/2013</td> <td>Initial Release</td>
test/command/7112.md view
@@ -6,7 +6,7 @@ ^D <table> <tbody>-<tr class="odd">+<tr> <td>setting</td> <td><code>echo PATH="path"</code></td> </tr>
+ test/command/7172.md view
@@ -0,0 +1,17 @@+```+% pandoc -t markdown+- one+  - two+^D+- one+  - two+```++```+% pandoc -t markdown+four_space_rule+- one+  - two+^D+-   one+    -   two+```
test/command/7181.md view
@@ -4,7 +4,7 @@ ^D \begin{figure} \centering-\includegraphics[page=13,trim=1cm,clip,width=4cm]{slides.pdf}+\pandocbounded{\includegraphics[keepaspectratio,page=13,trim=1cm,clip,width=4cm,alt={Global frog population.}]{slides.pdf}} \caption{Global frog population.} \end{figure} 
+ test/command/7201.md view
@@ -0,0 +1,47 @@+```+% pandoc -t revealjs --slide-level=1+# Overview++:::::::::::::: {.columns}+::: {.column width="40%"}++Left column++:::+::: {.column width="60%"}++* First list+    * subitem++. . .++* Second list+    * subitem+:::+::::::::::::::+^D+<section id="overview" class="slide level1">+<h1>Overview</h1>+<div class="columns">+<div class="column" style="width:40%;">+<p>Left column</p>+</div><div class="column" style="width:60%;">+<ul>+<li>First list+<ul>+<li>subitem</li>+</ul></li>+</ul>+<div class="fragment">+<ul>+<li>Second list+<ul>+<li>subitem</li>+</ul></li>+</ul>+</div>+</div>+</div>+</section>++```
test/command/7214.md view
@@ -13,12 +13,12 @@ <col style="width: 26%" /> </colgroup> <tbody>-<tr class="odd">+<tr> <td>日本語</td> <td>の文字列</td> <td>words in english</td> </tr>-<tr class="even">+<tr> <td>abc defghij</td> <td>def</td> <td>xyz</td>
+ test/command/7219.md view
@@ -0,0 +1,25 @@+```+% pandoc --citeproc -t plain+---+references:+- author:+  - family: Reese+    given: Trevor R.+  collection-title: 3rd series+  container-title: William and Mary Quarterly+  id: reese+  issued: 1958+  language: en-US+  page: 168-190+  title: Georgia in Anglo-Spanish diplomacy, 1736-1739+  type: article-journal+  volume: 15+...+and also in -@reese+^D+and also in (1958)++Reese, Trevor R. 1958. “Georgia in Anglo-Spanish Diplomacy, 1736-1739.”+William and Mary Quarterly, 3rd series, vol. 15: 168–90.++```
test/command/7272.md view
@@ -14,8 +14,9 @@   </tbody> </table> ^D+{\def\LTcaptype{none} % do not increment counter \begin{longtable}[]{@{}-  >{\raggedright\arraybackslash}p{(\columnwidth - 0\tabcolsep) * \real{1.0000}}@{}}+  >{\raggedright\arraybackslash}p{(\linewidth - 0\tabcolsep) * \real{1.0000}}@{}} \toprule\noalign{} \endhead \bottomrule\noalign{}@@ -25,4 +26,5 @@ text2 }\strut \end{minipage} \\ \end{longtable}+} ```
test/command/7278.md view
@@ -17,21 +17,21 @@ text in block ^D \begin{frame}{Slide}-\phantomsection\label{slide}+\protect\phantomsection\label{slide} Some blocks:  \begin{exampleblock}{example block title}-\phantomsection\label{example-block-title}+\protect\phantomsection\label{example-block-title} text in block \end{exampleblock}  \begin{alertblock}{alert block title}-\phantomsection\label{alert-block-title}+\protect\phantomsection\label{alert-block-title} text in block \end{alertblock}  \begin{block}{block title}-\phantomsection\label{block-title}+\protect\phantomsection\label{block-title} text in block \end{block} \end{frame}
+ test/command/7326.md view
@@ -0,0 +1,1227 @@+Table with row and column spans+```+% pandoc -f html -t asciidoc+<table>+  <colgroup>+    <col style="width: 17%" />+    <col style="width: 16%" />+    <col style="width: 15%" />+    <col style="width: 52%" />+  </colgroup>+  <thead>+    <tr>+      <th>Header 1</th>+      <th>Header 2</th>+      <th>Header 3</th>+      <th>Header 4</th>+    </tr>+  </thead>+  <tbody>+    <tr>+      <td>body row 1</td>+      <td>column 2</td>+      <td>column 3</td>+      <td>column 4</td>+    </tr>+    <tr>+      <td>body row 2</td>+      <td colspan="2">Cells may span columns.</td>+      <td>fff</td>+    </tr>+    <tr>+      <td>body row 3</td>+      <td rowspan="2">Cells may span rows.</td>+      <td rowspan="2">+        <ul>+          <li>Cells</li>+          <li>can</li>+          <li>contain</li>+          <li>blocks.</li>+        </ul>+      </td>+      <td rowspan="2">+        <ul>+          <li>This is a very long line of text</li>+          <li><a href="http://www.python.org/">Python</a></li>+          <li>b</li>+          <li>c</li>+        </ul>+      </td>+    </tr>+    <tr>+      <td>body row 4</td>+    </tr>+  </tbody>+</table>+^D+[width="100%",cols="17%,16%,15%,52%",options="header",]+|===+|Header 1 |Header 2 |Header 3 |Header 4+|body row 1 |column 2 |column 3 |column 4+|body row 2 2+|Cells may span columns. |fff+|body row 3 .2+|Cells may span rows. .2+a|+* Cells+* can+* contain+* blocks.++.2+a|+* This is a very long line of text+* http://www.python.org/[Python]+* b+* c++|body row 4+|===+```++Header and footer.+AsciiDoc only supports 1 header and 1 footer row.+So for multiple header and/or footer rows all the extra rows become part of the table body.+```+% pandoc -f html -t asciidoc+<table>+  <thead>+    <tr>+      <th colspan="2">Inputs</th>+      <th>Output</th>+    </tr>+    <tr>+      <th>A</th>+      <th>B</th>+      <th>A or B</th>+    </tr>+  </thead>+  <tbody>+    <tr>+      <td>False</td>+      <td>False</td>+      <td>False</td>+    </tr>+    <tr>+      <td>True</td>+      <td>False</td>+      <td>True</td>+    </tr>+    <tr>+      <td>False</td>+      <td>True</td>+      <td>True</td>+    </tr>+    <tr>+      <td>True</td>+      <td>True</td>+      <td>True</td>+    </tr>+  </tbody>+  <tfoot>+    <tr>+      <td>A</td>+      <td>B</td>+      <td>A or B</td>+    </tr>+    <tr>+      <td colspan="2">Inputs</td>+      <td>Output</td>+    </tr>+  </tfoot>+</table>+<table>+  <thead>+    <tr>+      <th colspan="2">Header</th>+    </tr>+  </thead>+  <tbody>+    <tr>+      <td>Body 1-1</td>+      <td>Body 2-1</td>+    </tr>+  </tbody>+  <tfoot>+    <tr>+      <td colspan="2">Footer</td>+    </tr>+  </tfoot>+</table>+^D+[cols=",,",options="header,footer",]+|===+2+|Inputs |Output+|A |B |A or B+|False |False |False+|True |False |True+|False |True |True+|True |True |True+|A |B |A or B+2+|Inputs |Output+|===++[cols=",",options="header,footer",]+|===+2+|Header+|Body 1-1 |Body 2-1+2+|Footer+|===+```++Table without header but with footer rows+```+% pandoc -f html -t asciidoc+<table>+  <colgroup>+    <col style="width: 37%" />+    <col style="width: 37%" />+    <col style="width: 26%" />+  </colgroup>+  <tbody>+    <tr>+      <td>False</td>+      <td>False</td>+      <td>False</td>+    </tr>+    <tr>+      <td>True</td>+      <td>False</td>+      <td>True</td>+    </tr>+    <tr>+      <td>False</td>+      <td>True</td>+      <td>True</td>+    </tr>+    <tr>+      <td>True</td>+      <td>True</td>+      <td>True</td>+    </tr>+  </tbody>+  <tfoot>+    <tr>+      <td>A</td>+      <td>B</td>+      <td>A or B</td>+    </tr>+    <tr>+      <td colspan="2">Inputs</td>+      <td>Output</td>+    </tr>+  </tfoot>+</table>+^D+[width="100%",cols="37%,37%,26%",options="footer",]+|===+|False |False |False+|True |False |True+|False |True |True+|True |True |True+|A |B |A or B+2+|Inputs |Output+|===+```++Adjust row span for multiple header rows+```+% pandoc -f html -t asciidoc+<table style="width: 63%">+  <colgroup>+    <col style="width: 30%" />+    <col style="width: 11%" />+    <col style="width: 11%" />+    <col style="width: 11%" />+  </colgroup>+  <thead>+    <tr>+      <th rowspan="2">Location</th>+      <th colspan="3">Temperature 1961-1990 in degree Celsius</th>+    </tr>+    <tr>+      <th>min</th>+      <th>mean</th>+      <th>max</th>+    </tr>+  </thead>+  <tbody>+    <tr>+      <td>Antarctica</td>+      <td>-89.2</td>+      <td>N/A</td>+      <td>19.8</td>+    </tr>+    <tr>+      <td>Earth</td>+      <td>-89.2</td>+      <td>14</td>+      <td>56.7</td>+    </tr>+  </tbody>+</table>+<table style="width: 63%">+  <colgroup>+    <col style="width: 11%" />+    <col style="width: 11%" />+    <col style="width: 11%" />+    <col style="width: 30%" />+  </colgroup>+  <thead>+    <tr>+      <th colspan="3">Temperature 1961-1990 in degree Celsius</th>+      <th rowspan="2">Location</th>+    </tr>+    <tr>+      <th>min</th>+      <th>mean</th>+      <th>max</th>+    </tr>+  </thead>+  <tbody>+    <tr>+      <td>-89.2</td>+      <td>N/A</td>+      <td>19.8</td>+      <td>Antarctica</td>+    </tr>+    <tr>+      <td>-89.2</td>+      <td>14</td>+      <td>56.7</td>+      <td>Earth</td>+    </tr>+  </tbody>+</table>+<table style="width: 65%">+  <colgroup>+    <col style="width: 11%" />+    <col style="width: 11%" />+    <col style="width: 11%" />+    <col style="width: 18%" />+    <col style="width: 14%" />+  </colgroup>+  <thead>+    <tr>+      <th colspan="3">Temperature 1961-1990 in degree Celsius</th>+      <th rowspan="2">Location</th>+      <th>Extra</th>+    </tr>+    <tr>+      <th>min</th>+      <th>mean</th>+      <th>max</th>+      <th>Extra 2</th>+    </tr>+  </thead>+  <tbody>+    <tr>+      <td>-89.2</td>+      <td>N/A</td>+      <td>19.8</td>+      <td>Antarctica</td>+      <td>Extra 3</td>+    </tr>+    <tr>+      <td>-89.2</td>+      <td>14</td>+      <td>56.7</td>+      <td>Earth</td>+      <td>Extra 4</td>+    </tr>+  </tbody>+</table>+<table>+  <thead>+    <tr>+      <th>Header 1-1</th>+      <th colspan="2" rowspan="2">Header 1-2</th>+    </tr>+    <tr>+      <th>Header 2-1</th>+    </tr>+    <tr>+      <th>Header 3-1</th>+      <th>Header 3-2</th>+      <th>Header 3-3</th>+    </tr>+  </thead>+  <tbody>+    <tr>+      <td rowspan="2">Body 1-1</td>+      <td colspan="2">Body 1-2</td>+    </tr>+    <tr>+      <td>Body 2-1</td>+      <td>Body 2-2</td>+    </tr>+  </tbody>+</table>+<table>+  <thead>+    <tr>+      <th rowspan="2">Header 1-1</th>+      <th>Header 1-2</th>+      <th rowspan="2">Header 1-3</th>+    </tr>+    <tr>+      <th>Header 2-1</th>+    </tr>+    <tr>+      <th>Header 3-1</th>+      <th>Header 3-2</th>+      <th>Header 3-3</th>+    </tr>+  </thead>+  <tbody></tbody>+</table>+^D+[width="63%",cols="49%,17%,17%,17%",options="header",]+|===+|Location 3+|Temperature 1961-1990 in degree Celsius+| |min |mean |max+|Antarctica |-89.2 |N/A |19.8+|Earth |-89.2 |14 |56.7+|===++[width="63%",cols="19%,17%,17%,47%",options="header",]+|===+3+|Temperature 1961-1990 in degree Celsius |Location+|min |mean |max |+|-89.2 |N/A |19.8 |Antarctica+|-89.2 |14 |56.7 |Earth+|===++[width="65%",cols="20%,16%,16%,27%,21%",options="header",]+|===+3+|Temperature 1961-1990 in degree Celsius |Location |Extra+|min |mean |max | |Extra 2+|-89.2 |N/A |19.8 |Antarctica |Extra 3+|-89.2 |14 |56.7 |Earth |Extra 4+|===++[cols=",,",options="header",]+|===+|Header 1-1 2+|Header 1-2+|Header 2-1 2+|+|Header 3-1 |Header 3-2 |Header 3-3+.2+|Body 1-1 2+|Body 1-2+|Body 2-1 |Body 2-2+|===++[cols=",,",options="header",]+|===+|Header 1-1 |Header 1-2 |Header 1-3+| |Header 2-1 |+|Header 3-1 |Header 3-2 |Header 3-3+|===+```++Adjust row span in multiple footer rows.+```+% pandoc -f html -t asciidoc+<table>+  <colgroup>+    <col style="width: 40%" />+    <col style="width: 40%" />+    <col style="width: 20%" />+  </colgroup>+  <tbody>+    <tr>+      <td>Body 1-1</td>+      <td>Body 1-2</td>+      <td>Body 1-3</td>+    </tr>+  </tbody>+  <tfoot>+    <tr>+      <td colspan="2">Footer 1-1/2</td>+      <td>Footer 1-3</td>+    </tr>+    <tr>+      <td>Footer 2-1</td>+      <td rowspan="3">Span 3</td>+      <td>Footer 2-3</td>+    </tr>+    <tr>+      <td rowspan="2">Span 2</td>+      <td>Footer 3-3</td>+    </tr>+    <tr>+      <td>Footer 4-3</td>+    </tr>+  </tfoot>+</table>+<table>+  <tbody>+    <tr>+      <td>Body 1-1</td>+      <td>Body 1-2</td>+      <td>Body 1-3</td>+      <td>Body 1-4</td>+      <td>Body 1-5</td>+    </tr>+    <tr>+      <td>Body 2-1</td>+      <td>Body 2-2</td>+      <td>Body 2-3</td>+      <td>Body 2-4</td>+      <td>Body 2-5</td>+    </tr>+  </tbody>+  <tfoot>+    <tr>+      <td colspan="3">Footer 1-1/2/3</td>+      <td>Footer 1-4</td>+      <td>Footer 1-5</td>+    </tr>+    <tr>+      <td>Footer 2-1</td>+      <td rowspan="3">Span 3</td>+      <td>Footer 2-3</td>+      <td colspan="2">Footer 2-4/5</td>+    </tr>+    <tr>+      <td rowspan="2">Span 2</td>+      <td colspan="2">Footer 3-3/4</td>+      <td rowspan="2">Span 2</td>+    </tr>+    <tr>+      <td rowspan="3">Span 3</td>+      <td>Footer 4-4</td>+    </tr>+    <tr>+      <td>Footer 5-1</td>+      <td>Footer 5-2</td>+      <td>Footer 5-4</td>+      <td rowspan="2">Span 2</td>+    </tr>+    <tr>+      <td colspan="2">Footer 6-1/2</td>+      <td>Footer 6-4</td>+    </tr>+  </tfoot>+</table>+<table>+  <tbody>+    <tr>+      <td>Body 1</td>+      <td>Body 2</td>+      <td>Body 3</td>+      <td>Body 4</td>+    </tr>+  </tbody>+  <tfoot>+    <tr>+      <td>Footer 1-1</td>+      <td colspan="2" rowspan="3">Span 3</td>+      <td rowspan="2">Span 2</td>+    </tr>+    <tr>+      <td>Footer 2-1</td>+    </tr>+    <tr>+      <td>Footer 3-1</td>+      <td>Footer 3-4</td>+    </tr>+  </tfoot>+</table>+<table>+  <tbody>+    <tr>+      <td>Body 1-1</td>+      <td>Body 1-2</td>+      <td>Body 1-3</td>+      <td>Body 1-4</td>+    </tr>+  </tbody>+  <tfoot>+    <tr>+      <td colspan="2">Footer 1-1/2</td>+      <td rowspan="6">Span 6</td>+      <td>Footer 1-4</td>+    </tr>+    <tr>+      <td rowspan="3">Span 3</td>+      <td>Footer 2-2</td>+      <td>Footer 2-4</td>+    </tr>+    <tr>+      <td>Footer 3-2</td>+      <td>Footer 3-4</td>+    </tr>+    <tr>+      <td>Footer 4-2</td>+      <td>Footer 4-4</td>+    </tr>+    <tr>+      <td>Footer 5-1</td>+      <td>Footer 5-2</td>+      <td rowspan="2">Span 2</td>+    </tr>+    <tr>+      <td colspan="2">Footer 6-1/2</td>+    </tr>+  </tfoot>+</table>+^D+[width="100%",cols="40%,40%,20%",options="footer",]+|===+|Body 1-1 |Body 1-2 |Body 1-3+2+|Footer 1-1/2 |Footer 1-3+|Footer 2-1 .2+|Span 3 |Footer 2-3+|Span 2 |Footer 3-3+| | |Footer 4-3+|===++[cols=",,,,",options="footer",]+|===+|Body 1-1 |Body 1-2 |Body 1-3 |Body 1-4 |Body 1-5+|Body 2-1 |Body 2-2 |Body 2-3 |Body 2-4 |Body 2-5+3+|Footer 1-1/2/3 |Footer 1-4 |Footer 1-5+|Footer 2-1 .3+|Span 3 |Footer 2-3 2+|Footer 2-4/5+.2+|Span 2 2+|Footer 3-3/4 .2+|Span 2+.2+|Span 3 |Footer 4-4+|Footer 5-1 |Footer 5-2 |Footer 5-4 |Span 2+2+|Footer 6-1/2 | |Footer 6-4 |+|===++[cols=",,,",options="footer",]+|===+|Body 1 |Body 2 |Body 3 |Body 4+|Footer 1-1 2.2+|Span 3 .2+|Span 2+|Footer 2-1+|Footer 3-1 2+| |Footer 3-4+|===++[cols=",,,",options="footer",]+|===+|Body 1-1 |Body 1-2 |Body 1-3 |Body 1-4+2+|Footer 1-1/2 .5+|Span 6 |Footer 1-4+.3+|Span 3 |Footer 2-2 |Footer 2-4+|Footer 3-2 |Footer 3-4+|Footer 4-2 |Footer 4-4+|Footer 5-1 |Footer 5-2 |Span 2+2+|Footer 6-1/2 | |+|===+```++Individual cell alignments+```+% pandoc -f native -t asciidoc+[ Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignLeft+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Left" , Space , Str "Header" ] ]+           , Cell+               ( "" , [] , [] )+               AlignCenter+               (RowSpan 2)+               (ColSpan 2)+               [ Plain [ Str "Center" , Space , Str "Headers" ] ]+           ]+       , Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignRight+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Right" , Space , Str "Header" ] ]+           ]+       , Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignCenter+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Center" , Space , Str "Header" ] ]+           , Cell+               ( "" , [] , [] )+               AlignRight+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Right" , Space , Str "Header" ] ]+           , Cell+               ( "" , [] , [] )+               AlignLeft+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Left" , Space , Str "Header" ] ]+           ]+       ])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignRight+               (RowSpan 2)+               (ColSpan 1)+               [ Plain [ Str "Right" , Space , Str "Body" ] ]+           , Cell+               ( "" , [] , [] )+               AlignLeft+               (RowSpan 1)+               (ColSpan 2)+               [ Plain [ Str "Left" , Space , Str "Body" ] ]+           ]+        , Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignCenter+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Center" , Space , Str "Body" ] ]+           , Cell+               ( "" , [] , [] )+               AlignRight+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Right" , Space , Str "Body" ] ]+           ]+        ]+    ]+    (TableFoot+        ( "" , [] , [] )+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignCenter+                (RowSpan 1)+                (ColSpan 3)+                [ Plain [ Str "Center" , Space , Str "Footer" ] ]+            ]+        , Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignLeft+                 (RowSpan 1)+                 (ColSpan 2)+                 [ Plain [ Str "Left" , Space , Str "Footer" ] ]+             , Cell+                 ( "" , [] , [] )+                 AlignCenter+                 (RowSpan 3)+                 (ColSpan 1)+                 [ Plain [ Str "Center" , Space , Str "Footer" ] ]+             ]+         , Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignRight+                 (RowSpan 1)+                 (ColSpan 2)+                 [ Plain [ Str "Right" , Space , Str "Footer" ] ]+             ]+         , Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignCenter+                 (RowSpan 1)+                 (ColSpan 2)+                 [ Plain [ Str "Center" , Space , Str "Footer" ] ]+             ]+        ])+]+^D+[cols=",,",options="header,footer",]+|===+<|Left Header 2+^|Center Headers+>|Right Header 2+|+^|Center Header >|Right Header <|Left Header+.2+>|Right Body 2+<|Left Body+^|Center Body >|Right Body+3+^|Center Footer+2+<|Left Footer .2+^|Center Footer+2+>|Right Footer+2+^|Center Footer |+|===+```++Adjust row span for empty rows and handle empty rows in general+```+% pandoc -f native -t asciidoc+[ Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 2)+               (ColSpan 1)+               [ Plain [ Str "Header" , Space , Str "1-1" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 3)+               (ColSpan 1)+               [ Plain [ Str "Span" , Space , Str "3" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 2)+               (ColSpan 1)+               [ Plain [ Str "Header" , Space , Str "1-3" ] ]+           ]+       , Row ( "" , [] , [] ) []+       , Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Header" , Space , Str "2-1" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Header" , Space , Str "2-3" ] ]+           ]+       ])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 3)+                (ColSpan 2)+                [ Plain [ Str "Body" , Space , Str "1-1/2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 5)+                (ColSpan 1)+                [ Plain [ Str "Span" , Space , Str "5" ] ]+            ]+        , Row ( "" , [] , [] ) []+        , Row ( "" , [] , [] ) []+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Body" , Space , Str "2-1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Body" , Space , Str "2-2" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Body" , Space , Str "3-1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Body" , Space , Str "3-2" ] ]+            ]+        , Row ( "" , [] , [] ) []+        ]+    ]+    (TableFoot+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 5)+               (ColSpan 1)+               [ Plain+                   [ Str "Span" , Space , Str "5" ]+               ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 2)+               [ Plain [ Str "Footer" , Space , Str "1-2" ] ]+           ]+       , Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 2)+               (ColSpan 2)+               [ Plain+                   [ Str "Span" , Space , Str "2" ]+               ]+           ]+       , Row ( "" , [] , [] ) []+       , Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 2)+               [ Plain [ Str "Footer" , Space , Str "3-2/3" ] ]+           ]+       , Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 2)+               [ Plain [ Str "Footer" , Space , Str "4-2/3" ] ]+           ]+       ])+, Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    ]+    (TableHead ( "" , [] , [] ) [])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Body" , Space , Str "1-1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Body" , Space , Str "1-2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 3)+                (ColSpan 1)+                [ Plain [ Str "Span" , Space , Str "4" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 5)+                (ColSpan 1)+                [ Plain [ Str "Span" , Space , Str "5" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Body" , Space , Str "2-2" ] ]+            ]+        , Row+            ( "" , [] , [] ) []+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Body" , Space , Str "3-2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Body" , Space , Str "3-3" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Body" , Space , Str "4-2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Body" , Space , Str "4-3" ] ]+            ]+        , Row+            ( "" , [] , [] ) []+        , Row+            ( "" , [] , [] ) []+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Body" , Space , Str "6-1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Body" , Space , Str "6-2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Span" , Space , Str "6-3" ] ]+            ]+        ]+    ]+    (TableFoot+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Footer" , Space , Str "1-1" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 8)+               (ColSpan 1)+               [ Plain [ Str "Span" , Space , Str "8" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Footer" , Space , Str "1-3" ] ]+           ]+       , Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 3)+               (ColSpan 1)+               [ Plain [ Str "Span" , Space , Str "3" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Footer" , Space , Str "2-3" ] ]+           ]+       , Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 2)+               (ColSpan 1)+               [ Plain [ Str "Span" , Space , Str "2" ] ]+           ]+       , Row ( "" , [] , [] ) []+       , Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Footer" , Space , Str "4-1" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Footer" , Space , Str "4-3" ] ]+           ]+       , Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Footer" , Space , Str "5-1" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 3)+               (ColSpan 1)+               [ Plain [ Str "Span" , Space , Str "3" ] ]+           ]+       , Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 2)+               (ColSpan 1)+               [ Plain [ Str "Span" , Space , Str "2" ] ]+           ]+       , Row ( "" , [] , [] ) []+       ])+, Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    ]+    (TableHead ( "" , [] , [] ) [])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [ "rowspan-cell" ] , [] )+                AlignDefault+                (RowSpan 6)+                (ColSpan 1)+                [ Plain [ Str "Span" , Space , Str "6" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Body" , Space , Str "1-2" ] ]+            , Cell+                ( "" , [ "rowspan-cell" ] , [] )+                AlignDefault+                (RowSpan 2)+                (ColSpan 1)+                [ Plain [ Str "Span" , Space , Str "2" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [ "rowspan-cell" ] , [] )+                AlignDefault+                (RowSpan 3)+                (ColSpan 1)+                [ Plain [ Str "Span" , Space , Str "3" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [ "rowspan-cell" ] , [] )+                AlignDefault+                (RowSpan 4)+                (ColSpan 1)+                [ Plain [ Str "Span" , Space , Str "4" ] ]+            ]+        , Row ( "" , [] , [] ) []+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Body" , Space , Str "3-2" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Body" , Space , Str "4-2" ] ]+            ]+        , Row ( "" , [] , [] ) []+        , Row ( "" , [] , [] ) []+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+]+^D+[cols=",,",options="header,footer",]+|===+|Header 1-1 |Span 3 |Header 1-3+|Header 2-1 | |Header 2-3+2+|Body 1-1/2 .3+|Span 5+|Body 2-1 |Body 2-2+|Body 3-1 |Body 3-2+| | |+.3+|Span 5 2+|Footer 1-2+2+|Span 2+2+|Footer 3-2/3+| 2+|Footer 4-2/3+|===++[cols=",,",options="footer",]+|===+|Body 1-1 |Body 1-2 .2+|Span 4+.3+|Span 5 |Body 2-2+|Body 3-2 |Body 3-3+|Body 4-2 |Body 4-3+| | |+|Body 6-1 |Body 6-2 |Span 6-3+|Footer 1-1 .5+|Span 8 |Footer 1-3+.2+|Span 3 |Footer 2-3+|Span 2+|Footer 4-1 |Footer 4-3+|Footer 5-1 |Span 3+|Span 2 | |+|===++[cols=",,",]+|===+.5+|Span 6 |Body 1-2 .2+|Span 2+.2+|Span 3+.3+|Span 4+|Body 3-2+|Body 4-2+| | |+| | |+|===+```
test/command/7329.md view
@@ -27,7 +27,12 @@ % pandoc -f markdown -t org -C --bibliography command/biblio.bib - [@item1] ^D-- [cite:@item1]+- (Doe 2005)++<<refs>>++<<ref-item1>>+Doe, John. 2005. /First Book/. Cambridge University Press. ```  @@ -40,7 +45,7 @@ <<refs>>  <<ref-item1>>-Doe, John. 2005. /First Book/. Cambridge: Cambridge University Press.+Doe, John. 2005. /First Book/. Cambridge University Press. ```  ```@@ -55,13 +60,13 @@ - [cite:@item1; @item2] - [cite:see @item1; @item2] ^D--   @item1--   @item1 [p. 12]--   @item1 [p.12; see also @item2]--   [@item1]--   [-@item1]--   [see @item1 p. 12]--   [see @item1 p. 12 and *passim*]--   [@item1; @item2]--   [see @item1; @item2]+- @item1+- @item1 [p. 12]+- @item1 [p.12; see also @item2]+- [@item1]+- [-@item1]+- [see @item1 p. 12]+- [see @item1 p. 12 and *passim*]+- [@item1; @item2]+- [see @item1; @item2] ```
+ test/command/7473.md view
@@ -0,0 +1,39 @@+```+% pandoc -f rst -t native+.. figure:: example.png+   :figclass: foo bar+   :align: right+   :width: 1in++   This is a caption.+^D+[ Figure+    ( "" , [ "foo" , "bar" , "align-right" ] , [] )+    (Caption+       Nothing+       [ Plain+           [ Str "This"+           , Space+           , Str "is"+           , Space+           , Str "a"+           , Space+           , Str "caption."+           ]+       ])+    [ Plain+        [ Image+            ( "" , [] , [ ( "width" , "1in" ) ] )+            [ Str "This"+            , Space+            , Str "is"+            , Space+            , Str "a"+            , Space+            , Str "caption."+            ]+            ( "example.png" , "" )+        ]+    ]+]+```
+ test/command/7512.md view
@@ -0,0 +1,70 @@+```+% pandoc -t native -f latex+\begin{equation*}+[d,\delta]=0.+\end{equation*}+^D+[ Para+    [ Math+        DisplayMath+        "\\begin{equation*}\n[d,\\delta]=0.\n\\end{equation*}"+    ]+]+```++```+% pandoc -t native -f latex+\begin{table}[htb]+  \begin{tabular}{|c|c|}+       $W$      & rel. err. \\[0mm]+       [$\mu$m] & [\%]\\+  \end{tabular}+\end{table}+^D+[ Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignCenter , ColWidthDefault )+    , ( AlignCenter , ColWidthDefault )+    ]+    (TableHead ( "" , [] , [] ) [])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Math InlineMath "W" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "rel." , Space , Str "err." ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "[" , Math InlineMath "\\mu" , Str "m]" ]+                ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "[%]" ] ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+]+```
test/command/7521.md view
@@ -5,7 +5,7 @@ - two ^D <ul>-<li>one </li>+<li>one</li> <li>two</li> </ul> ```
+ test/command/7582.md view
@@ -0,0 +1,28 @@+```+% pandoc -t revealjs+# Slide++::: columns+:::: column+Left column+::::++. . .++:::: column+Right column+::::+:::+^D+<section id="slide" class="slide level1">+<h1>Slide</h1>+<div class="columns">+<div class="column">+<p>Left column</p>+</div><div class="fragment"><div class="column">+<p>Right column</p>+</div></div>+</div>+</section>++```
+ test/command/7691.docx view

binary file changed (absent → 11923 bytes)

+ test/command/7691.md view
@@ -0,0 +1,5 @@+```+% pandoc command/7691.docx+^D+<p>Some text</p>+```
test/command/7713.md view
@@ -11,14 +11,14 @@ <col style="width: 33%" /> </colgroup> <thead>-<tr class="header">+<tr> <th>aaaaaaaaaaaa</th> <th>bbbbb</th> <th>ccccccccccc</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td></td> <td></td> <td>cccccccccc cccccccccc cccccccccc cccccccccc cccccccccc
+ test/command/7778.md view
@@ -0,0 +1,59 @@+Here the thing to remember is that block level structure indications+take precedence over inline level structure indications:++```+% pandoc+Term+: Def+<!--+: comment def+-->+^D+<dl>+<dt>Term</dt>+<dd>+Def &lt;!–+</dd>+<dd>+comment def –&gt;+</dd>+</dl>+```++```+% pandoc+Term+: Def+test <!--+: comment def+and -->+^D+<dl>+<dt>Term</dt>+<dd>+Def test &lt;!–+</dd>+<dd>+comment def and –&gt;+</dd>+</dl>+```++```+% pandoc+Term+: Def+`code+: comment def+more code`+^D+<dl>+<dt>Term</dt>+<dd>+Def `code+</dd>+<dd>+comment def more code`+</dd>+</dl>+```
test/command/7847.md view
@@ -7,14 +7,14 @@ <col style="width: 20%" /> </colgroup> <thead>-<tr class="header">+<tr> <th>aaa</th> <th>bbb</th> <th>ccc</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>Consequat nisi sit amet nibh. Nunc mi tortor, tristique sit amet, rhoncus porta, malesuada elementum, nisi.</td> <td></td>@@ -23,9 +23,9 @@ </tbody> </table> ^D-| aaa                                                                                                         | bbb | ccc |+| aaa | bbb | ccc | |---------------|------------------------------------------|---------------|-| Consequat nisi sit amet nibh. Nunc mi tortor, tristique sit amet, rhoncus porta, malesuada elementum, nisi. |     | ccc |+| Consequat nisi sit amet nibh. Nunc mi tortor, tristique sit amet, rhoncus porta, malesuada elementum, nisi. |  | ccc |  ``` @@ -45,9 +45,9 @@ </tr> </table> ^D-| aaa                                                                                                         | bbb | ccc |-|-------------------------------------------------------------------------------------------------------------|-----|-----|-| Consequat nisi sit amet nibh. Nunc mi tortor, tristique sit amet, rhoncus porta, malesuada elementum, nisi. |     | ccc |+| aaa | bbb | ccc |+|----|----|----|+| Consequat nisi sit amet nibh. Nunc mi tortor, tristique sit amet, rhoncus porta, malesuada elementum, nisi. |  | ccc |  ``` @@ -60,14 +60,14 @@ <col style="width: 20%" /> </colgroup> <thead>-<tr class="header">+<tr> <th>aaa</th> <th>bbb</th> <th>ccc</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>Consequat nisi sit amet nibh. Nunc mi tortor, tristique sit amet, rhoncus porta, malesuada elementum, nisi.</td> <td>bbb</td>@@ -76,8 +76,8 @@ </tbody> </table> ^D-| aaa                                                                                                         | bbb | ccc |-|-------------------------------------------------------------------------------------------------------------|-----|-----|+| aaa | bbb | ccc |+|----|----|----| | Consequat nisi sit amet nibh. Nunc mi tortor, tristique sit amet, rhoncus porta, malesuada elementum, nisi. | bbb | ccc |  ```
test/command/7857.md view
@@ -15,7 +15,7 @@ \note{my note}  \begin{frame}{slide}-\phantomsection\label{slide}+\protect\phantomsection\label{slide} ok \end{frame} ```
test/command/7861.md view
@@ -2,6 +2,6 @@ % pandoc -s -t native --data-dir=command/7861 --metadata-file=../../7861.yaml Hello ^D-2> Could not find metadata file ../../7861.yaml+2> Could not find metadata file '../../7861.yaml' => 98 ```
test/command/7863.md view
@@ -10,10 +10,17 @@ Text ^D [ Div-    ( "" , [] , [ ( "data-pos" , "8:1-9:1" ) ] )+    ( ""+    , []+    , [ ( "wrapper" , "1" ) , ( "data-pos" , "8:1-9:1" ) ]+    )     [ Para         [ Span-            ( "" , [] , [ ( "data-pos" , "8:1-8:5" ) ] ) [ Str "Text" ]+            ( ""+            , []+            , [ ( "wrapper" , "1" ) , ( "data-pos" , "8:1-8:5" ) ]+            )+            [ Str "Text" ]         ]     ] ]
test/command/7871.md view
@@ -6,7 +6,7 @@ ^D <table> <tbody>-<tr class="odd">+<tr> <td style="text-align: right; padding-right: 4px;">a</td> </tr> </tbody>
test/command/7919.md view
@@ -7,15 +7,15 @@ ^D <table> <thead>-<tr class="header">+<tr> <th>single column table</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>item 1</td> </tr>-<tr class="even">+<tr> <td>item 2</td> </tr> </tbody>@@ -31,15 +31,15 @@ ^D <table> <thead>-<tr class="header">+<tr> <th>single column table</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>item 1</td> </tr>-<tr class="even">+<tr> <td>item 2</td> </tr> </tbody>@@ -66,15 +66,15 @@ ^D <table> <thead>-<tr class="header">+<tr> <th>single column table</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>item 1</td> </tr>-<tr class="even">+<tr> <td>item 2</td> </tr> </tbody>@@ -90,15 +90,15 @@ ^D <table> <thead>-<tr class="header">+<tr> <th>single column table</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>item 1</td> </tr>-<tr class="even">+<tr> <td>item 2</td> </tr> </tbody>
+ test/command/8024.md view
@@ -0,0 +1,10 @@+```+% pandoc -d command/8024a.yaml -t markdown+Hello, if this works the text should be wrapped.+^D+Hello, if this+works the text+should be+wrapped.++```
+ test/command/8024a.yaml view
@@ -0,0 +1,2 @@+defaults: ${.}/8024b.yaml+
+ test/command/8024b.yaml view
@@ -0,0 +1,3 @@+wrap: auto+columns: 15+
test/command/8110.md view
@@ -18,19 +18,19 @@ ^D <table> <thead>-<tr class="header">+<tr> <th><p>Header text</p></th> <th><p>Header text</p></th> <th><p>Header text</p></th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td><p>Example</p></td> <td><p>Example</p></td> <td><p>Example</p></td> </tr>-<tr class="even">+<tr> <td><p>Example</p></td> <td><p>Example</p></td> <td><p>Example</p></td>
test/command/8131.md view
@@ -19,7 +19,7 @@  Content ^D--   [Head](#head)+- [Head](#head)  # Head 
test/command/8150.md view
@@ -11,11 +11,11 @@   <li>L4</li> </ul> ^D--   L1--   L2-    -   L3.1-    -   L3.2--   L4+- L1+- L2+  - L3.1+  - L3.2+- L4 ```  Nested ordered lists@@ -48,8 +48,8 @@ 	</ol> </ul> ^D--   L1--   L2-    1.  L3.1-    2.  L3.2+- L1+- L2+  1.  L3.1+  2.  L3.2 ```
test/command/8216.md view
@@ -18,15 +18,15 @@ <col style="width: 44%" /> </colgroup> <tbody>-<tr class="odd">+<tr> <td>Some text</td> <td><span class="class1 class2 class3">text</span></td> </tr>-<tr class="even">+<tr> <td>Some text</td> <td><span class="class1 class2 class3">text</span></td> </tr>-<tr class="odd">+<tr> <td>Some text</td> <td><span class="class1 class2 class3">text</span></td> </tr>
test/command/8256.md view
@@ -16,14 +16,13 @@     <style:font-face style:name="Courier New" style:font-family-generic="modern" style:font-pitch="fixed" svg:font-family="'Courier New'" />   </office:font-face-decls>   <office:automatic-styles>-    <style:style style:name="T1" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style>     <style:style style:name="fr2" style:family="graphic" style:parent-style-name="Formula"><style:graphic-properties style:vertical-pos="middle" style:vertical-rel="text" style:horizontal-pos="center" style:horizontal-rel="paragraph-content" style:wrap="none" /></style:style>     <style:style style:name="fr1" style:family="graphic" style:parent-style-name="Formula"><style:graphic-properties style:vertical-pos="middle" style:vertical-rel="text" /></style:style>   </office:automatic-styles> <office:body> <office:text> <text:p text:style-name="Title">This-<text:span text:style-name="T1">is</text:span><text:line-break />a+<text:span text:style-name="Emphasis">is</text:span><text:line-break />a test</text:p> <text:p text:style-name="Author">Someone</text:p> <text:p text:style-name="Text_20_body">Testing.</text:p>
test/command/8257.md view
@@ -16,22 +16,22 @@ <col style="width: 11%" /> </colgroup> <thead>-<tr class="header">+<tr> <th>Item</th> <th>Price</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>Eggs</td> <td>5£</td> </tr>-<tr class="even">+<tr> <td>Spam</td> <td>3£</td> </tr> </tbody><tfoot>-<tr class="odd">+<tr> <td>Sum</td> <td>8£</td> </tr>
test/command/8307.md view
@@ -13,7 +13,7 @@ ^D <table> <tbody>-<tr class="odd">+<tr> <td title="this   &#10; breaks">hello</td>
test/command/8354.md view
@@ -26,7 +26,7 @@ ^D <h2 class="unnumbered" id="references">References</h2> <div id="refs" class="references csl-bib-body hanging-indent"-data-entry-spacing="0" role="list">+role="list"> <div id="ref-feketeExploringReproducibilityVisualization2020" class="csl-entry" role="listitem"> Fekete, Jean-Daniel, and Juliana Freire. 2020. <span>“Exploring
test/command/8402.md view
@@ -19,14 +19,14 @@ ## inner 3 text ^D--   [Summary](#summary){#toc-summary}-    -   [Overview and-        Explanation](#overview-and-explanation){#toc-overview-and-explanation}--   [Details](#details){#toc-details}-    -   [inner 1](#inner-1){#toc-inner-1}-    -   [inner 2](#inner-2){#toc-inner-2}-        -   [inner inner 1](#inner-inner-1){#toc-inner-inner-1}-    -   [inner 3](#inner-3){#toc-inner-3}+- [Summary](#summary){#toc-summary}+  - [Overview and+    Explanation](#overview-and-explanation){#toc-overview-and-explanation}+- [Details](#details){#toc-details}+  - [inner 1](#inner-1){#toc-inner-1}+  - [inner 2](#inner-2){#toc-inner-2}+    - [inner inner 1](#inner-inner-1){#toc-inner-inner-1}+  - [inner 3](#inner-3){#toc-inner-3}  ::: {#6u8qXoeFGdqt .cell .markdown} # Summary
test/command/8508.md view
@@ -7,12 +7,12 @@ * [EBNF](https://en.wikipedia.org/wiki/Extended_Backus–Naur_form) ^D .SH SEE ALSO-.IP \[bu] 2+.IP \(bu 2 \c .UR https://en.wikipedia.org/wiki/Milk Milk .UE \c-.IP \[bu] 2+.IP \(bu 2 \c .UR https://en.wikipedia.org/wiki/Extended_Backus–Naur_form EBNF
test/command/8638.md view
@@ -7,6 +7,7 @@ | oranges | 4.25  | ^D \begin{frame}+{\def\LTcaptype{none} % do not increment counter \begin{longtable}[]{@{}lr@{}} \toprule\noalign{} fruit & price \\@@ -16,5 +17,6 @@ oranges & 4.25 \\ \bottomrule\noalign{} \end{longtable}+} \end{frame} ```
+ test/command/8652.md view
@@ -0,0 +1,28 @@+```+% pandoc -t native+My text^[My note]isnot^[Text]+^D+[ Para+    [ Str "My"+    , Space+    , Str "text"+    , Note [ Para [ Str "My" , Space , Str "note" ] ]+    , Str "isnot"+    , Note [ Para [ Str "Text" ] ]+    ]+]++```++```+% pandoc -t native+^[note1]test^[note2]+^D+[ Para+    [ Note [ Para [ Str "note1" ] ]+    , Str "test"+    , Note [ Para [ Str "note2" ] ]+    ]+]++```
test/command/8659.md view
@@ -5,7 +5,7 @@ ^D <table> <tbody>-<tr class="odd">+<tr> </tr> </tbody> </table>@@ -30,20 +30,20 @@ <col style="width: 16%" /> </colgroup> <thead>-<tr class="header">+<tr> <th style="text-align: left;"></th> <th></th> <th style="text-align: right;"></th> <th style="text-align: right;"><table> <tbody>-<tr class="odd">+<tr> </tr> </tbody> </table></th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td style="text-align: left;">a</td> <td>b</td> <td style="text-align: right;">c</td>
test/command/8665.md view
@@ -23,7 +23,7 @@ ^D [cols=",",options="header",] |===-|h1 |h2-|!@#$%^&*()\{}\|~?+-',."<>[]\` |col 2+<|h1 <|h2+<|!@++#++$%^&++*++()++{++}{vbar}~?{plus}-',."++<>[]\`++ <|col 2 |=== ```
+ test/command/8666.md view
@@ -0,0 +1,40 @@+```+% pandoc -f docbook -t native+<formalpara xml:id="my_code_id">+<title>Code title</title>+<para>+<programlisting language="bash" linenumbering="unnumbered">echo "hello world!"</programlisting>+</para>+</formalpara>+<example xml:id="my_example_id">+<title>Example title</title>+<simpara>example content</simpara>+</example>+<sidebar xml:id="my_sidebar_id">+<title>Sidebar title</title>+<simpara>sidebar content</simpara>+</sidebar>+^D+[ Div+    ( "my_code_id" , [ "formalpara" ] , [] )+    [ Div+        ( "" , [ "title" ] , [] )+        [ Plain [ Str "Code" , Space , Str "title" ] ]+    , CodeBlock ( "" , [ "bash" ] , [] ) "echo \"hello world!\""+    ]+, Div+    ( "my_example_id" , [ "example" ] , [] )+    [ Div+        ( "" , [ "title" ] , [] )+        [ Plain [ Str "Example" , Space , Str "title" ] ]+    , Para [ Str "example" , Space , Str "content" ]+    ]+, Div+    ( "my_sidebar_id" , [ "sidebar" ] , [] )+    [ Div+        ( "" , [ "title" ] , [] )+        [ Plain [ Str "Sidebar" , Space , Str "title" ] ]+    , Para [ Str "sidebar" , Space , Str "content" ]+    ]+]+```
test/command/8738.md view
@@ -2,5 +2,5 @@ % pandoc -f native -t mediawiki [Link ("",[],[]) [Link ("",[],[]) [Str "test"] ("https://bar.example.com",""),Str "Test"] ("https://foo.example.com","")] ^D-[https://foo.example.com testTest]+[https://foo.example.com <span>test</span>Test] ```
test/command/8745.md view
@@ -16,7 +16,7 @@ ^D [ Para [ Str "Sample" , Space , Str "text" ] , Figure-    ( "fig:Mondrian" , [] , [] )+    ( "fig:Mondrian" , [] , [ ( "latex-placement" , "ht" ) ] )     (Caption        Nothing        [ Plain
test/command/8770-block.md view
@@ -39,13 +39,13 @@ <col style="width: 16%" /> </colgroup> <thead>-<tr class="header">+<tr> <th style="text-align: center;">Fruit<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a></th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td style="text-align: center;">Bans<a href="#fn4" class="footnote-ref" id="fnref4" role="doc-noteref"><sup>4</sup></a></td> </tr>
test/command/8770-document.md view
@@ -32,13 +32,13 @@ <col style="width: 16%" /> </colgroup> <thead>-<tr class="header">+<tr> <th style="text-align: center;">Fruit<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a></th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td style="text-align: center;">Bans<a href="#fn4" class="footnote-ref" id="fnref4" role="doc-noteref"><sup>4</sup></a></td> </tr>
test/command/8770-section.md view
@@ -32,13 +32,13 @@ <col style="width: 16%" /> </colgroup> <thead>-<tr class="header">+<tr> <th style="text-align: center;">Fruit<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a></th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td style="text-align: center;">Bans<a href="#fn4" class="footnote-ref" id="fnref4" role="doc-noteref"><sup>4</sup></a></td> </tr>
+ test/command/8783.md view
@@ -0,0 +1,33 @@+```+% pandoc -f rtf -t native+{\rtf1\ansi\ansicpg1252\cocoartf2867+\cocoatextscaling0\cocoaplatform1{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}+{\*\expandedcolortbl;;\cssrgb\c0\c0\c0;}+{\*\listtable{\list\listtemplateid1\listhybrid{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{decimal\}.}{\leveltext\leveltemplateid1\'02\'00.;}{\levelnumbers\'01;}\fi-360\li720\lin720 }{\listname ;}\listid1}+{\list\listtemplateid2\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid101\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid2}}+{\*\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}{\listoverride\listid2\listoverridecount0\ls2}}+\paperw11905\paperh16837\margl1133\margr1133\margb1133\margt1133+\deftab720+\pard\pardeftab720\partightenfactor0++\f0\fs22 \cf2 \up0 \nosupersub \ulnone First paragraph\+\pard\tx20\tx360\pardeftab720\li360\fi-360\partightenfactor0+\ls1\ilvl0\cf2 \up0 \nosupersub \ulnone {\listtext	1.	}\cf2 \up0 \nosupersub \ulnone Numbered item\+\pard\pardeftab720\partightenfactor0+\cf2 Second paragraph\+\pard\tx20\tx180\pardeftab720\li180\fi-180\partightenfactor0+\ls2\ilvl0\cf2 \up0 \nosupersub \ulnone {\listtext	\uc0\u8226 	}\cf2 \up0 \nosupersub \ulnone Bullet item\+\pard\pardeftab720\partightenfactor0+\cf2 New paragraph}+^D+[ Para [ Str "First" , Space , Str "paragraph" ]+, OrderedList+    ( 1 , Decimal , Period )+    [ [ Para [ Str "Numbered" , Space , Str "item" ] ] ]+, Para [ Str "Second" , Space , Str "paragraph" ]+, BulletList+    [ [ Para [ Str "Bullet" , Space , Str "item" ] ] ]+, Para [ Str "New" , Space , Str "paragraph" ]+]+```
test/command/8789.md view
@@ -16,7 +16,7 @@ ^D <table> <thead>-<tr class="header">+<tr> <th style="text-align: right;"><strong>First</strong></th> <th style="text-align: right;"><strong>Second</strong></th> <th style="text-align: left;"><strong>Third</strong></th>@@ -24,13 +24,13 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td style="text-align: right;">160</td> <td style="text-align: right;">1</td> <td style="text-align: left;">test</td> <td style="text-align: left;">test</td> </tr>-<tr class="even">+<tr> <td style="text-align: right;">160</td> <td style="text-align: right;">2</td> <td colspan="2" style="text-align: left;"><em>This is a test:</em> <span
+ test/command/8852.md view
@@ -0,0 +1,43 @@+Github Formatted Markdown Identifiers+```+% pandoc -f man+gfm_auto_identifiers -t html+.TH "TEST" "1" "2026-05-08"  "test v1.0.0" "test manual"+.SH 1st HEADING+.SH C++ & Rust+.SH HEADING+.SH HEADING+^D+<h1 id="1st-heading">1st HEADING</h1>+<h1 id="c--rust">C++ &amp; Rust</h1>+<h1 id="heading">HEADING</h1>+<h1 id="heading-1">HEADING</h1>+```++Ascii Identifiers test+```+% pandoc -f man+ascii_identifiers -t html+.TH "TEST" "1" "2026-05-08"  "test v1.0.0" "test manual"+.SH Über den Flüssen+^D+<h1 id="uber-den-flussen">Über den Flüssen</h1>+```++Headers without Auto Identifiers test+```+% pandoc -f man-auto_identifiers -t native+.TH "TEST" "1" "2026-05-08"  "test v1.0.0" "test manual"+.SS Level 2+.SS different styles:+.SS Ordered+.SS Ordered+^D+[ Header+    2 ( "" , [] , [] ) [ Str "Level" , Space , Str "2" ]+, Header+    2+    ( "" , [] , [] )+    [ Str "different" , Space , Str "styles:" ]+, Header 2 ( "" , [] , [] ) [ Str "Ordered" ]+, Header 2 ( "" , [] , [] ) [ Str "Ordered" ]+]+```
test/command/8853.md view
@@ -2,5 +2,5 @@ % pandoc -f markdown+wikilinks_title_after_pipe --wrap=none [[hi]] and ![[hi]] ^D-<p><a href="hi" title="wikilink">hi</a> and <img src="hi" title="wikilink" alt="hi" /></p>+<p><a href="hi" class="wikilink">hi</a> and <img src="hi" class="wikilink" alt="hi" /></p> ```
+ test/command/8863.md view
@@ -0,0 +1,11 @@+```+% pandoc -f dokuwiki -t native+  * item 1+   * item 1.1+^D+[ BulletList+    [ [ Plain [ Str "item" , Space , Str "1" ] ]+    , [ Plain [ Str "item" , Space , Str "1.1" ] ]+    ]+]+```
+ test/command/8869.md view
@@ -0,0 +1,20 @@+Org arguments can either be single words, or quoted.++```+% pandoc -f org -t native+#+begin_src jupyter-julia :exports both+1 + 2+#+end_src++#+begin_src jupyter-julia :exports "both"+1 + 2+#+end_src+^D+[ CodeBlock+    ( "" , [ "julia" , "code" ] , [ ( "exports" , "both" ) ] )+    "1 + 2\n"+, CodeBlock+    ( "" , [ "julia" , "code" ] , [ ( "exports" , "both" ) ] )+    "1 + 2\n"+]+```
+ test/command/8880.md view
@@ -0,0 +1,42 @@+Raw EPUB attributes are rendered in EPUB output.++```+% pandoc -f native -t epub --metadata title=Raw -o - | pandoc -f epub -t html+[ RawBlock (Format "epub") "<p>ok</p>" ]+^D+<p><span id="title_page.xhtml"></span></p>+<p><span id="ch001.xhtml"></span></p>+<section id="ch001.xhtml_raw" class="unnumbered level1">+<h1 class="unnumbered">Raw</h1>+<p>ok</p>+</section>+```++Raw EPUB2 attributes are omitted from EPUB3 output.++```+% pandoc -f markdown -t epub3 --metadata title=Raw -o - | pandoc -f epub -t html+~~~ {=epub2}+<p>ok</p>+~~~+^D+<p><span id="title_page.xhtml"></span></p>+<p><span id="ch001.xhtml"></span></p>+<section id="ch001.xhtml_raw" class="unnumbered level1">+<h1 class="unnumbered">Raw</h1>+</section>+```++```+% pandoc -f markdown -t epub3 --metadata title=Raw -o - | pandoc -f epub -t html+~~~ {=epub3}+<p>ok</p>+~~~+^D+<p><span id="title_page.xhtml"></span></p>+<p><span id="ch001.xhtml"></span></p>+<section id="ch001.xhtml_raw" class="unnumbered level1">+<h1 class="unnumbered">Raw</h1>+<p>ok</p>+</section>+```
test/command/8948.md view
@@ -1,19 +1,31 @@ ``` % pandoc --embed-resources-![minimal](command/minimal.svg)-![minimal](command/minimal.svg)+![minimal](command/minimal.svg){.inline-svg}+![minimal](command/minimal.svg){.inline-svg} ^D-<p><svg role="img" aria-label="minimal" alt="minimal" viewBox="-.333 -.333 480 150" style="background-color:#ffffff00" xml:space="preserve" width="480" height="150"><use href="#svg_7868854ffb8f30209cd0" width="100%" height="100%" /></svg> <svg id="svg_7868854ffb8f30209cd0" role="img" aria-label="minimal" alt="minimal" viewBox="-.333 -.333 480 150" style="background-color:#ffffff00" xml:space="preserve" width="480" height="150">+<p><svg role="img" aria-label="minimal" alt="minimal" viewBox="-.333 -.333 480 150" style="background-color:#ffffff00" xml:space="preserve" width="480" height="150"><use href="#svg_7868854ffb8f30209cd0" width="100%" height="100%" /></svg>+<svg id="svg_7868854ffb8f30209cd0" role="img" aria-label="minimal" alt="minimal" viewBox="-.333 -.333 480 150" style="background-color:#ffffff00" xml:space="preserve" width="480" height="150">     <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></p> ```  ``` % pandoc --embed-resources-![minimal](command/minimal.svg)-![minimal](command/minimal.svg){#foo}+![minimal](command/minimal.svg){.inline-svg}+![minimal](command/minimal.svg){#foo .inline-svg} ^D-<p><svg role="img" aria-label="minimal" alt="minimal" viewBox="-.333 -.333 480 150" style="background-color:#ffffff00" xml:space="preserve" width="480" height="150"><use href="#foo" width="100%" height="100%" /></svg> <svg id="foo" role="img" aria-label="minimal" alt="minimal" viewBox="-.333 -.333 480 150" style="background-color:#ffffff00" xml:space="preserve" width="480" height="150">+<p><svg role="img" aria-label="minimal" alt="minimal" viewBox="-.333 -.333 480 150" style="background-color:#ffffff00" xml:space="preserve" width="480" height="150"><use href="#foo" width="100%" height="100%" /></svg>+<svg id="foo" role="img" aria-label="minimal" alt="minimal" viewBox="-.333 -.333 480 150" style="background-color:#ffffff00" xml:space="preserve" width="480" height="150">     <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></p>+```++```+% pandoc --embed-resources+![minimal](command/minimal.svg)+^D+<figure>+<img role="img" aria-label="minimal" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PgoKPHN2ZyB2aWV3Qm94PSItLjMzMyAtLjMzMyA0ODAgMTUwIiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjojZmZmZmZmMDAiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CiAgICA8cGF0aCBkPSJNIDAgMzUuNSBMIDYuNSAyMi41IEwgMTYgMzcgTCAyMyAyNCBMIDM0LjggNDMuNyBMIDQyLjUgMzAgTCA1MC4zIDQ3IEwgNTkuNyAyNy43IEwgNjkgNDcgTCA4NSAxNy43IEwgOTguMyAzOSBMIDExMyA5LjcgTCAxMjcuNyA0Mi4zIEwgMTM2LjMgMjMuNyBMIDE0NyA0NC4zIEwgMTU4LjMgMjAuMyBMIDE3MC4zIDQwLjMgTCAxNzcuNyAyNS43IEwgMTg5LjcgNDMgTCAxOTkuNyAyMSBMIDIwNy43IDM1IEwgMjE5IDExIEwgMjMzIDM3IEwgMjQwLjMgMjMuNyBMIDI1MSA0MyBMIDI2MyAxOC4zIEwgMjcyLjcgMzMuMyBMIDI4MyAxMCBMIDI5NSAzMi4zIEwgMzAxLjMgMjMgTCAzMTEuNyAzNyBMIDMyMy43IDcuNyBMIDMzOS4zIDM5IEwgMzQ2LjMgMjUuNyBMIDM1Ni4zIDQyLjMgTCAzNjkuNyAxNSBMIDM3Ni4zIDI1LjcgTCAzODQgOSBMIDM5MyAyOC4zIEwgNDAwLjMgMTkgTCA0MTEuNyAzOC4zIEwgNDIxIDIxIEwgNDM0LjMgNDMgTCA0NDUgMjUgTCA0NTMgMzYuMyBMIDQ2NC4zIDE4LjMgTCA0NzYuMiA0MC4zIEwgNDgwIDMzLjUgTCA0ODAgMjE1IEwgMCAyMTUgTCAwIDM1LjUgWiIgZmlsbD0iIzE3NTcyMCIvPgo8L3N2Zz4K" alt="minimal" />+<figcaption aria-hidden="true">minimal</figcaption>+</figure> ```
+ test/command/8957.md view
@@ -0,0 +1,7 @@+```+% pandoc -f latex -t html --wrap=none+![Sample figure caption.](fig.jpg){width="342pt" height="9pc"}+^D+<p>![Sample figure caption.](fig.jpg)<span>width="342pt" height="9pc"</span></p>++```
test/command/8966.md view
@@ -3,7 +3,7 @@ **Samsonov T.E.** Shape-Adaptive Geometric Simplification of Heterogeneous Line Datasets / T. E. Samsonov, O. P. Yakimova // International Journal of Geographical Information Science. — 2017. — Vol. 31. — № 8. — pp. 1485-1520. ^D #strong[Samsonov T.E.] Shape-Adaptive Geometric Simplification of-Heterogeneous Line Datasets / T. E. Samsonov, O. P. Yakimova \/\/-International Journal of Geographical Information Science. — 2017. —-Vol. 31. — № 8. — pp.~1485-1520.+Heterogeneous Line Datasets / T. E. Samsonov, O. P. Yakimova /\/+International Journal of Geographical Information Science. --- 2017. ---+Vol. 31. --- № 8. --- pp.~1485-1520. ```
test/command/8997.md view
@@ -24,7 +24,7 @@     , Space     , Str "colon"     ]-, CodeBlock ( "" , [ "example" ] , [] ) "aaa\n\nbbb\n"+, CodeBlock ( "" , [] , [] ) "aaa\n\nbbb\n" , Header     1     ( "has-no-space-after-second-colon" , [] , [] )@@ -40,7 +40,7 @@     , Space     , Str "colon"     ]-, CodeBlock ( "" , [ "example" ] , [] ) "aaa\n\nbbb\n"+, CodeBlock ( "" , [] , [] ) "aaa\n\nbbb\n" ] ``` @@ -56,7 +56,7 @@     1     ( "only-the-colon" , [] , [] )     [ Str "only" , Space , Str "the" , Space , Str "colon" ]-, CodeBlock ( "" , [ "example" ] , [] ) "\n"+, CodeBlock ( "" , [] , [] ) "\n" , Header     1     ( "only-the-colon-and-a-space" , [] , [] )@@ -72,6 +72,6 @@     , Space     , Str "space"     ]-, CodeBlock ( "" , [ "example" ] , [] ) "\n"+, CodeBlock ( "" , [] , [] ) "\n" ] ```
+ test/command/9000.md view
@@ -0,0 +1,14 @@+```+% pandoc -t org --wrap=auto --columns=20+[This is a link with a long description that should not+wrap](http://example.com) and+some regular text after it so we can see how wrapping works.+^D+[[http://example.com][This is a link with a long description that should not wrap]]+and some regular+text after it so we+can see how wrapping+works.++```+
test/command/9002.md view
@@ -1,14 +1,14 @@ ``` % pandoc command/9002.docx -t html ^D-<table>+<table style="width:40%;"> <caption><p>This is my table!</p></caption> <colgroup>-<col style="width: 50%" />-<col style="width: 50%" />+<col style="width: 20%" />+<col style="width: 20%" /> </colgroup> <thead>-<tr class="header">+<tr> <th>a</th> <th>b</th> </tr>@@ -16,5 +16,5 @@ <tbody> </tbody> </table>-<p>See Table 1 This is my table!</p>+<p>See <a href="#_Ref143272803">Table 1 This is my table!</a></p> ```
test/command/9017.md view
@@ -45,7 +45,8 @@ <ref-list>   <title></title>   <ref id="ref-degroot_probability">-    <mixed-citation>DeGroot. 2002. “Probability.”</mixed-citation>+    <mixed-citation>DeGroot. 2002.+    <italic>Probability</italic>.</mixed-citation>   </ref> </ref-list> </back>
test/command/9045.md view
@@ -4,7 +4,7 @@ ^D \begin{figure} \centering-\includegraphics{there.jpg}+\pandocbounded{\includegraphics[keepaspectratio,alt={hi}]{there.jpg}} \caption{hi}\label{foo} \end{figure} ```
+ test/command/9121.md view
@@ -0,0 +1,17 @@+````+% pandoc -t gfm+a $$x=y$$ b+^D+a+``` math+x=y+```+b+````++````+% pandoc -t gfm+a $x=y$ b+^D+a $`x=y`$ b+````
+ test/command/9136.md view
@@ -0,0 +1,89 @@+Verify that the OpenDocument writer uses predefined list, paragraph, and+text styles instead of generating per-instance automatic styles.++```+% pandoc -t opendocument+- one+- two++1. ordered one+2. ordered two++Some *italic*, **bold**, ~~strike~~, and `code`.++> A block quote.++Final paragraph.+^D+<text:list text:style-name="List_20_1">+  <text:list-item>+    <text:p text:style-name="List_20_Bullet_20_Tight">one</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Bullet_20_Tight">two</text:p>+  </text:list-item>+</text:list>+<text:list text:style-name="Numbering_20_1">+  <text:list-item>+    <text:p text:style-name="List_20_Number_20_Tight">ordered+    one</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Number_20_Tight">ordered+    two</text:p>+  </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">Some+<text:span text:style-name="Emphasis">italic</text:span>,+<text:span text:style-name="Strong_20_Emphasis">bold</text:span>,+<text:span text:style-name="Strikeout">strike</text:span>, and+<text:span text:style-name="Source_20_Text">code</text:span>.</text:p>+<text:p text:style-name="Quotations">A block quote.</text:p>+<text:p text:style-name="First_20_paragraph">Final paragraph.</text:p>+```++A non-default ordered list (start value other than 1, or non-decimal+format) generates a single named override style, not one per instance.++```+% pandoc -t opendocument+A) upper-alpha one+B) upper-alpha two++5. start at five+6. and continue+^D+<text:list text:style-name="Pandoc_5f_Numbering_5f_1">+  <text:list-item>+    <text:p text:style-name="List_20_Number_20_Tight">upper-alpha+    one</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Number_20_Tight">upper-alpha+    two</text:p>+  </text:list-item>+</text:list>+<text:list text:style-name="Numbering_20_1" text:start-value="5">+  <text:list-item>+    <text:p text:style-name="List_20_Number_20_Tight">start at+    five</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Number_20_Tight">and+    continue</text:p>+  </text:list-item>+</text:list>+```++A nested block quote uses the predefined `Quotations` style for the+outer paragraph, and inherits indent from it for the inner paragraph.++```+% pandoc -t opendocument+> First.+>+> > Nested.+^D+<text:p text:style-name="Quotations">First.</text:p>+<text:p text:style-name="P1">Nested.</text:p>+```
+ test/command/9196.md view
@@ -0,0 +1,6 @@+```+% pandoc -f rst --wrap=none+Define  _`my target`, then reference `my target`_.+^D+<p>Define <span id="my-target">my target</span>, then reference <a href="#my-target">my target</a>.</p>+```
test/command/9201.md view
@@ -12,7 +12,7 @@  **\--help** -:   This is line one.+: This is line one. -    This is line two.+  This is line two. ```
test/command/9236.md view
@@ -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")).  ```
test/command/9346.md view
@@ -3,6 +3,6 @@ |V1 |V2 |V3 |V4 |V5 |V6 |V7 |V8 |V9 |V10 |V11 |V12 |V13 |V14 |V15 |V16 |V17 |V18 |V19 |V20 |V21 |V22 |V23 |V24 |V25 |V26 |V27 |V28 |V29 |V30 |V31 |V32 |V33 |V34 |V35 |V36 |V37 |V38 |V39 |V40 |V41 |V42 |V43 |V44 |V45 |V46 |V47 |V48 |V49 |V50 |V51 |V52 |V53 |V54 |V55 |V56 |V57 |V58 |V59 |V60 |V61 |V62 |V63 |V64 |V65 |V66 |V67 |V68 |V69 |V70 |V71 |V72 | |:--|:--|:--|:--|:--|:--|:--|:--|:--|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---| ^D-| V1  | V2  | V3  | V4  | V5  | V6  | V7  | V8  | V9  | V10 | V11 | V12 | V13 | V14 | V15 | V16 | V17 | V18 | V19 | V20 | V21 | V22 | V23 | V24 | V25 | V26 | V27 | V28 | V29 | V30 | V31 | V32 | V33 | V34 | V35 | V36 | V37 | V38 | V39 | V40 | V41 | V42 | V43 | V44 | V45 | V46 | V47 | V48 | V49 | V50 | V51 | V52 | V53 | V54 | V55 | V56 | V57 | V58 | V59 | V60 | V61 | V62 | V63 | V64 | V65 | V66 | V67 | V68 | V69 | V70 | V71 | V72 |+| V1 | V2 | V3 | V4 | V5 | V6 | V7 | V8 | V9 | V10 | V11 | V12 | V13 | V14 | V15 | V16 | V17 | V18 | V19 | V20 | V21 | V22 | V23 | V24 | V25 | V26 | V27 | V28 | V29 | V30 | V31 | V32 | V33 | V34 | V35 | V36 | V37 | V38 | V39 | V40 | V41 | V42 | V43 | V44 | V45 | V46 | V47 | V48 | V49 | V50 | V51 | V52 | V53 | V54 | V55 | V56 | V57 | V58 | V59 | V60 | V61 | V62 | V63 | V64 | V65 | V66 | V67 | V68 | V69 | V70 | V71 | V72 | |:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-| ```
test/command/9350.md view
@@ -2,6 +2,7 @@ % pandoc -f html -t latex <table><tbody><tr></tr></tbody></table> ^D+{\def\LTcaptype{none} % do not increment counter \begin{longtable}[]{@{}l@{}} \toprule\noalign{} \endhead@@ -9,4 +10,5 @@ \endlastfoot  \\ \end{longtable}+} ```
+ test/command/9358.docx view

binary file changed (absent → 13439 bytes)

+ test/command/9358.md view
@@ -0,0 +1,45 @@+Caption belongs to the second table:+```+% pandoc -f docx -t html command/9358.docx+^D+<p>Lorem gipsum</p>+<table>+<colgroup>+<col style="width: 50%" />+<col style="width: 50%" />+</colgroup>+<thead>+<tr>+<th>A</th>+<th>B</th>+</tr>+</thead>+<tbody>+<tr>+<td>C</td>+<td>D</td>+</tr>+</tbody>+</table>+<p>Lorem ipsum</p>+<table>+<caption><p>Table 1 Numbers from 1 to 4</p></caption>+<colgroup>+<col style="width: 50%" />+<col style="width: 50%" />+</colgroup>+<thead>+<tr>+<th>1</th>+<th>2</th>+</tr>+</thead>+<tbody>+<tr>+<td>3</td>+<td>4</td>+</tr>+</tbody>+</table>+<p>Lorem yipsum</p>+```
+ test/command/9366.md view
@@ -0,0 +1,34 @@+```+% pandoc -f native -t latex+[ Para+    [ Strikeout+        [ Link+            ( "" , [] , [] )+            [ Str "Example" ]+            ( "https://example.com" , "" )+        ]+    ]+, Para+    [ Strikeout+        [ Link+            ( "" , [] , [] )+            [ Str "https://example.com" ]+            ( "https://example.com" , "" )+        ]+    ]+, Para+    [ Strikeout+        [ Link+            ( "" , [] , [] )+            [ Str "info@example.com" ]+            ( "mailto:info@example.com" , "" )+        ]+    ]+]+^D+\st{\mbox{\href{https://example.com}{Example}}}++\st{\mbox{\url{https://example.com}}}++\st{\mbox{\href{mailto:info@example.com}{\nolinkurl{info@example.com}}}}+```
test/command/9387.md view
@@ -9,7 +9,7 @@ test  ] #label("my label")-See #link(label("my label"))[my label];.+See #link(label("my label"))[my label].  ``` 
+ test/command/9391.docx view

binary file changed (absent → 13701 bytes)

+ test/command/9391.md view
@@ -0,0 +1,9 @@+```+% pandoc command/9391.docx -t html+^D+<p>Lorem ipsum.</p>+<figure>+<img src="media/image1.png" style="width:1.09702in;height:1.09702in" />+<figcaption><p>Blue square.</p></figcaption>+</figure>+```
test/command/9420.md view
@@ -1,6 +1,6 @@ ``` % pandoc --embed-resources-![](command/9420.svg)+![](command/9420.svg){.inline-svg} ^D <p><svg id="svg_e1815ef374a63cf552e4" role="img" width="504pt" height="360pt" viewBox="0 0 504 360"> <defs>
test/command/9452.md view
@@ -12,8 +12,8 @@  Here is a sentence @something2024. -With supplement @something2024[p.~3];.+With supplement @something2024[p.~3]. -And just the year #cite(<something2024>, form: "year");.+And just the year (#cite(<something2024>, form: "year")).  ```
test/command/9467.md view
@@ -2,57 +2,6 @@ % pandoc --embed-resources ![](command/9467.svg) ^D-<p><svg id="svg2" role="img" width="191.56267" height="151.71201" viewBox="0 0 191.56267 151.71201" xmlns:svg="http://www.w3.org/2000/svg">-  <defs id="svg2_defs6">-    <clipPath clipPathUnits="userSpaceOnUse" id="svg2_clipPath24">-      <path d="M 56.69362,0 113.38724,113.38724 170.08086,0 Z" id="svg2_path22" />-    </clipPath>-    <clipPath clipPathUnits="userSpaceOnUse" id="svg2_clipPath38">-      <path d="M 0,0 H 100 V 100 H 0 Z" id="svg2_path36" />-    </clipPath>-    <radialGradient fx="50.000641" fy="50.000641" cx="50.000641" cy="50.000641" r="50.000641" gradientUnits="userSpaceOnUse" id="svg2_radialGradient46">-      <stop style="stop-opacity:1;stop-color:#ffffff" offset="0" id="svg2_stop40"></stop>-      <stop style="stop-opacity:1;stop-color:#9999ff" offset="25.00032" id="svg2_stop42"></stop>-      <stop style="stop-opacity:1;stop-color:#9999ff" offset="50.00064" id="svg2_stop44"></stop>-    </radialGradient>-  </defs>-  <g id="svg2_g8" transform="matrix(1.3333333,0,0,-1.3333333,0,151.712)">-    <g id="svg2_g10" transform="translate(-26.606,0.199)">-      <g id="svg2_g12">-        <g id="svg2_g14">-          <g id="svg2_g16">-            <g id="svg2_g18">-              <g id="svg2_g20" clip-path="url(#svg2_clipPath24)">-                <g id="svg2_g26" transform="matrix(2.26802,0,0,2.26802,113.38724,56.69362)">-                  <g id="svg2_g28">-                    <g id="svg2_g30" transform="translate(-50,-50)">-                      <g id="svg2_g32">-                        <g id="svg2_g34" clip-path="url(#svg2_clipPath38)">-                          <path d="M 0,0 H 100 V 100 H 0 Z" style="fill:url(#svg2_radialGradient46);stroke:none" id="svg2_path48" />-                        </g>-                      </g>-                    </g>-                  </g>-                </g>-              </g>-            </g>-            <path d="M 56.69362,0 113.38724,113.38724 170.08086,0 Z" style="fill:none;stroke:#9999ff;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1" id="svg2_path50" />-            <g id="svg2_g52">-              <g id="svg2_g54" transform="translate(63.337,5.457)">-                <g id="svg2_g56">-                  <g id="svg2_g58" transform="translate(-36.731,-5.656)">-                    <text xml:space="preserve" transform="matrix(1,0,0,-1,36.731,5.656)" style="font-variant:normal;font-weight:normal;font-size:9.9626px;font-family:CMSS10;-inkscape-font-specification:CMSS10;writing-mode:lr-tb;fill:#9999ff;fill-opacity:1;fill-rule:nonzero;stroke:none" id="svg2_text62"><tspan x="0 4.9812999 8.38552 13.173546 18.321222 20.701286 25.128666 30.27634 37.191383 41.010048 46.157722 50.945747 56.093422 60.520802 68.995987 72.593483 75.997704 78.377769 83.165794 88.303505 93.284805 95.664871" y="0" id="svg2_tspan60">gradientshadedtriangle</tspan></text>-                    <g id="svg2_g64" transform="translate(36.731,5.656)"></g>-                  </g>-                </g>-                <g id="svg2_g66" transform="translate(-63.337,-5.457)"></g>-              </g>-            </g>-          </g>-        </g>-      </g>-    </g>-  </g>-</svg></p>+<p><img role="img" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTkiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgoKPHN2ZwogICB2ZXJzaW9uPSIxLjEiIGlkPSJzdmcyIiB3aWR0aD0iMTkxLjU2MjY3IiBoZWlnaHQ9IjE1MS43MTIwMSIgdmlld0JveD0iMCAwIDE5MS41NjI2NyAxNTEuNzEyMDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6c3ZnPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPGRlZnMgaWQ9ImRlZnM2Ij4KICAgIDxjbGlwUGF0aCBjbGlwUGF0aFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgaWQ9ImNsaXBQYXRoMjQiPgogICAgICA8cGF0aCBkPSJNIDU2LjY5MzYyLDAgMTEzLjM4NzI0LDExMy4zODcyNCAxNzAuMDgwODYsMCBaIiBpZD0icGF0aDIyIiAvPgogICAgPC9jbGlwUGF0aD4KICAgIDxjbGlwUGF0aCBjbGlwUGF0aFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgaWQ9ImNsaXBQYXRoMzgiPgogICAgICA8cGF0aCBkPSJNIDAsMCBIIDEwMCBWIDEwMCBIIDAgWiIgaWQ9InBhdGgzNiIgLz4KICAgIDwvY2xpcFBhdGg+CiAgICA8cmFkaWFsR3JhZGllbnQgZng9IjUwLjAwMDY0MSIgZnk9IjUwLjAwMDY0MSIgY3g9IjUwLjAwMDY0MSIgY3k9IjUwLjAwMDY0MSIgcj0iNTAuMDAwNjQxIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgaWQ9InJhZGlhbEdyYWRpZW50NDYiPgogICAgICA8c3RvcCBzdHlsZT0ic3RvcC1vcGFjaXR5OjE7c3RvcC1jb2xvcjojZmZmZmZmIiBvZmZzZXQ9IjAiIGlkPSJzdG9wNDAiIC8+CiAgICAgIDxzdG9wIHN0eWxlPSJzdG9wLW9wYWNpdHk6MTtzdG9wLWNvbG9yOiM5OTk5ZmYiIG9mZnNldD0iMjUuMDAwMzIiIGlkPSJzdG9wNDIiIC8+CiAgICAgIDxzdG9wIHN0eWxlPSJzdG9wLW9wYWNpdHk6MTtzdG9wLWNvbG9yOiM5OTk5ZmYiIG9mZnNldD0iNTAuMDAwNjQiIGlkPSJzdG9wNDQiIC8+CiAgICA8L3JhZGlhbEdyYWRpZW50PgogIDwvZGVmcz4KICA8ZyBpZD0iZzgiIHRyYW5zZm9ybT0ibWF0cml4KDEuMzMzMzMzMywwLDAsLTEuMzMzMzMzMywwLDE1MS43MTIpIj4KICAgIDxnIGlkPSJnMTAiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yNi42MDYsMC4xOTkpIj4KICAgICAgPGcgaWQ9ImcxMiI+CiAgICAgICAgPGcgaWQ9ImcxNCI+CiAgICAgICAgICA8ZyBpZD0iZzE2Ij4KICAgICAgICAgICAgPGcgaWQ9ImcxOCI+CiAgICAgICAgICAgICAgPGcgaWQ9ImcyMCIgY2xpcC1wYXRoPSJ1cmwoI2NsaXBQYXRoMjQpIj4KICAgICAgICAgICAgICAgIDxnIGlkPSJnMjYiIHRyYW5zZm9ybT0ibWF0cml4KDIuMjY4MDIsMCwwLDIuMjY4MDIsMTEzLjM4NzI0LDU2LjY5MzYyKSI+CiAgICAgICAgICAgICAgICAgIDxnIGlkPSJnMjgiPgogICAgICAgICAgICAgICAgICAgIDxnIGlkPSJnMzAiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC01MCwtNTApIj4KICAgICAgICAgICAgICAgICAgICAgIDxnIGlkPSJnMzIiPgogICAgICAgICAgICAgICAgICAgICAgICA8ZyBpZD0iZzM0IiBjbGlwLXBhdGg9InVybCgjY2xpcFBhdGgzOCkiPgogICAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0gMCwwIEggMTAwIFYgMTAwIEggMCBaIiBzdHlsZT0iZmlsbDp1cmwoI3JhZGlhbEdyYWRpZW50NDYpO3N0cm9rZTpub25lIiBpZD0icGF0aDQ4IiAvPgogICAgICAgICAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICAgICAgPC9nPgogICAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgPC9nPgogICAgICAgICAgICA8L2c+CiAgICAgICAgICAgIDxwYXRoIGQ9Ik0gNTYuNjkzNjIsMCAxMTMuMzg3MjQsMTEzLjM4NzI0IDE3MC4wODA4NiwwIFoiIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiM5OTk5ZmY7c3Ryb2tlLXdpZHRoOjAuMzk4NTtzdHJva2UtbGluZWNhcDpidXR0O3N0cm9rZS1saW5lam9pbjptaXRlcjtzdHJva2UtbWl0ZXJsaW1pdDoxMDtzdHJva2UtZGFzaGFycmF5Om5vbmU7c3Ryb2tlLW9wYWNpdHk6MSIgaWQ9InBhdGg1MCIgLz4KICAgICAgICAgICAgPGcgaWQ9Imc1MiI+CiAgICAgICAgICAgICAgPGcgaWQ9Imc1NCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNjMuMzM3LDUuNDU3KSI+CiAgICAgICAgICAgICAgICA8ZyBpZD0iZzU2Ij4KICAgICAgICAgICAgICAgICAgPGcgaWQ9Imc1OCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTM2LjczMSwtNS42NTYpIj4KICAgICAgICAgICAgICAgICAgICA8dGV4dCB4bWw6c3BhY2U9InByZXNlcnZlIiB0cmFuc2Zvcm09Im1hdHJpeCgxLDAsMCwtMSwzNi43MzEsNS42NTYpIiBzdHlsZT0iZm9udC12YXJpYW50Om5vcm1hbDtmb250LXdlaWdodDpub3JtYWw7Zm9udC1zaXplOjkuOTYyNnB4O2ZvbnQtZmFtaWx5OkNNU1MxMDstaW5rc2NhcGUtZm9udC1zcGVjaWZpY2F0aW9uOkNNU1MxMDt3cml0aW5nLW1vZGU6bHItdGI7ZmlsbDojOTk5OWZmO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiBpZD0idGV4dDYyIj48dHNwYW4geD0iMCA0Ljk4MTI5OTkgOC4zODU1MiAxMy4xNzM1NDYgMTguMzIxMjIyIDIwLjcwMTI4NiAyNS4xMjg2NjYgMzAuMjc2MzQgMzcuMTkxMzgzIDQxLjAxMDA0OCA0Ni4xNTc3MjIgNTAuOTQ1NzQ3IDU2LjA5MzQyMiA2MC41MjA4MDIgNjguOTk1OTg3IDcyLjU5MzQ4MyA3NS45OTc3MDQgNzguMzc3NzY5IDgzLjE2NTc5NCA4OC4zMDM1MDUgOTMuMjg0ODA1IDk1LjY2NDg3MSIgeT0iMCIgaWQ9InRzcGFuNjAiPmdyYWRpZW50c2hhZGVkdHJpYW5nbGU8L3RzcGFuPjwvdGV4dD4KICAgICAgICAgICAgICAgICAgICA8ZyBpZD0iZzY0IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgzNi43MzEsNS42NTYpIiAvPgogICAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICA8ZyBpZD0iZzY2IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNjMuMzM3LC01LjQ1NykiIC8+CiAgICAgICAgICAgICAgPC9nPgogICAgICAgICAgICA8L2c+CiAgICAgICAgICA8L2c+CiAgICAgICAgPC9nPgogICAgICA8L2c+CiAgICA8L2c+CiAgPC9nPgo8L3N2Zz4K" /></p>  ```
test/command/9472.md view
@@ -11,10 +11,13 @@ % Options for packages loaded elsewhere \PassOptionsToPackage{unicode}{hyperref} \PassOptionsToPackage{hyphens}{url}-% \documentclass[+  french,+  ngerman, ]{article}+\usepackage{xcolor} \usepackage{amsmath,amssymb}+\setcounter{secnumdepth}{-\maxdimen} % remove section numbering \usepackage{iftex} \ifPDFTeX   \usepackage[T1]{fontenc}@@ -45,27 +48,24 @@ }{% if KOMA class   \KOMAoptions{parskip=half}} \makeatother-\usepackage{xcolor}-\setlength{\emergencystretch}{3em} % prevent overfull lines-\providecommand{\tightlist}{%-  \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}-\setcounter{secnumdepth}{-\maxdimen} % remove section numbering \ifLuaTeX-\usepackage[bidi=basic]{babel}+\usepackage[bidi=basic,shorthands=off]{babel} \else-\usepackage[bidi=default]{babel}+\usepackage[bidi=default,shorthands=off]{babel} \fi-\babelprovide[main,import]{ngerman}-\babelprovide[import]{french}-% get rid of language-specific shorthands (see #6817):-\let\LanguageShortHands\languageshorthands-\def\languageshorthands#1{} \ifLuaTeX-  \usepackage{selnolig}  % disable illegal ligatures+  \usepackage{selnolig} % disable illegal ligatures \fi+\setlength{\emergencystretch}{3em} % prevent overfull lines+\providecommand{\tightlist}{%+  \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}} \usepackage{bookmark} \IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available \urlstyle{same}+% fallback for those not using the hyperref driver hyperxmp:+\makeatletter+\@ifundefined{xmpquote}{\newcommand{\xmpquote}[1]{#1}}{}+\makeatother \hypersetup{   pdflang={de-DE},   hidelinks,
+ test/command/9603.docx view

binary file changed (absent → 13799 bytes)

+ test/command/9603.md view
@@ -0,0 +1,23 @@+```+% pandoc command/9603.docx -t html -f docx+styles+^D+<p>A table with a contemporary style:</p>+<table data-custom-style="TableContemporary">+<colgroup>+<col style="width: 50%" />+<col style="width: 50%" />+</colgroup>+<thead>+<tr>+<th>Test</th>+<th>Column</th>+</tr>+</thead>+<tbody>+<tr>+<td>1</td>+<td>2</td>+</tr>+</tbody>+</table>+```
+ test/command/9635.md view
@@ -0,0 +1,16 @@+```+% pandoc+> ::: {.fence}+> that is+> not closed++okay+^D+2> [WARNING] Div at _chunk line 1 column 1 unclosed at _chunk line 5 column 1, closing implicitly.+<blockquote>+<div class="fence">+<p>that is not closed</p>+</div>+</blockquote>+<p>okay</p>+```
+ test/command/9644.md view
@@ -0,0 +1,7 @@+```+% pandoc -t latex+[$T$]{.underline}+[$T$]{.mark}+^D+\ul{$T$} \hl{$T$}+```
+ test/command/9652.md view
@@ -0,0 +1,9 @@+````+% pandoc -f markdown -t html --embed-resources+```{=html}+<img class="something inline-svg" src="command/9652.svg" />+```+^D+<svg id="svg_b627f92299158b36552b" role="img" width="504.00pt" height="360.00pt" viewBox="0 0 504.00 360.00" class="something inline-svg please-do-not-delete-me">+</svg>+````
+ test/command/9652.svg view
@@ -0,0 +1,3 @@+<?xml version='1.0' encoding='UTF-8' ?>+<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' class='please-do-not-delete-me' width='504.00pt' height='360.00pt' viewBox='0 0 504.00 360.00'>+</svg>
+ test/command/9657.md view
@@ -0,0 +1,7 @@+```+% pandoc -t opendocument+[Text here]{custom-style="Strikethrough"}+^D+<text:p text:style-name="Text_20_body"><text:span text:style-name="Strikethrough">Text+here</text:span></text:p>+```
+ test/command/9676.md view
@@ -0,0 +1,9 @@+```+% pandoc -f latex+\def\foo{BAR}+\foo+\ifstrequal{BAR}{BAR}{\def\foo{BAZ}}{}+\foo+^D+<p>BAR BAZ</p>+```
+ test/command/9700.md view
@@ -0,0 +1,14 @@+```+% pandoc -t mediawiki+This is a normal sentence with a manual text footnote\*++\* The footnote explains why it couldn't just be inside parentheses++\#foobar \#foobar+^D+This is a normal sentence with a manual text footnote*++<nowiki></nowiki>* The footnote explains why it couldn’t just be inside parentheses++<nowiki></nowiki>#foobar #foobar+```
+ test/command/9716.md view
@@ -0,0 +1,13 @@+```+% pandoc -f markdown+alerts -t native+> [!TIP]+> A suggestion.+^D+[ Div+    ( "" , [ "tip" ] , [] )+    [ Div ( "" , [ "title" ] , [] ) [ Para [ Str "Tip" ] ]+    , Para [ Str "A" , Space , Str "suggestion." ]+    ]+]++```
+ test/command/9777-b.md view
@@ -0,0 +1,62 @@+```+% pandoc -f native -t typst+[ Table+    ( "" , [] , [ ( "typst:figure:kind" , "figure" ) ] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "f" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "b" ] ]+           ]+       ])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "2" ] ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+]+^D+#figure(+  align(center)[#table(+    columns: 2,+    align: (auto,auto,),+    table.header([f], [b],),+    table.hline(),+    [1], [2],+  )]+  , kind: figure+  )+```+
+ test/command/9777.md view
@@ -0,0 +1,58 @@+```+% pandoc -f native -t typst+[ Table+    ( "" , [ "typst:no-figure" ] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "f" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "b" ] ]+           ]+       ])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "2" ] ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+]+^D+#table(+  columns: 2,+  align: (auto,auto,),+  table.header([f], [b],),+  table.hline(),+  [1], [2],+)+```
+ test/command/9792.md view
@@ -0,0 +1,21 @@+```+% pandoc -t gfm+- list item+  <details>++  - subitem+  </details>++  item _continue_ **with** formatting+- next list item+^D+- list item+  <details>++  - subitem++  </details>++  item *continue* **with** formatting+- next list item+```
+ test/command/9797.md view
@@ -0,0 +1,39 @@+```+% pandoc -t native -f csv+"one_line_break:+four_line_breaks:++++last_line"+^D+[ Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidthDefault ) ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain+                   [ Str "one_line_break:"+                   , LineBreak+                   , Str "four_line_breaks:"+                   , LineBreak+                   , LineBreak+                   , LineBreak+                   , LineBreak+                   , Str "last_line"+                   ]+               ]+           ]+       ])+    [ TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [] ]+    (TableFoot ( "" , [] , [] ) [])+]+```
+ test/command/9805.md view
@@ -0,0 +1,10 @@+```+% pandoc -f rst -t native+word.*word+------------+* abc+^D+[ Header 1 ( "word.word" , [] , [] ) [ Str "word.*word" ]+, BulletList [ [ Plain [ Str "abc" ] ] ]+]+```
+ test/command/9807.md view
@@ -0,0 +1,13 @@+```+% pandoc -f typst -t native+#let foo = [+  bar baz+]+*#foo*+^D+[ Para+    [ Strong+        [ SoftBreak , Str "bar" , Space , Str "baz" , SoftBreak ]+    ]+]+```
+ test/command/9809.md view
@@ -0,0 +1,14 @@+```+% pandoc -f html -t native+<ul>+  <li>Bullet point.</li>+  <p>Nested line.</p>+</ul>+^D+[ BulletList+    [ [ Para [ Str "Bullet" , Space , Str "point." ]+      , Para [ Str "Nested" , Space , Str "line." ]+      ]+    ]+]+```
test/command/982.md view
@@ -7,5 +7,9 @@ y=x^2 \EEQ ^D-[ Para [ Math DisplayMath "y=x^2" ] ]+[ Para+    [ Math+        DisplayMath "\\begin{equation}\ny=x^2\n\\end{equation}"+    ]+] ```
+ test/command/9865.md view
@@ -0,0 +1,53 @@+````+% pandoc+- example 1+- ```+  one+  two+  ```+- list item three+^D+<ul>+<li>example 1</li>+<li><pre><code>one+two</code></pre></li>+<li>list item three</li>+</ul>+````++````+% pandoc+- example 3+- ```+one+two+```+- list item three+^D+<ul>+<li>example 3</li>+<li><pre><code>one+two</code></pre></li>+<li>list item three</li>+</ul>+````++Here is a case that we used to handle differently, but+#9865 aligns pandoc's markdown parser with commonmark in letting+block level structure take precedence over inline level structure.++````+% pandoc+- a <!--++- b++-->+- c+^D+<ul>+<li><p>a &lt;!–</p></li>+<li><p>b</p></li>+</ul>+<p>–&gt; - c</p>+````
+ test/command/9878.md view
@@ -0,0 +1,12 @@+```+% pandoc -f textile -t native+15% 50%+^D+[ Para [ Str "15%" , Space , Str "50%" ] ]+```+```+% pandoc -f textile -t native+15%. 70%+^D+[ Para [ Str "15%." , Space , Str "70%" ] ]+```
+ test/command/9902.md view
@@ -0,0 +1,6 @@+```+% pandoc -t native -f latex+raw_tex+\kern.1pt+^D+[ RawBlock (Format "latex") "\\kern.1pt" ]+```
+ test/command/9904.md view
@@ -0,0 +1,180 @@+```+% pandoc -f rst -t native --citeproc --bibliography command/biblio.bib+The axioms were introduced by :cite:t:`{see}item1`.+The axioms were introduced by :cite:t:`item1{p. 1166}`.+The axioms were introduced by :cite:t:`{see}item1{p. 1166}`.+Axioms were introduced :cite:`{see}item1`.+Axioms were introduced :cite:p:`item1{p. 1166}`.+Axioms were introduced :cite:p:`{see}item1{p. 1166}`.++.. bibliography::+^D+[ Para+    [ Str "The"+    , Space+    , Str "axioms"+    , Space+    , Str "were"+    , Space+    , Str "introduced"+    , Space+    , Str "by"+    , Space+    , Cite+        [ Citation+            { citationId = "item1"+            , citationPrefix = [ Str "see" ]+            , citationSuffix = []+            , citationMode = AuthorInText+            , citationNoteNum = 0+            , citationHash = 0+            }+        ]+        [ Str "(see" , Space , Str "Doe;" , Space , Str "2005)" ]+    , Str "."+    , SoftBreak+    , Str "The"+    , Space+    , Str "axioms"+    , Space+    , Str "were"+    , Space+    , Str "introduced"+    , Space+    , Str "by"+    , Space+    , Cite+        [ Citation+            { citationId = "item1"+            , citationPrefix = []+            , citationSuffix = [ Str "p." , Space , Str "1166" ]+            , citationMode = AuthorInText+            , citationNoteNum = 0+            , citationHash = 0+            }+        ]+        [ Str "Doe" , Space , Str "(2005," , Space , Str "1166)" ]+    , Str "."+    , SoftBreak+    , Str "The"+    , Space+    , Str "axioms"+    , Space+    , Str "were"+    , Space+    , Str "introduced"+    , Space+    , Str "by"+    , Space+    , Cite+        [ Citation+            { citationId = "item1"+            , citationPrefix = [ Str "see" ]+            , citationSuffix = [ Str "p." , Space , Str "1166" ]+            , citationMode = AuthorInText+            , citationNoteNum = 0+            , citationHash = 0+            }+        ]+        [ Str "(see"+        , Space+        , Str "Doe;"+        , Space+        , Str "2005,"+        , Space+        , Str "1166)"+        ]+    , Str "."+    , SoftBreak+    , Str "Axioms"+    , Space+    , Str "were"+    , Space+    , Str "introduced"+    , Space+    , Cite+        [ Citation+            { citationId = "item1"+            , citationPrefix = [ Str "see" ]+            , citationSuffix = []+            , citationMode = NormalCitation+            , citationNoteNum = 0+            , citationHash = 0+            }+        ]+        [ Str "(see" , Space , Str "Doe" , Space , Str "2005)" ]+    , Str "."+    , SoftBreak+    , Str "Axioms"+    , Space+    , Str "were"+    , Space+    , Str "introduced"+    , Space+    , Cite+        [ Citation+            { citationId = "item1"+            , citationPrefix = []+            , citationSuffix = [ Str "p." , Space , Str "1166" ]+            , citationMode = NormalCitation+            , citationNoteNum = 0+            , citationHash = 0+            }+        ]+        [ Str "(Doe" , Space , Str "2005," , Space , Str "1166)" ]+    , Str "."+    , SoftBreak+    , Str "Axioms"+    , Space+    , Str "were"+    , Space+    , Str "introduced"+    , Space+    , Cite+        [ Citation+            { citationId = "item1"+            , citationPrefix = [ Str "see" ]+            , citationSuffix = [ Str "p." , Space , Str "1166" ]+            , citationMode = NormalCitation+            , citationNoteNum = 0+            , citationHash = 0+            }+        ]+        [ Str "(see"+        , Space+        , Str "Doe"+        , Space+        , Str "2005,"+        , Space+        , Str "1166)"+        ]+    , Str "."+    ]+, Div+    ( "refs"+    , [ "references" , "csl-bib-body" , "hanging-indent" ]+    , []+    )+    [ Div+        ( "ref-item1" , [ "csl-entry" ] , [] )+        [ Para+            [ Str "Doe,"+            , Space+            , Str "John."+            , Space+            , Str "2005."+            , Space+            , Emph [ Str "First" , Space , Str "Book" ]+            , Str "."+            , Space+            , Str "Cambridge"+            , Space+            , Str "University"+            , Space+            , Str "Press."+            ]+        ]+    ]+]++```
+ test/command/9905.md view
@@ -0,0 +1,20 @@+```+% pandoc -t html5+# Section Ψ {#Ψ}++look at [Section Ψ](#Ψ).+^D+<h1 id="Ψ">Section Ψ</h1>+<p>look at <a href="#Ψ">Section Ψ</a>.</p>++```+```+% pandoc -t html4+# Section Ψ {#Ψ}++look at [Section Ψ](#Ψ).+^D+<h1 id="Ψ">Section Ψ</h1>+<p>look at <a href="#%CE%A8">Section Ψ</a>.</p>++```
+ test/command/9908.md view
@@ -0,0 +1,10 @@+```+% pandoc -f native -t markdown+[ BulletList+    [ [ BlockQuote [ Para [ Str "a" ] , Para [ Str "b" ] ] ] ]+]+^D+- > a+  >+  > b+```
+ test/command/9943.md view
@@ -0,0 +1,24 @@+```+% pandoc -t man -s -Vpandoc-version=X.Y+---+title: HELLO+section: 1+---+^D+.\" Automatically generated by Pandoc X.Y+.\"+.TH "HELLO" "1" "" ""+```++```+% pandoc -t man -s -Vpandoc-version=X.Y+---+title: HELLO+section: 1+header: Head+---+^D+.\" Automatically generated by Pandoc X.Y+.\"+.TH "HELLO" "1" "" "" "Head"+```
+ test/command/9945.md view
@@ -0,0 +1,28 @@+```+% pandoc -t typst --dpi 300+![](image.jpg){width=300 height=300}+^D+#box(image("image.jpg", height: 1in, width: 1in))+```++```+% pandoc -t typst --dpi 600+![](image.jpg){width=300px height=300px}+^D+#box(image("image.jpg", height: 0.5in, width: 0.5in))+```++```+% pandoc -t typst --dpi 600+![](image.jpg){width=1in height=3cm}+^D+#box(image("image.jpg", height: 3cm, width: 1in))+```+++```+% pandoc -t typst --dpi 600+![](image.jpg){.foo .bar baz=3}+^D+#box(image("image.jpg"))+```
+ test/command/9953.md view
@@ -0,0 +1,29 @@+```+% pandoc -f markdown -t native -s+---+header-includes: |+    \makeatletter+    \let\old@verbatim@font=\verbatim@font+    \def\verbatim@font{%+    \fontsize{10}{12}%+    \old@verbatim@font+    }+    \makeatother+...+^D+Pandoc+  Meta+    { unMeta =+        fromList+          [ ( "header-includes"+            , MetaBlocks+                [ RawBlock+                    (Format "tex")+                    "\\makeatletter\n\\let\\old@verbatim@font=\\verbatim@font\n\\def\\verbatim@font{%\n\\fontsize{10}{12}%\n\\old@verbatim@font\n}\n\\makeatother"+                ]+            )+          ]+    }+  []++```
+ test/command/9987.md view
@@ -0,0 +1,10 @@+```+% pandoc -f bibtex -t bibtex+@misc{agency,+  author = {{European Environment Agency}},+}+^D+@misc{agency,+  author = {{European Environment Agency}}+}+```
test/command/ascii.md view
@@ -17,7 +17,7 @@ äéıå ^D .PP-\[:a]\['e]\[.i]\[oa]+\(:a\('e\(.i\(oa ```  ```@@ -25,7 +25,7 @@ äéıå ^D .LP-\[:a]\['e]\[.i]\[oa]+\(:a\('e\(.i\(oa ```  ```
+ test/command/author-in-text-move-note.md view
@@ -0,0 +1,19 @@+```+% pandoc --citeproc --csl command/chicago-fullnote-bibliography.csl -t plain+---+references:+- id: foo+  type: book+  author: John Doe+  title: A Book+...++See @foo [p. 21], as well.+^D+See John Doe,[1] as well.++John Doe. A Book, n.d.++[1] A Book, n.d., 21.+```+
test/command/biblatex-angenendt.md view
@@ -50,7 +50,7 @@   author:   - family: Angenendt     given: Arnold-  container-title: Revue d'Histoire Ecclésiastique+  container-title: Revue d'Histoire Eccl[é]{.nocase}siastique   id: angenendt   issued: 2002   language: de-DE
test/command/biblatex-crossref-nested.md view
@@ -53,7 +53,7 @@   publisher: Publisher   publisher-place: Location   title: Macbeth \[title field of bookinbook-1\]-  type: chapter+  type: book   volume: 3   volume-title: Tragedies \[title field of book-1\] - author:
test/command/bits-title-supress.md view
@@ -45,7 +45,7 @@ ``` % pandoc -f jats -t native <sec>-	<title supress="no">The European Parliament</title>+	<title suppress="no">The European Parliament</title> 	<p>Members of the European Parliament (MEPs) are directly elected by EU citizens.</p> </sec> ^D@@ -89,7 +89,7 @@ ``` % pandoc -f jats -t native <sec>-	<title supress="yes">The European Parliament</title>+	<title suppress="yes">The European Parliament</title> 	<p>Members of the European Parliament (MEPs) are directly elected by EU citizens.</p> </sec> ^D
test/command/citeproc-87.md view
@@ -18,7 +18,7 @@ The Quoted is passed to citeproc as a Span ("",["csl-quoted"],[]) so that flipflopping and localization occur. ```-% pandoc -C -t plain -Mlang=en+% pandoc -C -t plain -Mlang=en --csl command/le-tapuscrit-note.csl --- references: - id: a@@ -30,13 +30,15 @@  Foo [@a 50]. ^D-Foo (Aristotele, n.d., 50).+Foo.[1] -Aristotele. n.d. “Metafisica Et ‘Physica’.”+ARISTOTELE, “Metafisica et ‘Physica’.”++[1] Aristotele, “Metafisica et ‘Physica’,” p. 50. ```  ```-% pandoc -C -t plain -Mlang=it+% pandoc -C -t plain -Mlang=it --csl command/le-tapuscrit-note.csl --- references: - id: a@@ -48,8 +50,10 @@  Foo [@a 50]. ^D-Foo (Aristotele, s.d., 50).+Foo.[1] -Aristotele. s.d. «Metafisica et “Physica”».+ARISTOTELE, «Metafisica et “Physica”».++[1] Aristotele, «Metafisica et “Physica”», p. 50. ``` 
+ test/command/dokuwiki-quote.md view
@@ -0,0 +1,16 @@+```+% pandoc -f dokuwiki -t native+> <code>some+code+</code>+>> ok+> then+> more+^D+[ BlockQuote+    [ CodeBlock ( "" , [] , [] ) "some\ncode\n"+    , BlockQuote [ Plain [ Str "ok" ] ]+    , Plain [ Str "then" , LineBreak , Str "more" ]+    ]+]+```
test/command/figures-mediawiki.md view
@@ -6,9 +6,6 @@  ^D <div id="fig-id" class="figure">- [[File:foo.png|thumb|none]]-- </div> ```
+ test/command/grid-table-indented.md view
@@ -0,0 +1,65 @@+Like other block-level constructs, grid tables may be indented by up to+three spaces and are still recognized as tables.++```+% pandoc -f markdown -t html+   +---+---++   | a | b |+   +===+===++   | 1 | 2 |+   +---+---++^D+<table style="width:11%;">+<colgroup>+<col style="width: 5%" />+<col style="width: 5%" />+</colgroup>+<thead>+<tr>+<th>a</th>+<th>b</th>+</tr>+</thead>+<tbody>+<tr>+<td>1</td>+<td>2</td>+</tr>+</tbody>+</table>+```++A headerless indented grid table is recognized too.++```+% pandoc -f markdown -t html+  +------+------++  | foo  | bar  |+  +------+------++^D+<table style="width:19%;">+<colgroup>+<col style="width: 9%" />+<col style="width: 9%" />+</colgroup>+<tbody>+<tr>+<td>foo</td>+<td>bar</td>+</tr>+</tbody>+</table>+```++A grid table indented four spaces is a code block, not a table.++```+% pandoc -f markdown -t html+    +---+---++    | a | b |+    +---+---++^D+<pre><code>+---+---++| a | b |++---+---+</code></pre>+```
+ test/command/jabberwocky.md view
@@ -0,0 +1,22 @@+```+% pandoc -t plain -f markdown+| 'Twas brillig, and the slithy toves+|       Did gyre and gimble in the wabe:+| All mimsy were the borogoves,+|       And the mome raths outgrabe.+|+| "Beware the Jabberwock, my son!+|       The jaws that bite, the claws that catch!+| Beware the Jubjub bird, and shun+|       The frumious Bandersnatch!"+^D+’Twas brillig, and the slithy toves+      Did gyre and gimble in the wabe:+All mimsy were the borogoves,+      And the mome raths outgrabe.++“Beware the Jabberwock, my son!+      The jaws that bite, the claws that catch!+Beware the Jubjub bird, and shun+      The frumious Bandersnatch!”+```
test/command/latex-color.md view
@@ -169,9 +169,12 @@ ^D [ Div     ( "" , [] , [ ( "style" , "background-color: orange" ) ] )-    [ BulletList-        [ [ Para [ Str "Item" , Space , Str "1" ] ]-        , [ Para [ Str "Item" , Space , Str "2" ] ]+    [ Div+        ( "" , [ "minipage" ] , [] )+        [ BulletList+            [ [ Para [ Str "Item" , Space , Str "1" ] ]+            , [ Para [ Str "Item" , Space , Str "2" ] ]+            ]         ]     ] ]@@ -190,9 +193,12 @@ ^D [ Div     ( "" , [] , [ ( "style" , "background-color: blue" ) ] )-    [ BulletList-        [ [ Para [ Str "Item" , Space , Str "1" ] ]-        , [ Para [ Str "Item" , Space , Str "2" ] ]+    [ Div+        ( "" , [ "minipage" ] , [] )+        [ BulletList+            [ [ Para [ Str "Item" , Space , Str "1" ] ]+            , [ Para [ Str "Item" , Space , Str "2" ] ]+            ]         ]     ] , Para
+ test/command/latex-math-trailing-space.md view
@@ -0,0 +1,38 @@+Test that trailing spaces before \end{equation} don't create spurious paragraph breaks:++```+% pandoc -f latex -t latex+\begin{equation}+  a+ \end{equation}+^D+\begin{equation}+  a+\end{equation}+```++Same for align environment:++```+% pandoc -f latex -t latex+\begin{align}+  x &= y \\+ \end{align}+^D+\begin{align}+  x &= y \\+\end{align}+```++Test with multiple trailing spaces:++```+% pandoc -f latex -t latex+\begin{equation}+  a + b+   \end{equation}+^D+\begin{equation}+  a + b+\end{equation}+```
test/command/lists-inside-definition.md view
@@ -12,10 +12,10 @@ \begin{description} \tightlist \item[Definition]+\hfill \begin{enumerate} \def\labelenumi{\arabic{enumi}.} \tightlist-\item[] \item   list \item@@ -33,6 +33,7 @@     2. list ^D \begin{description}+\tightlist \item[Definition] Foo @@ -56,9 +57,9 @@ \begin{description} \tightlist \item[Definition]+\hfill \begin{itemize} \tightlist-\item[] \item   list \item
test/command/macros.md view
@@ -61,9 +61,9 @@ ^D \(5-67\) -\[\begin{aligned}+\begin{align} x &= y\\-\end{aligned}\]+\end{align}  \emph{hi} 
+ test/command/man-defines.md view
@@ -0,0 +1,15 @@+```+% pandoc -f man -t plain+.de test+ok+..+.test+.br+\A'test'+.br+\A'xyz'+^D+ok+1+0+```
+ test/command/mdoc-An.md view
@@ -0,0 +1,17 @@+```+% pandoc -f mdoc -t plain+.Sh DESCRIPTION+.An Emily Brontë ,+.An Anne Brontë+.Pp+.An -split+.An Charlotte Brontë+.An Bramwell Brontë+^D+DESCRIPTION++Emily Brontë, Anne Brontë++Charlotte Brontë+Bramwell Brontë+```
+ test/command/mdoc-Bd-unfilled.md view
@@ -0,0 +1,24 @@+```+% pandoc -f mdoc -t plain+.Bd -unfilled+’Twas brillig, and the slithy toves+      Did gyre and gimble in the wabe:+All mimsy were the borogoves,+      And the mome raths outgrabe.++“Beware the Jabberwock, my son!+      The jaws that bite, the claws that catch!+Beware the Jubjub bird, and shun+      The frumious Bandersnatch!”+.Ed+^D+’Twas brillig, and the slithy toves+      Did gyre and gimble in the wabe:+All mimsy were the borogoves,+      And the mome raths outgrabe.++“Beware the Jabberwock, my son!+      The jaws that bite, the claws that catch!+Beware the Jubjub bird, and shun+      The frumious Bandersnatch!”+```
+ test/command/mdoc-Bl-column.md view
@@ -0,0 +1,22 @@+```+% pandoc -f mdoc -t djot+.Bl -column a b+.It a Ta+.Sy b+b+.Ta c+.Pp+.It c Ta d Ta \&+.It Em e+.Ta f+.Ta g+.It h Ta Ta j+.It Pq a Ta b Ta c+.El+^D+| a   | *b* b | c |+| c   | d     |   |+| _e_ | f     | g |+| h   |       | j |+| (a) | b     | c |+```
+ test/command/mdoc-Bl-tag.md view
@@ -0,0 +1,36 @@+```+% pandoc -f mdoc -t native+.Bl -tag+.It one+one+.It Xo+two+.Xc+two+.It Em three Xo+three+.Xc+three+.It Po one two+.Bq three+.Pc+four+.El+^D+[ DefinitionList+    [ ( [ Str "one" ] , [ [ Para [ Str "one" ] ] ] )+    , ( [ Str "two" ] , [ [ Para [ Str "two" ] ] ] )+    , ( [ Emph [ Str "three" ] , Space , Str "three" ]+      , [ [ Para [ Str "three" ] ] ]+      )+    , ( [ Str "(one"+        , Space+        , Str "two"+        , Space+        , Str "[three])"+        ]+      , [ [ Para [ Str "four" ] ] ]+      )+    ]+]+```
+ test/command/mediawiki_behavior_switches.md view
@@ -0,0 +1,16 @@+```+% pandoc -f mediawiki -t native+____INDEX____+__NOINDEX__+__noindex__+__FOOBAR__+^D+[ Para+    [ Str "____"+    , SoftBreak+    , Str "__noindex__"+    , SoftBreak+    , Str "__FOOBAR__"+    ]+]+```
test/command/pandoc-citeproc-118.md view
@@ -19,10 +19,9 @@ ^D (Hitchcock 1959) is a spy thriller film. -:::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+:::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-nbn .csl-entry}-Hitchcock, Alfred, dir. 1959. *North by Northwest*. USA:-Metro-Goldwyn-Mayer.+Hitchcock, Alfred, dir. 1959. *North by Northwest*. Metro-Goldwyn-Mayer. ::: :::: ```
test/command/pandoc-citeproc-136.md view
@@ -15,7 +15,7 @@ ^D *Stanze in lode della donna brutta* (1547) is an anoynymous work. -:::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+:::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-stanze .csl-entry} *Stanze in lode della donna brutta*. 1547. Florence. :::
test/command/pandoc-citeproc-14.md view
@@ -51,27 +51,27 @@ References {#references .unnumbered} ========== ^D-Foo (Pelikan 1971b, 1:12). Bar (Pelikan 1971c, 1:12). Baz (Pelikan-1971a, 12).+Foo (Pelikan 1971b, 1:12). Bar (Pelikan 1971c, 12). Baz (Pelikan 1971a,+12).  # References {#references .unnumbered} -:::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+:::::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-CTv1c2 .csl-entry}-Pelikan, Jaroslav. 1971a. "Chapter Two." In *The Christian Tradition: A-History of the Development of Doctrine*, 1:34--56. Chicago: University-of Chicago Press.+Pelikan, Jaroslav. 1971a. "Chapter Two." In *The Emergence of the+Catholic Tradition (100--600)*, vol. 1 of *The Christian Tradition: A+History of the Development of Doctrine*. University of Chicago Press. :::  ::: {#ref-CT .csl-entry}----------. 1971b. *The Christian Tradition: A History of the Development-of Doctrine*. Chicago: University of Chicago Press.+Pelikan, Jaroslav. 1971b. *The Christian Tradition: A History of the+Development of Doctrine*. University of Chicago Press. :::  ::: {#ref-CTv1 .csl-entry}----------. 1971c. *The Emergence of the Catholic Tradition (100--600)*.-*The Christian Tradition: A History of the Development of Doctrine*.-Vol. 1. Chicago: University of Chicago Press.+Pelikan, Jaroslav. 1971c. *The Emergence of the Catholic Tradition+(100--600)*. In *The Christian Tradition: A History of the Development+of Doctrine*, vol. 1. University of Chicago Press. ::: :::::: ```
test/command/pandoc-citeproc-175.md view
@@ -35,9 +35,9 @@  > Doe, Jane. 2011. "A Title." *A Magazine*, January--February. -:::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+:::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-item1 .csl-entry}-Doe, Jane. 2011. "A Title." *A Magazine*, January--February 2011.+Doe, Jane. 2011. "A Title." *A Magazine*, January--February, 33--44. ::: :::: ```
test/command/pandoc-citeproc-25.md view
@@ -22,9 +22,9 @@  # References {#references .unnumbered} -:::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+:::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-item1 .csl-entry}-Author, Al. 1998. "Foo Bar Baz: Bazbaz Foo."+Author, Al. 1998. *Foo Bar Baz: Bazbaz Foo*. ::: :::: ```
test/command/pandoc-citeproc-250.md view
@@ -13,9 +13,9 @@ ^D ([Doe, n.d.](#ref-doe)) -:::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+:::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-doe .csl-entry}-Doe. n.d. "Title."+Doe. n.d. *Title*. ::: :::: ```
test/command/pandoc-citeproc-301.md view
@@ -10,16 +10,16 @@  @test; @test2 ^D-"Essays Presented to N.R. Ker (On Art)" (n.d.); "*Test:* An Experiment:-An Abridgement" (n.d.)+*Essays Presented to N.R. Ker (On Art)* (n.d.); **Test:* An Experiment:+An Abridgement* (n.d.) -::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+::::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-test .csl-entry}-"Essays Presented to N.R. Ker (On Art)." n.d.+*Essays Presented to N.R. Ker (On Art)*. n.d. :::  ::: {#ref-test2 .csl-entry}-"*Test:* An Experiment: An Abridgement." n.d.+**Test:* An Experiment: An Abridgement*. n.d. ::: ::::: ```
test/command/pandoc-citeproc-307.md view
@@ -22,7 +22,7 @@ ^D Bonjour(Bazin 1954) ! -:::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+:::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-bazin_cybernetique_1954 .csl-entry} Bazin, André. 1954. « La Cybernétique d'André Cayatte ». *Cahiers du cinéma*, nᵒ 36 (juin): 22‑27.
test/command/pandoc-citeproc-320a.md view
@@ -1,87 +1,80 @@ ```-% pandoc --citeproc -t markdown-citations+% pandoc --citeproc -t plain --- references: - author:   - family: ʾUdhrī     given: Jamīl     non-dropping-particle: 'al-'-    note: ayn+  issued: 2000+  title: hamza   id: item1 - author:   - family: ʿUdhrī     given: Jamīl     non-dropping-particle: 'al-'-    note: hamza+  issued: 2000+  title: ayn   id: item2 - author:-  - family: '\''Udhrī'+  - family: "'Udhrī"     given: Jamīl     non-dropping-particle: 'al-'-    note: straight apostrophe+  issued: 2000+  title: straight apostrophe   id: item3 - author:   - family: '‘Udhrī'     given: Jamīl     non-dropping-particle: 'al-'-    note: inverted apostrophe = opening single curly quote (for ayn)+  issued: 2000+  title: inverted curly apostrophe = opening single curly quote (for ayn)   id: item4 - author:   - family: '’Udhrī'     given: Jamīl     non-dropping-particle: 'al-'-    note: apostrophe = closing single curly quote (for hamza)+  issued: 2000+  title: curly apostrophe = closing single curly quote (for hamza)   id: item5 - author:   - family: Uch     given: Ann   id: item6+  issued: 2000 - author:   - family: Uebel     given: Joe   id: item7+  issued: 2000 - author:   - family: Zzz     given: Zoe   id: item8+  issued: 2000 ---  Foo [@item1; @item2; @item3; @item4; @item5; @item6; @item7; @item8]. ^D-Foo (al-ʾUdhrī, n.d.; al-ʿUdhrī, n.d.; al-\'Udhrī, n.d.; al-'Udhrī,-n.d.a, n.d.b; Uch, n.d.; Uebel, n.d.; Zzz, n.d.).+Foo (al-ʾUdhrī 2000; al-ʿUdhrī 2000; al-’Udhrī 2000b, 2000a; al-‘Udhrī+2000; Uch 2000; Uebel 2000; Zzz 2000). -::::::::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}-::: {#ref-item6 .csl-entry}-Uch, Ann. n.d.-:::+Uch, Ann. 2000. -::: {#ref-item1 .csl-entry}-ʾUdhrī, Jamīl al-. n.d.-:::+‘Udhrī, Jamīl al-. 2000. Inverted Curly Apostrophe = Opening Single+Curly Quote (for Ayn). -::: {#ref-item2 .csl-entry}-ʿUdhrī, Jamīl al-. n.d.-:::+ʿUdhrī, Jamīl al-. 2000. Ayn. -::: {#ref-item3 .csl-entry}-\'Udhrī, Jamīl al-. n.d.-:::+’Udhrī, Jamīl al-. 2000a. Curly Apostrophe = Closing Single Curly Quote+(for Hamza). -::: {#ref-item4 .csl-entry}-'Udhrī, Jamīl al-. n.d.a.-:::+ʾUdhrī, Jamīl al-. 2000. Hamza. -::: {#ref-item5 .csl-entry}----------. n.d.b.-:::+’Udhrī, Jamīl al-. 2000b. Straight Apostrophe. -::: {#ref-item7 .csl-entry}-Uebel, Joe. n.d.-:::+Uebel, Joe. 2000. -::: {#ref-item8 .csl-entry}-Zzz, Zoe. n.d.-:::-:::::::::::+Zzz, Zoe. 2000.+ ```
test/command/pandoc-citeproc-325.md view
@@ -16,15 +16,15 @@  [@item1; @item2] ^D-(Smith, n.d.a, n.d.b)+(Smith, n.d.-a, n.d.-b) -::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+::::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-item1 .csl-entry}-Smith, John. n.d.a.+Smith, John. n.d.-a. :::  ::: {#ref-item2 .csl-entry}----------. n.d.b.+Smith, John. n.d.-b. ::: ::::: ```
test/command/pandoc-citeproc-327.md view
@@ -45,7 +45,7 @@ ::: {#ref-LiLiaoDongWanHaiYuDiQiDongWuCiJiShengChanLiYanJiuJiShengJingGuaYiXingPingJie2017 .csl-entry} [\[1\] ]{.csl-left-margin}[李轶平, 于旭光, 孙明, 等. [辽东湾海域底栖动物次级生产力研究及生境适宜性评价](http://kns.cnki.net/kns/detail/detail.aspx?QueryID=4&CurRec=4&recid=&FileName=CHAN201706006&DbName=CJFDLAST2018&DbCode=CJFQ&yx=Y&pr=&URLID=21.1110.S.20171129.1725.006)\[J\].-水产科学, 2017(6): 728--734.]{.csl-right-inline}+水产科学, 2017(6): 728~734.]{.csl-right-inline} ::: :::: ```
test/command/pandoc-citeproc-371.md view
@@ -28,13 +28,13 @@  # References {#references .unnumbered} -::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+::::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-item2 .csl-entry} Doe, Jane. 2018. *Title Two*. :::  ::: {#ref-item1 .csl-entry}----------. In press. *Title One*.+Doe, Jane. In press. *Title One*. ::: ::::: ```
test/command/pandoc-citeproc-38.md view
@@ -19,11 +19,11 @@  @a ^D-Doe, Doe, and Roe (2007)+Doe et al. (2007) -:::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+:::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-a .csl-entry}-Doe, Ann, Ben Doe, and Ron Roe. 2007. "Title."+Doe, Ann, Ben Doe, and Ron Roe. 2007. *Title*. ::: :::: ```
test/command/pandoc-citeproc-401.md view
@@ -43,17 +43,17 @@ ^D Haslanger (\[2003\] 2012, \[2000\] 2012) says... -::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+::::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-haslanger2012FeminismMetaphysicsNegotiating .csl-entry} Haslanger, Sally. (2000) 2012. "Feminism in Metaphysics: Negotiating the Natural." In *Resisting Reality: Social Construction and Social-Critique*, 139--57. Oxford: Oxford University Press.+Critique*. Oxford University Press. :::  ::: {#ref-haslanger2012SocialConstructionDebunking .csl-entry}----------. (2003) 2012. "Social Construction: The 'Debunking' Project."-In *Resisting Reality: Social Construction and Social Critique*,-113--38. Oxford: Oxford University Press.+Haslanger, Sally. (2003) 2012. "Social Construction: The 'Debunking'+Project." In *Resisting Reality: Social Construction and Social+Critique*. Oxford University Press. ::: ::::: ```
test/command/pandoc-citeproc-408.md view
@@ -27,13 +27,13 @@ ^D (Smith and Smith 2019; Smith 2019) -::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+::::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-smith1 .csl-entry}-Smith, Mary. 2019. "Foo."+Smith, Mary. 2019. *Foo*. :::  ::: {#ref-smithsmith .csl-entry}-Smith, Mary, and John Smith. 2019. "Foo Bar."+Smith, Mary, and John Smith. 2019. *Foo Bar*. ::: ::::: ```
test/command/pandoc-citeproc-416.md view
@@ -44,17 +44,17 @@  # References {#references .unnumbered} -:::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+:::::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-item2 .csl-entry}-Doe, J. 2007. "The Title," December 12--13, 2007.+Doe, J. 2007. *The Title*. December 12--13. :::  ::: {#ref-item3 .csl-entry}----------. 2008. "The Title," 2008.+Doe, J. 2008. *The Title*. :::  ::: {#ref-item1 .csl-entry}----------. 2010. "The Title," December 13, 2010.+Doe, J. 2010. *The Title*. December 13. ::: :::::: ```
test/command/pandoc-citeproc-47.md view
@@ -69,8 +69,8 @@ References {#references .unnumbered} ========== ^D-Foo (Doe 2000a). Bar (Doe and Poe 2000). Foo (Doe 2000b). Bar (Doe, Loe,-and Toe 2000).+Foo (Doe 2000a). Bar (Doe and Poe 2000). Foo (Doe 2000b). Bar (Doe et+al. 2000).  Expected output: @@ -92,13 +92,13 @@  # References {#references .unnumbered} -::::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+::::::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-doe .csl-entry} Doe, A. 2000a. *Title*. :::  ::: {#ref-doe-ed .csl-entry}----------, ed. 2000b. *Title*.+Doe, A., ed. 2000b. *Title*. :::  ::: {#ref-doeloetoe .csl-entry}
test/command/pandoc-citeproc-51.md view
@@ -33,7 +33,7 @@ ^D Doe (1987--1988); Roe (1987) -::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+::::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-item1 .csl-entry} Doe, John. 1987--1988. "The Title." *Journal of Something* 3: 12--34. :::
test/command/pandoc-citeproc-64.md view
@@ -1,5 +1,5 @@ ```-% pandoc --citeproc -t markdown-citations+% pandoc --citeproc -t markdown-citations --csl command/chicago-fullnote-bibliography.csl --- bibliography: - command/biblio.bib@@ -8,17 +8,17 @@  ^D :::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}-::: {#ref-item1 .csl-entry}-Doe, John. 2005. *First Book*. Cambridge: Cambridge University Press.+::: {#ref-item2 .csl-entry}+Doe, John. "Article." *Journal of Generic Studies* 6 (2006): 33--34. ::: -::: {#ref-item2 .csl-entry}----------. 2006. "Article." *Journal of Generic Studies* 6: 33--34.+::: {#ref-item1 .csl-entry}+---------. *First Book*. Cambridge: Cambridge University Press, 2005. :::  ::: {#ref-пункт3 .csl-entry}-Doe, John, and Jenny Roe. 2007. "Why Water Is Wet." In *Third Book*,-edited by Sam Smith. Oxford: Oxford University Press.+Doe, John, and Jenny Roe. "Why Water Is Wet." In *Third Book*, edited by+Sam Smith. Oxford: Oxford University Press, 2007. ::: :::::: ```
test/command/pandoc-citeproc-65.md view
@@ -28,11 +28,10 @@ ^D (Stotz 1996--2004) -:::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+:::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-stotz:1996handbuch .csl-entry} Stotz, Peter. 1996--2004. *Handbuch zur lateinischen Sprache des-Mittelalters*. 5 vols. Handbuch der Altertumswissenschaft 2.5. Munich:-Beck.+Mittelalters*. 5 vols. Handbuch der Altertumswissenschaft, 2.5. Beck. ::: :::: ```
test/command/pandoc-citeproc-7.md view
@@ -23,9 +23,9 @@ ^D Author (2011) -:::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+:::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-item1 .csl-entry}-Author, Ann. 2011. "Title." *Journal*, September 24--26, 2011.+Author, Ann. 2011. "Title." *Journal*, September 24--26. ::: :::: ```
test/command/pandoc-citeproc-70.md view
@@ -56,14 +56,14 @@ ^D (Thorndike 1955; Dinkova-Bruun 2009) -::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+::::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-bruun:2009samuel .csl-entry} Dinkova-Bruun, Greti. 2009. "Samuel Presbyter and the Glosses to His Versification of Psalm 1: An Anti-Church Invective?" In *Florilegium mediaevale: Études offertes à Jacqueline Hamesse à l'occasion de son-éméritat*, edited by José Francisco Meirinhos and Olga Weijers, 155--74.-Textes et études du moyen âge 50. Louvain-la-Neuve: Fédération-Internationale des Instituts d'Études Médiévales.+éméritat*, edited by José Francisco Meirinhos and Olga Weijers. Textes+et études du moyen âge 50. Fédération Internationale des Instituts+d'Études Médiévales. :::  ::: {#ref-thorndike:1955unde .csl-entry}
test/command/pandoc-citeproc-76.md view
@@ -44,21 +44,21 @@ ^D Author (1998c), Author (1998d), Author (1998a), Author (1998b) -::::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+::::::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-item3 .csl-entry}-Author, Al. 1998a. "Foo Bar Baz: A Bazbaz Bar Foo."+Author, Al. 1998a. *Foo Bar Baz: A Bazbaz Bar Foo*. :::  ::: {#ref-item4 .csl-entry}----------. 1998b. "Foo Bar Baz: An Abazbaz Bar Foo."+Author, Al. 1998b. *Foo Bar Baz: An Abazbaz Bar Foo*. :::  ::: {#ref-item1 .csl-entry}----------. 1998c. "Foo Bar Baz: Bazbaz Bar Foo."+Author, Al. 1998c. *Foo Bar Baz: Bazbaz Bar Foo*. :::  ::: {#ref-item2 .csl-entry}----------. 1998d. "Foo Bar Baz: The Bazbaz Bar Foo."+Author, Al. 1998d. *Foo Bar Baz: The Bazbaz Bar Foo*. ::: ::::::: ```
test/command/pandoc-citeproc-87.md view
@@ -108,49 +108,49 @@ References ========== ^D-Doe (2006c) -- webpage, date+Doe (2006a) -- webpage, date -Doe (2006d) -- webpage, date range+Doe (2006c) -- webpage, date range -Doe (2006a) -- webpage, date range YM+Doe (2006b) -- webpage, date range YM  Doe (2006--2007) -- webpage, date range across years  Doe (2006e) -- article-newspaper -Doe (2006b) -- article-newspaper YM+Doe (2006d) -- article-newspaper YM  # References {#references .unnumbered} -::::::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}-::: {#ref-item2a .csl-entry}-Doe, John. 2006a. "Title." The Web Site. October--November 2006.+::::::::: {#refs .references .csl-bib-body .hanging-indent}+::: {#ref-item1 .csl-entry}+Doe, John. 2006a. "Title." The Web Site, October 26. <http://www.example.com>. ::: -::: {#ref-item3b .csl-entry}----------. 2006b. "Title." *The Newspaper*, October--November 2006.+::: {#ref-item2a .csl-entry}+Doe, John. 2006b. "Title." The Web Site, October--November. <http://www.example.com>. ::: -::: {#ref-item1 .csl-entry}----------. 2006c. "Title." The Web Site. October 26, 2006.+::: {#ref-item2 .csl-entry}+Doe, John. 2006c. "Title." The Web Site, October 26--November 27. <http://www.example.com>. ::: -::: {#ref-item2 .csl-entry}----------. 2006d. "Title." The Web Site. October 26--November 27, 2006.+::: {#ref-item3b .csl-entry}+Doe, John. 2006d. "Title." *The Newspaper*, October--November. <http://www.example.com>. :::  ::: {#ref-item3 .csl-entry}----------. 2006e. "Title." *The Newspaper*, October 26--November 27,-2006. <http://www.example.com>.+Doe, John. 2006e. "Title." *The Newspaper*, October 26--November 27.+<http://www.example.com>. :::  ::: {#ref-item2b .csl-entry}----------. 2006--2007. "Title." The Web Site. December 31, 2006--January-1, 2007. <http://www.example.com>.+Doe, John. 2006--2007. "Title." The Web Site, December 31--January 1.+<http://www.example.com>. ::: ::::::::: ```
test/command/pandoc-citeproc-chicago-author-date.md view
@@ -83,18 +83,18 @@  # References {#references .unnumbered} -:::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+:::::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-item1 .csl-entry}-Doe, John. 2005. *First Book*. Cambridge: Cambridge University Press.+Doe, John. 2005. *First Book*. Cambridge University Press. :::  ::: {#ref-item2 .csl-entry}----------. 2006. "Article." *Journal of Generic Studies* 6: 33--34.+Doe, John. 2006. "Article." *Journal of Generic Studies* 6: 33--34. :::  ::: {#ref-пункт3 .csl-entry} Doe, John, and Jenny Roe. 2007. "Why Water Is Wet." In *Third Book*,-edited by Sam Smith. Oxford: Oxford University Press.+edited by Sam Smith. Oxford University Press. ::: :::::: 
test/command/pandoc-citeproc-no-author.md view
@@ -45,29 +45,29 @@ *Magazine* (2012a, 3), *Magazine* (2012b), *Magazine* (2012c), *Magazine* (2012d), *Newspaper* (2012a), *Newspaper* (2012b) -::::::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+::::::::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-item1 .csl-entry}-*Magazine*. 2012a. "Title A," 2012.+*Magazine*. 2012a. "Title A." :::  ::: {#ref-item2 .csl-entry}----------. 2012b. "Title B," 2012.+*Magazine*. 2012b. "Title B." :::  ::: {#ref-item3 .csl-entry}----------. 2012c. "Title C," 2012.+*Magazine*. 2012c. "Title C." :::  ::: {#ref-item4 .csl-entry}----------. 2012d. "Title D," 2012.+*Magazine*. 2012d. "Title D." :::  ::: {#ref-item5 .csl-entry}-*Newspaper*. 2012a. "Title E," 2012.+*Newspaper*. 2012a. "Title E." :::  ::: {#ref-item6 .csl-entry}----------. 2012b. "Title F," 2012.+*Newspaper*. 2012b. "Title F." ::: ::::::::: ```
test/command/pandoc-citeproc-number-of-volumes.md view
@@ -21,9 +21,9 @@ ^D Author (2013) -:::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+:::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-item1 .csl-entry}-Author, Al. 2013. *Title*. 2 vols. Location: Publisher.+Author, Al. 2013. *Title*. 2 vols. Publisher. ::: :::: ```
+ test/command/pdfstandard.md view
@@ -0,0 +1,616 @@+PDF standard support: basic PDF/A-2b test (infers version 1.7)+```+% pandoc -t latex -s+---+pdfstandard: a-2b+lang: en-US+---++Test document.+^D+\DocumentMetadata{+  pdfversion=1.7,+  pdfstandard={a-2b},+  lang=en-US,+  xmp=true}+% Options for packages loaded elsewhere+\PassOptionsToPackage{unicode}{hyperref}+\PassOptionsToPackage{hyphens}{url}+\documentclass[+  american,+]{article}+\usepackage{xcolor}+\usepackage{amsmath,amssymb}+\setcounter{secnumdepth}{-\maxdimen} % remove section numbering+\usepackage{iftex}+\ifPDFTeX+  \usepackage[T1]{fontenc}+  \usepackage[utf8]{inputenc}+  \usepackage{textcomp} % provide euro and other symbols+\else % if luatex or xetex+  \usepackage{unicode-math} % this also loads fontspec+  \defaultfontfeatures{Scale=MatchLowercase}+  \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1}+\fi+\usepackage{lmodern}+\ifPDFTeX\else+  % xetex/luatex font selection+\fi+% Use upquote if available, for straight quotes in verbatim environments+\IfFileExists{upquote.sty}{\usepackage{upquote}}{}+\IfFileExists{microtype.sty}{% use microtype if available+  \usepackage[]{microtype}+  \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts+}{}+\makeatletter+\@ifundefined{KOMAClassName}{% if non-KOMA class+  \IfFileExists{parskip.sty}{%+    \usepackage{parskip}+  }{% else+    \setlength{\parindent}{0pt}+    \setlength{\parskip}{6pt plus 2pt minus 1pt}}+}{% if KOMA class+  \KOMAoptions{parskip=half}}+\makeatother+\ifLuaTeX+\usepackage[bidi=basic,shorthands=off]{babel}+\else+\usepackage[bidi=default,shorthands=off]{babel}+\fi+\ifLuaTeX+  \usepackage{selnolig} % disable illegal ligatures+\fi+\setlength{\emergencystretch}{3em} % prevent overfull lines+\providecommand{\tightlist}{%+  \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}+\usepackage{bookmark}+\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available+\urlstyle{same}+% fallback for those not using the hyperref driver hyperxmp:+\makeatletter+\@ifundefined{xmpquote}{\newcommand{\xmpquote}[1]{#1}}{}+\makeatother+\hypersetup{+  pdflang={en-US},+  hidelinks,+  pdfcreator={LaTeX via pandoc}}++\author{}+\date{}++\begin{document}++Test document.++\end{document}+```++PDF standard support: PDF/UA-1 with tagging+```+% pandoc -t latex -s+---+pdfstandard: ua-1+lang: en-US+---++Accessible document.+^D+\DocumentMetadata{+  pdfstandard={ua-1},+  tagging=on,+  lang=en-US,+  xmp=true}+% Options for packages loaded elsewhere+\PassOptionsToPackage{unicode}{hyperref}+\PassOptionsToPackage{hyphens}{url}+\documentclass[+  american,+]{article}+\usepackage{xcolor}+\usepackage{amsmath,amssymb}+\setcounter{secnumdepth}{-\maxdimen} % remove section numbering+\usepackage{iftex}+\ifPDFTeX+  \usepackage[T1]{fontenc}+  \usepackage[utf8]{inputenc}+  \usepackage{textcomp} % provide euro and other symbols+\else % if luatex or xetex+  \usepackage{unicode-math} % this also loads fontspec+  \defaultfontfeatures{Scale=MatchLowercase}+  \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1}+\fi+\usepackage{lmodern}+\ifPDFTeX\else+  % xetex/luatex font selection+\fi+% Use upquote if available, for straight quotes in verbatim environments+\IfFileExists{upquote.sty}{\usepackage{upquote}}{}+\IfFileExists{microtype.sty}{% use microtype if available+  \usepackage[]{microtype}+  \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts+}{}+\makeatletter+\@ifundefined{KOMAClassName}{% if non-KOMA class+  \IfFileExists{parskip.sty}{%+    \usepackage{parskip}+  }{% else+    \setlength{\parindent}{0pt}+    \setlength{\parskip}{6pt plus 2pt minus 1pt}}+}{% if KOMA class+  \KOMAoptions{parskip=half}}+\makeatother+\ifLuaTeX+\usepackage[bidi=basic,shorthands=off]{babel}+\else+\usepackage[bidi=default,shorthands=off]{babel}+\fi+\ifLuaTeX+  \usepackage{selnolig} % disable illegal ligatures+\fi+\setlength{\emergencystretch}{3em} % prevent overfull lines+\providecommand{\tightlist}{%+  \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}+\usepackage{bookmark}+\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available+\urlstyle{same}+% fallback for those not using the hyperref driver hyperxmp:+\makeatletter+\@ifundefined{xmpquote}{\newcommand{\xmpquote}[1]{#1}}{}+\makeatother+\hypersetup{+  pdflang={en-US},+  hidelinks,+  pdfcreator={LaTeX via pandoc}}++\author{}+\date{}++\begin{document}++Accessible document.++\end{document}+```++PDF standard support: multiple standards with version+```+% pandoc -t latex -s+---+pdfstandard:+  - a-2b+  - ua-1+  - "1.7"+lang: de-DE+---++Multi-standard document.+^D+\DocumentMetadata{+  pdfversion=1.7,+  pdfstandard={a-2b,ua-1},+  tagging=on,+  lang=de-DE,+  xmp=true}+% Options for packages loaded elsewhere+\PassOptionsToPackage{unicode}{hyperref}+\PassOptionsToPackage{hyphens}{url}+\documentclass[+  ngerman,+]{article}+\usepackage{xcolor}+\usepackage{amsmath,amssymb}+\setcounter{secnumdepth}{-\maxdimen} % remove section numbering+\usepackage{iftex}+\ifPDFTeX+  \usepackage[T1]{fontenc}+  \usepackage[utf8]{inputenc}+  \usepackage{textcomp} % provide euro and other symbols+\else % if luatex or xetex+  \usepackage{unicode-math} % this also loads fontspec+  \defaultfontfeatures{Scale=MatchLowercase}+  \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1}+\fi+\usepackage{lmodern}+\ifPDFTeX\else+  % xetex/luatex font selection+\fi+% Use upquote if available, for straight quotes in verbatim environments+\IfFileExists{upquote.sty}{\usepackage{upquote}}{}+\IfFileExists{microtype.sty}{% use microtype if available+  \usepackage[]{microtype}+  \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts+}{}+\makeatletter+\@ifundefined{KOMAClassName}{% if non-KOMA class+  \IfFileExists{parskip.sty}{%+    \usepackage{parskip}+  }{% else+    \setlength{\parindent}{0pt}+    \setlength{\parskip}{6pt plus 2pt minus 1pt}}+}{% if KOMA class+  \KOMAoptions{parskip=half}}+\makeatother+\ifLuaTeX+\usepackage[bidi=basic,shorthands=off]{babel}+\else+\usepackage[bidi=default,shorthands=off]{babel}+\fi+\ifLuaTeX+  \usepackage{selnolig} % disable illegal ligatures+\fi+\setlength{\emergencystretch}{3em} % prevent overfull lines+\providecommand{\tightlist}{%+  \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}+\usepackage{bookmark}+\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available+\urlstyle{same}+% fallback for those not using the hyperref driver hyperxmp:+\makeatletter+\@ifundefined{xmpquote}{\newcommand{\xmpquote}[1]{#1}}{}+\makeatother+\hypersetup{+  pdflang={de-DE},+  hidelinks,+  pdfcreator={LaTeX via pandoc}}++\author{}+\date{}++\begin{document}++Multi-standard document.++\end{document}+```++PDF standard support: PDF/A-1b infers version 1.4+```+% pandoc -t latex -s+---+pdfstandard: a-1b+lang: en-US+---++PDF/A-1 document.+^D+\DocumentMetadata{+  pdfversion=1.4,+  pdfstandard={a-1b},+  lang=en-US,+  xmp=true}+% Options for packages loaded elsewhere+\PassOptionsToPackage{unicode}{hyperref}+\PassOptionsToPackage{hyphens}{url}+\documentclass[+  american,+]{article}+\usepackage{xcolor}+\usepackage{amsmath,amssymb}+\setcounter{secnumdepth}{-\maxdimen} % remove section numbering+\usepackage{iftex}+\ifPDFTeX+  \usepackage[T1]{fontenc}+  \usepackage[utf8]{inputenc}+  \usepackage{textcomp} % provide euro and other symbols+\else % if luatex or xetex+  \usepackage{unicode-math} % this also loads fontspec+  \defaultfontfeatures{Scale=MatchLowercase}+  \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1}+\fi+\usepackage{lmodern}+\ifPDFTeX\else+  % xetex/luatex font selection+\fi+% Use upquote if available, for straight quotes in verbatim environments+\IfFileExists{upquote.sty}{\usepackage{upquote}}{}+\IfFileExists{microtype.sty}{% use microtype if available+  \usepackage[]{microtype}+  \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts+}{}+\makeatletter+\@ifundefined{KOMAClassName}{% if non-KOMA class+  \IfFileExists{parskip.sty}{%+    \usepackage{parskip}+  }{% else+    \setlength{\parindent}{0pt}+    \setlength{\parskip}{6pt plus 2pt minus 1pt}}+}{% if KOMA class+  \KOMAoptions{parskip=half}}+\makeatother+\ifLuaTeX+\usepackage[bidi=basic,shorthands=off]{babel}+\else+\usepackage[bidi=default,shorthands=off]{babel}+\fi+\ifLuaTeX+  \usepackage{selnolig} % disable illegal ligatures+\fi+\setlength{\emergencystretch}{3em} % prevent overfull lines+\providecommand{\tightlist}{%+  \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}+\usepackage{bookmark}+\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available+\urlstyle{same}+% fallback for those not using the hyperref driver hyperxmp:+\makeatletter+\@ifundefined{xmpquote}{\newcommand{\xmpquote}[1]{#1}}{}+\makeatother+\hypersetup{+  pdflang={en-US},+  hidelinks,+  pdfcreator={LaTeX via pandoc}}++\author{}+\date{}++\begin{document}++PDF/A-1 document.++\end{document}+```++PDF standard support: PDF/A-4 with no version inference (uses default 2.0)+```+% pandoc -t latex -s+---+pdfstandard: a-4+lang: en-US+---++PDF/A-4 document.+^D+\DocumentMetadata{+  pdfstandard={a-4},+  lang=en-US,+  xmp=true}+% Options for packages loaded elsewhere+\PassOptionsToPackage{unicode}{hyperref}+\PassOptionsToPackage{hyphens}{url}+\documentclass[+  american,+]{article}+\usepackage{xcolor}+\usepackage{amsmath,amssymb}+\setcounter{secnumdepth}{-\maxdimen} % remove section numbering+\usepackage{iftex}+\ifPDFTeX+  \usepackage[T1]{fontenc}+  \usepackage[utf8]{inputenc}+  \usepackage{textcomp} % provide euro and other symbols+\else % if luatex or xetex+  \usepackage{unicode-math} % this also loads fontspec+  \defaultfontfeatures{Scale=MatchLowercase}+  \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1}+\fi+\usepackage{lmodern}+\ifPDFTeX\else+  % xetex/luatex font selection+\fi+% Use upquote if available, for straight quotes in verbatim environments+\IfFileExists{upquote.sty}{\usepackage{upquote}}{}+\IfFileExists{microtype.sty}{% use microtype if available+  \usepackage[]{microtype}+  \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts+}{}+\makeatletter+\@ifundefined{KOMAClassName}{% if non-KOMA class+  \IfFileExists{parskip.sty}{%+    \usepackage{parskip}+  }{% else+    \setlength{\parindent}{0pt}+    \setlength{\parskip}{6pt plus 2pt minus 1pt}}+}{% if KOMA class+  \KOMAoptions{parskip=half}}+\makeatother+\ifLuaTeX+\usepackage[bidi=basic,shorthands=off]{babel}+\else+\usepackage[bidi=default,shorthands=off]{babel}+\fi+\ifLuaTeX+  \usepackage{selnolig} % disable illegal ligatures+\fi+\setlength{\emergencystretch}{3em} % prevent overfull lines+\providecommand{\tightlist}{%+  \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}+\usepackage{bookmark}+\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available+\urlstyle{same}+% fallback for those not using the hyperref driver hyperxmp:+\makeatletter+\@ifundefined{xmpquote}{\newcommand{\xmpquote}[1]{#1}}{}+\makeatother+\hypersetup{+  pdflang={en-US},+  hidelinks,+  pdfcreator={LaTeX via pandoc}}++\author{}+\date{}++\begin{document}++PDF/A-4 document.++\end{document}+```++PDF standard support: numeric YAML version (2 becomes 2.0)+```+% pandoc -t latex -s+---+pdfstandard:+  - ua-1+  - 2+lang: en-US+---++PDF 2.0 document.+^D+\DocumentMetadata{+  pdfversion=2.0,+  pdfstandard={ua-1},+  tagging=on,+  lang=en-US,+  xmp=true}+% Options for packages loaded elsewhere+\PassOptionsToPackage{unicode}{hyperref}+\PassOptionsToPackage{hyphens}{url}+\documentclass[+  american,+]{article}+\usepackage{xcolor}+\usepackage{amsmath,amssymb}+\setcounter{secnumdepth}{-\maxdimen} % remove section numbering+\usepackage{iftex}+\ifPDFTeX+  \usepackage[T1]{fontenc}+  \usepackage[utf8]{inputenc}+  \usepackage{textcomp} % provide euro and other symbols+\else % if luatex or xetex+  \usepackage{unicode-math} % this also loads fontspec+  \defaultfontfeatures{Scale=MatchLowercase}+  \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1}+\fi+\usepackage{lmodern}+\ifPDFTeX\else+  % xetex/luatex font selection+\fi+% Use upquote if available, for straight quotes in verbatim environments+\IfFileExists{upquote.sty}{\usepackage{upquote}}{}+\IfFileExists{microtype.sty}{% use microtype if available+  \usepackage[]{microtype}+  \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts+}{}+\makeatletter+\@ifundefined{KOMAClassName}{% if non-KOMA class+  \IfFileExists{parskip.sty}{%+    \usepackage{parskip}+  }{% else+    \setlength{\parindent}{0pt}+    \setlength{\parskip}{6pt plus 2pt minus 1pt}}+}{% if KOMA class+  \KOMAoptions{parskip=half}}+\makeatother+\ifLuaTeX+\usepackage[bidi=basic,shorthands=off]{babel}+\else+\usepackage[bidi=default,shorthands=off]{babel}+\fi+\ifLuaTeX+  \usepackage{selnolig} % disable illegal ligatures+\fi+\setlength{\emergencystretch}{3em} % prevent overfull lines+\providecommand{\tightlist}{%+  \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}+\usepackage{bookmark}+\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available+\urlstyle{same}+% fallback for those not using the hyperref driver hyperxmp:+\makeatletter+\@ifundefined{xmpquote}{\newcommand{\xmpquote}[1]{#1}}{}+\makeatother+\hypersetup{+  pdflang={en-US},+  hidelinks,+  pdfcreator={LaTeX via pandoc}}++\author{}+\date{}++\begin{document}++PDF 2.0 document.++\end{document}+```++PDF standard support: explicit version overrides inferred version+```+% pandoc -t latex -s+---+pdfstandard:+  - a-2b+  - "1.5"+lang: en-US+---++Explicit version document.+^D+\DocumentMetadata{+  pdfversion=1.5,+  pdfstandard={a-2b},+  lang=en-US,+  xmp=true}+% Options for packages loaded elsewhere+\PassOptionsToPackage{unicode}{hyperref}+\PassOptionsToPackage{hyphens}{url}+\documentclass[+  american,+]{article}+\usepackage{xcolor}+\usepackage{amsmath,amssymb}+\setcounter{secnumdepth}{-\maxdimen} % remove section numbering+\usepackage{iftex}+\ifPDFTeX+  \usepackage[T1]{fontenc}+  \usepackage[utf8]{inputenc}+  \usepackage{textcomp} % provide euro and other symbols+\else % if luatex or xetex+  \usepackage{unicode-math} % this also loads fontspec+  \defaultfontfeatures{Scale=MatchLowercase}+  \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1}+\fi+\usepackage{lmodern}+\ifPDFTeX\else+  % xetex/luatex font selection+\fi+% Use upquote if available, for straight quotes in verbatim environments+\IfFileExists{upquote.sty}{\usepackage{upquote}}{}+\IfFileExists{microtype.sty}{% use microtype if available+  \usepackage[]{microtype}+  \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts+}{}+\makeatletter+\@ifundefined{KOMAClassName}{% if non-KOMA class+  \IfFileExists{parskip.sty}{%+    \usepackage{parskip}+  }{% else+    \setlength{\parindent}{0pt}+    \setlength{\parskip}{6pt plus 2pt minus 1pt}}+}{% if KOMA class+  \KOMAoptions{parskip=half}}+\makeatother+\ifLuaTeX+\usepackage[bidi=basic,shorthands=off]{babel}+\else+\usepackage[bidi=default,shorthands=off]{babel}+\fi+\ifLuaTeX+  \usepackage{selnolig} % disable illegal ligatures+\fi+\setlength{\emergencystretch}{3em} % prevent overfull lines+\providecommand{\tightlist}{%+  \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}+\usepackage{bookmark}+\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available+\urlstyle{same}+% fallback for those not using the hyperref driver hyperxmp:+\makeatletter+\@ifundefined{xmpquote}{\newcommand{\xmpquote}[1]{#1}}{}+\makeatother+\hypersetup{+  pdflang={en-US},+  hidelinks,+  pdfcreator={LaTeX via pandoc}}++\author{}+\date{}++\begin{document}++Explicit version document.++\end{document}+```
test/command/refs.md view
@@ -118,7 +118,7 @@ , Para     [ Math         DisplayMath-        "\\label{eq:Accuracy}\n  Accuracy = \\frac{t_p + t_n}{t_p + f_p + f_n + t_n}"+        "\\begin{equation}\n  \\label{eq:Accuracy}\n  Accuracy = \\frac{t_p + t_n}{t_p + f_p + f_n + t_n}\n\\end{equation}"     ] ] ```
+ test/command/reset-citation-positions.md view
@@ -0,0 +1,41 @@+```+% pandoc --citeproc -t plain --csl command/chicago-fullnote-bibliography.csl+---+suppress-bibliography: true+references:+- id: foo+  name: John doe+  title: A Book+  type: book+  publisher: Oxford University Press+  issued: 2010+...++# Chapter one++Blah [@foo, p. 7].++Blah [@foo, p. 8].++# Chapter two {.reset-citation-positions}++Blah [@foo, p. 57].+^D+Chapter one++Blah.[1]++Blah.[2]++Chapter two++Blah.[3]++[1] A Book (Oxford University Press, 2010), 7.++[2] A Book, 8.++[3] A Book (Oxford University Press, 2010), 57.++```+
+ test/command/rst-writer-gridtable-if-rowspans.md view
@@ -0,0 +1,246 @@+```+% pandoc -f native -t rst+[ Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    ]+    (TableHead ( "" , [] , [] ) [])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 2)+                (ColSpan 1)+                [ Plain [ Str "2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "3" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "3" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "3" ] ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+, Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "1" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 2)+               (ColSpan 1)+               [ Plain [ Str "2" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "3" ] ]+           ]+       , Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "1" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "3" ] ]+           ]+       ])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "3" ] ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+, Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    ]+    (TableHead ( "" , [] , [] ) [])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        [] []+    ]+    (TableFoot ( "" , [] , [] )+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 2)+                (ColSpan 1)+                [ Plain [ Str "2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "3" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "3" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "3" ] ]+            ]+    ])+]+^D++---+---+---++| 1 | 2 | 3 |++---+   +---++| 1 |   | 3 |++---+---+---++| 1 | 2 | 3 |++---+---+---++++---+---+---++| 1 | 2 | 3 |++---+   +---++| 1 |   | 3 |++===+===+===++| 1 | 2 | 3 |++---+---+---++++===+===+===++| 1 | 2 | 3 |++---+   +---++| 1 |   | 3 |++---+---+---++| 1 | 2 | 3 |++===+===+===++```
+ test/command/rst_block_subst.md view
@@ -0,0 +1,18 @@+```+% pandoc -f rst -t native+|figure05|++.. |figure05| figure:: img/dummy.png++   capt+^D+[ Figure+    ( "" , [] , [] )+    (Caption Nothing [ Plain [ Str "capt" ] ])+    [ Plain+        [ Image+            ( "" , [] , [] ) [ Str "capt" ] ( "img/dummy.png" , "" )+        ]+    ]+]+```
test/command/table-with-column-span.md view
@@ -315,11 +315,11 @@   <table:table-column table:style-name="Table1.P" />   <table:table-row>     <table:table-cell table:style-name="TableRowCell" office:value-type="string" table:number-columns-spanned="8">-      <text:p text:style-name="Table_20_Contents"><text:span text:style-name="T1">Octet+      <text:p text:style-name="Table_20_Contents"><text:span text:style-name="Strong_20_Emphasis">Octet       no. 1</text:span></text:p>     </table:table-cell>     <table:table-cell table:style-name="TableRowCell" office:value-type="string" table:number-columns-spanned="8">-      <text:p text:style-name="Table_20_Contents"><text:span text:style-name="T1">Octet+      <text:p text:style-name="Table_20_Contents"><text:span text:style-name="Strong_20_Emphasis">Octet       no. 2</text:span></text:p>     </table:table-cell>   </table:table-row>
test/command/tasklist.md view
@@ -100,6 +100,6 @@ - [ ] foo - [x] bar ^D--   [ ] foo--   [x] bar+- [ ] foo+- [x] bar ```
test/command/toc.md view
@@ -16,12 +16,12 @@ ## e ::: ^D--   [A](#a){#toc-a}-    -   [b](#b){#toc-b}--   [B](#b-1){#toc-b-1}-    -   [b](#b-2){#toc-b-2}--   [E](#e){#toc-e}-    -   [e](#e-1){#toc-e-1}+- [A](#a){#toc-a}+  - [b](#b){#toc-b}+- [B](#b-1){#toc-b-1}+  - [b](#b-2){#toc-b-2}+- [E](#e){#toc-e}+  - [e](#e-1){#toc-e-1}  # A 
test/command/translations.md view
@@ -21,7 +21,7 @@ ```  ```-% pandoc -f latex -t native -M lang=sr+% pandoc -f latex -t native -M lang=sr-Latn \figurename~2 \figurename. ^D
+ test/command/typst-hs-80.md view
@@ -0,0 +1,55 @@+```+% pandoc -f typst -t native -s+#set document(+  title: [My Title],+)++#title()+^D+Pandoc+  Meta+    { unMeta =+        fromList+          [ ( "title"+            , MetaInlines [ Str "My" , Space , Str "Title" ]+            )+          ]+    }+  []+```++```+% pandoc -f typst -t native -s+#set document(+  title: [ignored],+)++#title[My Title]+^D+Pandoc+  Meta+    { unMeta =+        fromList+          [ ( "title"+            , MetaInlines [ Str "My" , Space , Str "Title" ]+            )+          ]+    }+  []+```++```+% pandoc -f typst -t native -s+#title[My Title]+^D+Pandoc+  Meta+    { unMeta =+        fromList+          [ ( "title"+            , MetaInlines [ Str "My" , Space , Str "Title" ]+            )+          ]+    }+  []+```
+ test/command/typst-image-alt.md view
@@ -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"))++```
+ test/command/typst-images.md view
@@ -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+  ]+)+```
+ test/command/typst-property-output.md view
@@ -0,0 +1,235 @@+```+% pandoc -f html -t typst+<span typst:text:fill="orange">foo</span>+^D+#text(fill: orange)[foo]+```++```+% pandoc -f html -t typst+<span>foo</span>+^D+foo+```++```+% pandoc -f html -t typst+<div typst:inset="10pt">foo</div>+^D+#block(inset: 10pt)[+foo+]+```++```+% pandoc -f html -t typst+<div typst:text:fill="purple">foo</div>+^D+#block[+#set text(fill: purple);+foo+]+```++```+% pandoc -f html -t typst+<div>foo</div>+^D+#block[+foo+]+```++```+% pandoc -f html -t typst+<table typst:fill="blue">+  <tr><td>A</td><td>B</td></tr>+</table>+^D+#figure(+  align(center)[#table(+    columns: 2,+    align: (auto,auto,),+    fill: blue,+    [A], [B],+  )]+  , kind: table+  )+```++```+% pandoc -f html -t typst+<table typst:text:fill="orange">+  <tr><td>A</td><td>B</td></tr>+</table>+^D+#figure(+  align(center)[#set text(fill: orange);#table(+    columns: 2,+    align: (auto,auto,),+    [A], [B],+  )]+  , kind: table+  )+```++```+% pandoc -f html -t typst+<table>+  <tr><td>A</td><td typst:fill="green">B</td></tr>+</table>+^D+#figure(+  align(center)[#table(+    columns: 2,+    align: (auto,auto,),+    [A], table.cell(fill: green)[B],+  )]+  , kind: table+  )+```++```+% pandoc -f html -t typst+<table>+  <tr><td>A</td><td typst:text:fill="fuchsia">B</td></tr>+</table>+^D+#figure(+  align(center)[#table(+    columns: 2,+    align: (auto,auto,),+    [A], [#set text(fill: fuchsia);+    B],+  )]+  , kind: table+  )+```++```+% pandoc -f html -t typst+<table>+  <tr><td>A</td><td typst:text:fill="maroon" align="center">B</td></tr>+</table>+^D+#figure(+  align(center)[#table(+    columns: 2,+    align: (auto,center,),+    [A], table.cell(align: center)[#set text(fill: maroon);+    B],+  )]+  , kind: table+  )+```++```+% pandoc -f html -t typst+<table>+  <tr><td>A</td><td typst:align="horizon" align="center">B</td></tr>+</table>+^D+#figure(+  align(center)[#table(+    columns: 2,+    align: (auto,center,),+    [A], table.cell(align: horizon + center)[B],+  )]+  , kind: table+  )+```+++```+% pandoc -f html -t typst+<table>+  <tr><td>A</td><td>B</td></tr>+</table>+^D+#figure(+  align(center)[#table(+    columns: 2,+    align: (auto,auto,),+    [A], [B],+  )]+  , kind: table+  )+```++```+% pandoc -f html -t typst+<p>Paragraph before.</p>++<table class="typst:no-figure" typst:text:size="3em">+  <tr>+    <td>A</td>+    <td>B</td>+    <td>C</td>+  </tr>+</table>++<p>Paragraph after.</p>+^D+Paragraph before.++#{set text(size: 3em);table(+  columns: 3,+  align: (auto,auto,auto,),+  [A], [B], [C],+)}+Paragraph after.+```+++```+% pandoc -f html -t typst+<p>Paragraph before.</p>++<table typst:text:size="3em">+  <tr>+    <td>A</td>+    <td>B</td>+    <td>C</td>+  </tr>+</table>++<p>Paragraph after.</p>+^D+Paragraph before.++#figure(+  align(center)[#set text(size: 3em);#table(+    columns: 3,+    align: (auto,auto,auto,),+    [A], [B], [C],+  )]+  , kind: table+  )++Paragraph after.+```+++```+% pandoc -f html -t typst+<p>Paragraph before.</p>++<table class="typst:no-figure">+  <tr>+    <td>A</td>+    <td>B</td>+    <td>C</td>+  </tr>+</table>++<p>Paragraph after.</p>+^D+Paragraph before.++#table(+  columns: 3,+  align: (auto,auto,auto,),+  [A], [B], [C],+)+Paragraph after.+```
@@ -11,20 +11,20 @@  [[name of page|title]] ^D-<p><a href="https://example.org" title="wikilink">https://example.org</a></p>-<p><a href="https://example.org" title="wikilink">title</a></p>-<p><a href="name of page" title="wikilink">name of page</a></p>-<p><a href="name of page" title="wikilink">title</a></p>+<p><a href="https://example.org" class="wikilink">https://example.org</a></p>+<p><a href="https://example.org" class="wikilink">title</a></p>+<p><a href="name of page" class="wikilink">name of page</a></p>+<p><a href="name of page" class="wikilink">title</a></p> ```  ## Writer  ``` % pandoc -t commonmark_x+wikilinks_title_after_pipe -f html-<p><a href="https://example.org" title="wikilink">https://example.org</a></p>-<p><a href="https://example.org" title="wikilink">title</a></p>-<p><a href="Home" title="wikilink">Home</a></p>-<p><a href="Name of page" title="wikilink">Title</a></p>+<p><a href="https://example.org" class="wikilink">https://example.org</a></p>+<p><a href="https://example.org" class="wikilink">title</a></p>+<p><a href="Home" class="wikilink">Home</a></p>+<p><a href="Name of page" class="wikilink">Title</a></p> ^D [[https://example.org]] @@ -48,20 +48,20 @@  [[name of page|title]] ^D-<p><a href="https://example.org" title="wikilink">https://example.org</a></p>-<p><a href="https://example.org" title="wikilink">title</a></p>-<p><a href="name of page" title="wikilink">name of page</a></p>-<p><a href="name of page" title="wikilink">title</a></p>+<p><a href="https://example.org" class="wikilink">https://example.org</a></p>+<p><a href="https://example.org" class="wikilink">title</a></p>+<p><a href="name of page" class="wikilink">name of page</a></p>+<p><a href="name of page" class="wikilink">title</a></p> ```  ## Writer  ``` % pandoc -t markdown+wikilinks_title_after_pipe -f html-<p><a href="https://example.org" title="wikilink">https://example.org</a></p>-<p><a href="https://example.org" title="wikilink">title</a></p>-<p><a href="Home" title="wikilink">Home</a></p>-<p><a href="Name of page" title="wikilink">Title</a></p>+<p><a href="https://example.org" class="wikilink">https://example.org</a></p>+<p><a href="https://example.org" class="wikilink">title</a></p>+<p><a href="Home" class="wikilink">Home</a></p>+<p><a href="Name of page" class="wikilink">Title</a></p> ^D [[https://example.org]] 
@@ -12,20 +12,20 @@  [[Title|Name of page]] ^D-<p><a href="https://example.org" title="wikilink">https://example.org</a></p>-<p><a href="https://example.org" title="wikilink">title</a></p>-<p><a href="Name of page" title="wikilink">Name of page</a></p>-<p><a href="Name of page" title="wikilink">Title</a></p>+<p><a href="https://example.org" class="wikilink">https://example.org</a></p>+<p><a href="https://example.org" class="wikilink">title</a></p>+<p><a href="Name of page" class="wikilink">Name of page</a></p>+<p><a href="Name of page" class="wikilink">Title</a></p> ```  ## Writer  ``` % pandoc -t commonmark_x+wikilinks_title_before_pipe -f html-<p><a href="https://example.org" title="wikilink">https://example.org</a></p>-<p><a href="https://example.org" title="wikilink">title</a></p>-<p><a href="Home" title="wikilink">Home</a></p>-<p><a href="Name of page" title="wikilink">Title</a></p>+<p><a href="https://example.org" class="wikilink">https://example.org</a></p>+<p><a href="https://example.org" class="wikilink">title</a></p>+<p><a href="Home" class="wikilink">Home</a></p>+<p><a href="Name of page" class="wikilink">Title</a></p> ^D [[https://example.org]] @@ -59,20 +59,20 @@  [[Title|Name of page]] ^D-<p><a href="https://example.org" title="wikilink">https://example.org</a></p>-<p><a href="https://example.org" title="wikilink">title</a></p>-<p><a href="Name of page" title="wikilink">Name of page</a></p>-<p><a href="Name of page" title="wikilink">Title</a></p>+<p><a href="https://example.org" class="wikilink">https://example.org</a></p>+<p><a href="https://example.org" class="wikilink">title</a></p>+<p><a href="Name of page" class="wikilink">Name of page</a></p>+<p><a href="Name of page" class="wikilink">Title</a></p> ```  ## Writer  ``` % pandoc -t markdown+wikilinks_title_before_pipe -f html-<p><a href="https://example.org" title="wikilink">https://example.org</a></p>-<p><a href="https://example.org" title="wikilink">title</a></p>-<p><a href="Home" title="wikilink">Home</a></p>-<p><a href="Name of page" title="wikilink">Title</a></p>+<p><a href="https://example.org" class="wikilink">https://example.org</a></p>+<p><a href="https://example.org" class="wikilink">title</a></p>+<p><a href="Home" class="wikilink">Home</a></p>+<p><a href="Name of page" class="wikilink">Title</a></p> ^D [[https://example.org]] 
test/djot-reader.native view
@@ -1,1089 +1,2365 @@ Pandoc   Meta { unMeta = fromList [] }   [ Div-      ( "Pandoc-Test-Suite"-      , [ "section" ]-      , [ ( "wrapper" , "1" ) ]-      )-      [ Header 1 ( "" , [] , [] ) [ Str "Pandoc Test Suite" ]-      , Para-          [ Str "John MacFarlane" , SoftBreak , Str "Anonymous" ]-      , Para [ Str "July 17, 2006" ]-      , Para-          [ Str-              "This is a set of tests for pandoc. Most of them are adapted from John Gruber\8217s"-          , SoftBreak-          , Str "markdown test suite."-          ]-      , HorizontalRule-      ]-  , Div-      ( "headers" , [ "section" ] , [ ( "wrapper" , "1" ) ] )-      [ Header 1 ( "" , [] , [] ) [ Str "Headers" ]-      , Div-          ( "level-2-with-an-embedded-link"-          , [ "section" ]-          , [ ( "wrapper" , "1" ) ]-          )-          [ Header-              2-              ( "" , [] , [] )-              [ Str "Level 2 with an "-              , Link-                  ( "" , [] , [] )-                  [ Str "embedded link" ]-                  ( "/url" , "" )-              ]-          , Div-              ( "level-3-with-emphasis"-              , [ "section" ]-              , [ ( "wrapper" , "1" ) ]-              )-              [ Header-                  3-                  ( "" , [] , [] )-                  [ Str "Level 3 with " , Emph [ Str "emphasis" ] ]-              , Div-                  ( "level-4"-                  , [ "section" ]-                  , [ ( "wrapper" , "1" ) ]-                  )-                  [ Header 4 ( "" , [] , [] ) [ Str "Level 4" ]-                  , Div-                      ( "level-5"-                      , [ "section" ]-                      , [ ( "wrapper" , "1" ) ]-                      )-                      [ Header 5 ( "" , [] , [] ) [ Str "Level 5" ] ]-                  ]-              ]-          ]-      ]-  , Div-      ( "level-1" , [ "section" ] , [ ( "wrapper" , "1" ) ] )-      [ Header 1 ( "" , [] , [] ) [ Str "Level 1" ]-      , Div-          ( "level-2-with-emphasis"-          , [ "section" ]-          , [ ( "wrapper" , "1" ) ]-          )-          [ Header-              2-              ( "" , [] , [] )-              [ Str "Level 2 with " , Emph [ Str "emphasis" ] ]-          , Div-              ( "level-3" , [ "section" ] , [ ( "wrapper" , "1" ) ] )-              [ Header 3 ( "" , [] , [] ) [ Str "Level 3" ]-              , Para [ Str "with no blank line" ]-              ]-          ]-      , Div-          ( "level-2" , [ "section" ] , [ ( "wrapper" , "1" ) ] )-          [ Header 2 ( "" , [] , [] ) [ Str "Level 2" ]-          , Para [ Str "with no blank line" ]-          , HorizontalRule-          ]-      ]-  , Div-      ( "paragraphs" , [ "section" ] , [ ( "wrapper" , "1" ) ] )-      [ Header 1 ( "" , [] , [] ) [ Str "Paragraphs" ]-      , Para [ Str "Here\8217s a regular paragraph." ]-      , Para-          [ Str-              "In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item."-          , SoftBreak-          , Str-              "Because a hard-wrapped line in the middle of a paragraph looked like a list"-          , SoftBreak-          , Str "item."-          ]-      , Para [ Str "Here\8217s one with a bullet. * criminey." ]-      , Para-          [ Str "There should be a hard line break"-          , LineBreak-          , Str "here."-          ]-      , HorizontalRule-      ]-  , Div-      ( "block-quotes" , [ "section" ] , [ ( "wrapper" , "1" ) ] )-      [ Header 1 ( "" , [] , [] ) [ Str "Block Quotes" ]-      , Para [ Str "E-mail style:" ]-      , BlockQuote-          [ Para [ Str "This is a block quote. It is pretty short." ]-          ]-      , BlockQuote-          [ Para [ Str "Code in a block quote:" ]-          , CodeBlock-              ( "" , [ "" ] , [] )-              "sub status {\nprint \"working\";\n}\n"-          , Para [ Str "A list:" ]-          , OrderedList-              ( 1 , Decimal , Period )-              [ [ Plain [ Str "item one" ] ]-              , [ Plain [ Str "item two" ] ]-              ]-          , Para [ Str "Nested block quotes:" ]-          , BlockQuote [ Para [ Str "nested" ] ]-          , BlockQuote [ Para [ Str "nested" ] ]-          ]-      , Para [ Str "This should not be a block quote: 2 > 1." ]-      , Para [ Str "And a following paragraph." ]-      , HorizontalRule-      ]-  , Div-      ( "code-blocks" , [ "section" ] , [ ( "wrapper" , "1" ) ] )-      [ Header 1 ( "" , [] , [] ) [ Str "Code Blocks" ]-      , Para [ Str "Code:" ]-      , CodeBlock-          ( "" , [ "" ] , [] )-          "---- (should be four hyphens)\n\nsub status {\n    print \"working\";\n}\n\nthis code block is indented by one tab\n"-      , Para [ Str "And:" ]-      , CodeBlock-          ( "" , [ "" ] , [] )-          "    this code block is indented by two tabs\n\nThese should not be escaped:  \\$ \\\\ \\> \\[ \\{\n"-      , HorizontalRule-      ]-  , Div-      ( "lists" , [ "section" ] , [ ( "wrapper" , "1" ) ] )-      [ Header 1 ( "" , [] , [] ) [ Str "Lists" ]-      , Div-          ( "unordered" , [ "section" ] , [ ( "wrapper" , "1" ) ] )-          [ Header 2 ( "" , [] , [] ) [ Str "Unordered" ]-          , Para [ Str "Asterisks tight:" ]-          , BulletList-              [ [ Plain [ Str "asterisk 1" ] ]-              , [ Plain [ Str "asterisk 2" ] ]-              , [ Plain [ Str "asterisk 3" ] ]-              ]-          , Para [ Str "Asterisks loose:" ]-          , BulletList-              [ [ Para [ Str "asterisk 1" ] ]-              , [ Para [ Str "asterisk 2" ] ]-              , [ Para [ Str "asterisk 3" ] ]-              ]-          , Para [ Str "Pluses tight:" ]-          , BulletList-              [ [ Plain [ Str "Plus 1" ] ]-              , [ Plain [ Str "Plus 2" ] ]-              , [ Plain [ Str "Plus 3" ] ]-              ]-          , Para [ Str "Pluses loose:" ]-          , BulletList-              [ [ Para [ Str "Plus 1" ] ]-              , [ Para [ Str "Plus 2" ] ]-              , [ Para [ Str "Plus 3" ] ]-              ]-          , Para [ Str "Minuses tight:" ]-          , BulletList-              [ [ Plain [ Str "Minus 1" ] ]-              , [ Plain [ Str "Minus 2" ] ]-              , [ Plain [ Str "Minus 3" ] ]-              ]-          , Para [ Str "Minuses loose:" ]-          , BulletList-              [ [ Para [ Str "Minus 1" ] ]-              , [ Para [ Str "Minus 2" ] ]-              , [ Para [ Str "Minus 3" ] ]-              ]-          ]-      , Div-          ( "ordered" , [ "section" ] , [ ( "wrapper" , "1" ) ] )-          [ Header 2 ( "" , [] , [] ) [ Str "Ordered" ]-          , Para [ Str "Tight:" ]-          , OrderedList-              ( 1 , Decimal , Period )-              [ [ Plain [ Str "First" ] ]-              , [ Plain [ Str "Second" ] ]-              , [ Plain [ Str "Third" ] ]-              ]-          , Para [ Str "and:" ]-          , OrderedList-              ( 1 , Decimal , Period )-              [ [ Plain [ Str "One" ] ]-              , [ Plain [ Str "Two" ] ]-              , [ Plain [ Str "Three" ] ]-              ]-          , Para [ Str "Loose using tabs:" ]-          , OrderedList-              ( 1 , Decimal , Period )-              [ [ Para [ Str "First" ] ]-              , [ Para [ Str "Second" ] ]-              , [ Para [ Str "Third" ] ]-              ]-          , Para [ Str "and using spaces:" ]-          , OrderedList-              ( 1 , Decimal , Period )-              [ [ Para [ Str "One" ] ]-              , [ Para [ Str "Two" ] ]-              , [ Para [ Str "Three" ] ]-              ]-          , Para [ Str "Multiple paragraphs:" ]-          , OrderedList-              ( 1 , Decimal , Period )-              [ [ Para [ Str "Item 1, graf one." ]-                , Para-                    [ Str-                        "Item 1. graf two. The quick brown fox jumped over the lazy dog\8217s back."-                    ]-                ]-              , [ Para [ Str "Item 2." ] ]-              , [ Para [ Str "Item 3." ] ]-              ]-          ]-      , Div-          ( "nested" , [ "section" ] , [ ( "wrapper" , "1" ) ] )-          [ Header 2 ( "" , [] , [] ) [ Str "Nested" ]-          , BulletList-              [ [ Plain [ Str "Tab" ]-                , BulletList-                    [ [ Plain [ Str "Tab" ]-                      , BulletList [ [ Plain [ Str "Tab" ] ] ]-                      ]-                    ]-                ]-              ]-          , Para [ Str "Here\8217s another:" ]-          , OrderedList-              ( 1 , Decimal , Period )-              [ [ Plain [ Str "First" ] ]-              , [ Plain [ Str "Second:" ]-                , BulletList-                    [ [ Plain [ Str "Fee" ] ]-                    , [ Plain [ Str "Fie" ] ]-                    , [ Plain [ Str "Foe" ] ]-                    ]-                ]-              , [ Plain [ Str "Third" ] ]-              ]-          , Para [ Str "Same thing but with paragraphs:" ]-          , OrderedList-              ( 1 , Decimal , Period )-              [ [ Para [ Str "First" ] ]-              , [ Para [ Str "Second:" ]-                , BulletList-                    [ [ Plain [ Str "Fee" ] ]-                    , [ Plain [ Str "Fie" ] ]-                    , [ Plain [ Str "Foe" ] ]-                    ]-                ]-              , [ Para [ Str "Third" ] ]-              ]-          ]-      , Div-          ( "tabs-and-spaces"-          , [ "section" ]-          , [ ( "wrapper" , "1" ) ]-          )-          [ Header 2 ( "" , [] , [] ) [ Str "Tabs and spaces" ]-          , BulletList-              [ [ Para [ Str "this is a list item indented with tabs" ]-                ]-              , [ Para-                    [ Str "this is a list item indented with spaces" ]-                , BulletList-                    [ [ Para-                          [ Str-                              "this is an example list item indented with tabs"-                          ]-                      ]-                    , [ Para-                          [ Str-                              "this is an example list item indented with spaces"-                          ]-                      ]-                    ]-                ]-              ]-          ]-      , Div-          ( "fancy-list-markers"-          , [ "section" ]-          , [ ( "wrapper" , "1" ) ]-          )-          [ Header 2 ( "" , [] , [] ) [ Str "Fancy list markers" ]-          , OrderedList-              ( 2 , Decimal , TwoParens )-              [ [ Para [ Str "begins with 2" ] ]-              , [ Para [ Str "and now 3" ]-                , Para [ Str "with a continuation" ]-                , OrderedList-                    ( 4 , LowerRoman , Period )-                    [ [ Plain-                          [ Str-                              "sublist with roman numerals, starting with 4"-                          ]-                      ]-                    , [ Plain [ Str "more items" ]-                      , OrderedList-                          ( 1 , UpperAlpha , TwoParens )-                          [ [ Plain [ Str "a subsublist" ] ]-                          , [ Plain [ Str "a subsublist" ] ]-                          ]-                      ]-                    ]-                ]-              ]-          , Para [ Str "Nesting:" ]-          , OrderedList-              ( 1 , UpperAlpha , Period )-              [ [ Plain [ Str "Upper Alpha" ]-                , OrderedList-                    ( 1 , UpperRoman , Period )-                    [ [ Plain [ Str "Upper Roman." ]-                      , OrderedList-                          ( 6 , Decimal , TwoParens )-                          [ [ Plain [ Str "Decimal start with 6" ]-                            , OrderedList-                                ( 3 , LowerAlpha , OneParen )-                                [ [ Plain-                                      [ Str "Lower alpha with paren" ]-                                  ]-                                ]-                            ]-                          ]-                      ]-                    ]-                ]-              ]-          , Para [ Str "Autonumbering:" ]-          , OrderedList-              ( 1 , Decimal , Period )-              [ [ Plain [ Str "Autonumber." ] ]-              , [ Plain [ Str "More." ]-                , OrderedList-                    ( 1 , Decimal , Period )-                    [ [ Plain [ Str "Nested." ] ] ]-                ]-              ]-          , Para [ Str "Should not be a list item:" ]-          , Para [ Str "M.A.\160\&2007" ]-          , OrderedList-              ( 2 , UpperAlpha , Period )-              [ [ Plain [ Str "Williams" ] ] ]-          , HorizontalRule-          ]-      ]-  , Div-      ( "definition-lists"-      , [ "section" ]-      , [ ( "wrapper" , "1" ) ]-      )-      [ Header 1 ( "" , [] , [] ) [ Str "Definition Lists" ]-      , Para [ Str "Tight using spaces:" ]-      , DefinitionList-          [ ( [ Str "apple" ] , [ [ Plain [ Str "red fruit" ] ] ] )-          , ( [ Str "orange" ]-            , [ [ Plain [ Str "orange fruit" ] ] ]-            )-          , ( [ Str "banana" ]-            , [ [ Plain [ Str "yellow fruit" ] ] ]-            )-          ]-      , Para [ Str "Tight using tabs:" ]-      , DefinitionList-          [ ( [ Str "apple" ] , [ [ Plain [ Str "red fruit" ] ] ] )-          , ( [ Str "orange" ]-            , [ [ Plain [ Str "orange fruit" ] ] ]-            )-          , ( [ Str "banana" ]-            , [ [ Plain [ Str "yellow fruit" ] ] ]-            )-          ]-      , Para [ Str "Loose:" ]-      , DefinitionList-          [ ( [ Str "apple" ] , [ [ Para [ Str "red fruit" ] ] ] )-          , ( [ Str "orange" ] , [ [ Para [ Str "orange fruit" ] ] ] )-          , ( [ Str "banana" ] , [ [ Para [ Str "yellow fruit" ] ] ] )-          ]-      , Para [ Str "Multiple blocks with italics:" ]-      , DefinitionList-          [ ( [ Emph [ Str "apple" ] ]-            , [ [ Para [ Str "red fruit" ]-                , Para-                    [ Str "contains seeds, crisp, pleasant to taste" ]-                ]-              ]-            )-          , ( [ Emph [ Str "orange" ] ]-            , [ [ Para [ Str "orange fruit" ]-                , CodeBlock-                    ( "" , [ "" ] , [] ) "{ orange code block }\n"-                ]-              ]-            )-          ]-      , BlockQuote [ Para [ Str "orange block quote" ] ]-      , Para [ Str "Multiple definitions, tight:" ]-      , DefinitionList-          [ ( [ Str "apple" ]-            , [ [ Para [ Str "red fruit" ] , Para [ Str "computer" ] ] ]-            )-          , ( [ Str "orange" ]-            , [ [ Para [ Str "orange fruit" ] , Para [ Str "bank" ] ] ]-            )-          ]-      , Para [ Str "Multiple definitions, loose:" ]-      , DefinitionList-          [ ( [ Str "apple" ]-            , [ [ Para [ Str "red fruit" ] , Para [ Str "computer" ] ] ]-            )-          , ( [ Str "orange" ]-            , [ [ Para [ Str "orange fruit" ] , Para [ Str "bank" ] ] ]-            )-          ]-      , Para-          [ Str-              "Blank line after term, indented marker, alternate markers:"-          ]-      , DefinitionList-          [ ( [ Str "apple" ]-            , [ [ Para [ Str "red fruit" ] , Para [ Str "computer" ] ] ]-            )-          , ( [ Str "orange" ]-            , [ [ Para [ Str "orange fruit" ]-                , OrderedList-                    ( 1 , Decimal , Period )-                    [ [ Plain [ Str "sublist" ] ]-                    , [ Plain [ Str "sublist" ] ]-                    ]-                ]-              ]-            )-          ]-      ]-  , Div-      ( "html-blocks" , [ "section" ] , [ ( "wrapper" , "1" ) ] )-      [ Header 1 ( "" , [] , [] ) [ Str "HTML Blocks" ]-      , Para [ Str "Simple block on one line:" ]-      , Div ( "" , [] , [] ) [ Para [ Str "foo" ] ]-      , Para [ Str "And nested without indentation:" ]-      , Div-          ( "" , [] , [] )-          [ Div-              ( "" , [] , [] )-              [ Div ( "" , [] , [] ) [ Para [ Str "foo" ] ] ]-          , Div ( "" , [] , [] ) [ Para [ Str "bar" ] ]-          ]-      , Para [ Str "Interpreted markdown in a table:" ]-      , Para [ Str "This is " , Emph [ Str "emphasized" ] ]-      , Para [ Str "And this is " , Strong [ Str "strong" ] ]-      , Para [ Str "Here\8217s a simple block:" ]-      , Div ( "" , [] , [] ) [ Para [ Str "foo" ] ]-      , Para [ Str "This should be a code block, though:" ]-      , CodeBlock ( "" , [ "" ] , [] ) "<div>\n    foo\n</div>\n"-      , Para [ Str "As should this:" ]-      , CodeBlock ( "" , [ "" ] , [] ) "<div>foo</div>\n"-      , Para [ Str "Now, nested:" ]-      , Div-          ( "" , [] , [] )-          [ Div-              ( "" , [] , [] )-              [ Div ( "" , [] , [] ) [ Para [ Str "foo" ] ] ]-          ]-      , Para [ Str "This should just be an HTML comment:" ]-      , Para [ Str "Multiline:" ]-      , Para [ Str "Code block:" ]-      , CodeBlock ( "" , [ "" ] , [] ) "<!-- Comment -->\n"-      , Para-          [ Str-              "Just plain comment, with trailing spaces on the line:"-          ]-      , Para [ Str "Code:" ]-      , CodeBlock ( "" , [ "" ] , [] ) "<hr />\n"-      , Para [ Str "Hr\8217s:" ]-      , HorizontalRule-      ]-  , Div-      ( "inline-markup"-      , [ "section" ]-      , [ ( "wrapper" , "1" ) ]-      )-      [ Header 1 ( "" , [] , [] ) [ Str "Inline Markup" ]-      , Para-          [ Str "This is "-          , Emph [ Str "emphasized" ]-          , Str ", and so "-          , Emph [ Str "is this" ]-          , Str "."-          ]-      , Para-          [ Str "This is "-          , Strong [ Str "strong" ]-          , Str ", and so "-          , Strong [ Str "is this" ]-          , Str "."-          ]-      , Para-          [ Str "An "-          , Emph-              [ Link-                  ( "" , [] , [] )-                  [ Str "emphasized link" ]-                  ( "/url" , "" )-              ]-          , Str "."-          ]-      , Para [ Strong [ Emph [ Str "This is strong and em." ] ] ]-      , Para-          [ Str "So is "-          , Strong [ Emph [ Str "this" ] ]-          , Str " word."-          ]-      , Para [ Strong [ Emph [ Str "This is strong and em." ] ] ]-      , Para-          [ Str "So is "-          , Strong [ Emph [ Str "this" ] ]-          , Str " word."-          ]-      , Para-          [ Str "This is code: "-          , Code ( "" , [] , [] ) ">"-          , Str ", "-          , Code ( "" , [] , [] ) "$"-          , Str ", "-          , Code ( "" , [] , [] ) "\\`, "-          , Str "$"-          , Code ( "" , [] , [] ) ", "-          , Str "<html>"-          , Code ( "" , [] , [] ) "."-          ]-      , Para-          [ Span-              ( "" , [ "deleted" ] , [] )-              [ Str "This is " , Emph [ Str "strikeout" ] , Str "." ]-          ]-      , Para-          [ Str "Superscripts: a"-          , Superscript [ Str "bc" ]-          , Str "d a"-          , Superscript [ Emph [ Str "hello" ] ]-          , Str " a"-          , Superscript [ Str "hello\160there" ]-          , Str "."-          ]-      , Para-          [ Str "Subscripts: H"-          , Subscript [ Str "2" ]-          , Str "O, H"-          , Subscript [ Str "23" ]-          , Str "O, H"-          , Subscript [ Str "many\160of\160them" ]-          , Str "O."-          ]-      , Para-          [ Str-              "These should not be superscripts or subscripts, because of the unescaped spaces:"-          , SoftBreak-          , Str "a^b c^d, a~b c~d."-          ]-      , HorizontalRule-      ]-  , Div-      ( "smart-quotes-ellipses-dashes"-      , [ "section" ]-      , [ ( "wrapper" , "1" ) ]-      )-      [ Header-          1 ( "" , [] , [] ) [ Str "Smart quotes, ellipses, dashes" ]-      , Para-          [ Quoted DoubleQuote [ Str "Hello," ]-          , Str " said the spider. "-          , Quoted-              DoubleQuote-              [ Quoted SingleQuote [ Str "Shelob" ]-              , Str " is my name."-              ]-          ]-      , Para-          [ Quoted SingleQuote [ Str "A" ]-          , Str ", "-          , Quoted SingleQuote [ Str "B" ]-          , Str ", and "-          , Quoted SingleQuote [ Str "C" ]-          , Str " are letters."-          ]-      , Para-          [ Quoted SingleQuote [ Str "Oak," ]-          , Str " "-          , Quoted SingleQuote [ Str "elm," ]-          , Str " and "-          , Quoted SingleQuote [ Str "beech" ]-          , Str " are names of trees. So is "-          , Quoted SingleQuote [ Str "pine." ]-          ]-      , Para-          [ Quoted-              SingleQuote-              [ Str "He said, "-              , Quoted DoubleQuote [ Str "I want to go." ]-              ]-          , Str " Were you alive in the 70\8217s?"-          ]-      , Para-          [ Str "Here is some quoted "-          , Quoted SingleQuote [ Code ( "" , [] , [] ) "code" ]-          , Str " and a "-          , Quoted-              DoubleQuote-              [ Link-                  ( "" , [] , [] )-                  [ Str "quoted" , SoftBreak , Str "link" ]-                  ( "http://example.com/?foo=1&bar=2" , "" )-              ]-          , Str "."-          ]-      , Para-          [ Str-              "Some dashes: one\8212two \8212 three\8212four \8212 five."-          ]-      , Para-          [ Str-              "Dashes between numbers: 5\8211\&7, 255\8211\&66, 1987\8211\&1999."-          ]-      , Para [ Str "Ellipses\8230and\8230and\8230." ]-      , HorizontalRule-      ]-  , Div-      ( "latex" , [ "section" ] , [ ( "wrapper" , "1" ) ] )-      [ Header 1 ( "" , [] , [] ) [ Str "LaTeX" ]-      , BulletList-          [ []-          , [ Plain [ Math InlineMath "2+2=4" ] ]-          , [ Plain [ Math InlineMath "x \\in y" ] ]-          , [ Plain [ Math InlineMath "\\alpha \\wedge \\omega" ] ]-          , [ Plain [ Math InlineMath "223" ] ]-          , [ Plain [ Math InlineMath "p" , Str "-Tree" ] ]-          , [ Plain-                [ Str "Here\8217s some display math:"-                , SoftBreak-                , Math-                    DisplayMath-                    "\\frac{d}{dx}f(x)=\\lim_{h\\to 0}\\frac{f(x+h)-f(x)}{h}"-                ]-            ]-          , [ Plain-                [ Str "Here\8217s one that has a line break in it: "-                , Math InlineMath "\\alpha + \\omega \\times x^2"-                , Str "."-                ]-            ]-          ]-      , Para [ Str "These shouldn\8217t be math:" ]-      , BulletList-          [ [ Plain-                [ Str "To get the famous equation, write "-                , Code ( "" , [] , [] ) "$e = mc^2$"-                , Str "."-                ]-            ]-          , [ Plain-                [ Str "$22,000 is a "-                , Emph [ Str "lot" ]-                , Str " of money. So is $34,000. (It worked if "-                , Quoted DoubleQuote [ Str "lot" ]-                , Str " is"-                , SoftBreak-                , Str "emphasized.)"-                ]-            ]-          , [ Plain [ Str "Shoes ($20) and socks ($5)." ] ]-          , [ Plain-                [ Str "Escaped "-                , Code ( "" , [] , [] ) "$"-                , Str ": $73 "-                , Emph [ Str "this should be emphasized" ]-                , Str " 23$."-                ]-            ]-          ]-      , Para [ Str "Here\8217s a LaTeX table:" ]-      , HorizontalRule-      ]-  , Div-      ( "special-characters"-      , [ "section" ]-      , [ ( "wrapper" , "1" ) ]-      )-      [ Header 1 ( "" , [] , [] ) [ Str "Special Characters" ]-      , Para [ Str "Here is some unicode:" ]-      , BulletList-          [ [ Plain [ Str "I hat: \206" ] ]-          , [ Plain [ Str "o umlaut: \246" ] ]-          , [ Plain [ Str "section: \167" ] ]-          , [ Plain [ Str "set membership: \8712" ] ]-          , [ Plain [ Str "copyright: \169" ] ]-          ]-      , Para [ Str "AT&T has an ampersand in their name." ]-      , Para [ Str "AT&T is another way to write it." ]-      , Para [ Str "This & that." ]-      , Para [ Str "4 < 5." ]-      , Para [ Str "6 > 5." ]-      , Para [ Str "Backslash: \\" ]-      , Para [ Str "Backtick: `" ]-      , Para [ Str "Asterisk: *" ]-      , Para [ Str "Underscore: _" ]-      , Para [ Str "Left brace: {" ]-      , Para [ Str "Right brace: }" ]-      , Para [ Str "Left bracket: [" ]-      , Para [ Str "Right bracket: ]" ]-      , Para [ Str "Left paren: (" ]-      , Para [ Str "Right paren: )" ]-      , Para [ Str "Greater-than: >" ]-      , Para [ Str "Hash: #" ]-      , Para [ Str "Period: ." ]-      , Para [ Str "Bang: !" ]-      , Para [ Str "Plus: +" ]-      , Para [ Str "Minus: -" ]-      , HorizontalRule-      ]-  , Div-      ( "links" , [ "section" ] , [ ( "wrapper" , "1" ) ] )-      [ Header 1 ( "" , [] , [] ) [ Str "Links" ]-      , Div-          ( "explicit" , [ "section" ] , [ ( "wrapper" , "1" ) ] )-          [ Header 2 ( "" , [] , [] ) [ Str "Explicit" ]-          , Para-              [ Str "Just a "-              , Link ( "" , [] , [] ) [ Str "URL" ] ( "/url/" , "" )-              , Str "."-              ]-          , Para-              [ Link-                  ( ""-                  , []-                  , [ ( "wrapper" , "1" ) , ( "title" , "title" ) ]-                  )-                  [ Str "URL and title" ]-                  ( "/url/" , "" )-              , Str "."-              ]-          , Para-              [ Link-                  ( ""-                  , []-                  , [ ( "wrapper" , "1" )-                    , ( "title" , "title preceded by two spaces" )-                    ]-                  )-                  [ Str "URL and title" ]-                  ( "/url/" , "" )-              , Str "."-              ]-          , Para-              [ Link-                  ( ""-                  , []-                  , [ ( "wrapper" , "1" )-                    , ( "title" , "title preceded by a tab" )-                    ]-                  )-                  [ Str "URL and title" ]-                  ( "/url/" , "" )-              , Str "."-              ]-          , Para-              [ Link-                  ( ""-                  , []-                  , [ ( "wrapper" , "1" )-                    , ( "title" , "title with \"quotes\" in it" )-                    ]-                  )-                  [ Str "URL and title" ]-                  ( "/url/" , "" )-              ]-          , Para-              [ Link-                  ( ""-                  , []-                  , [ ( "wrapper" , "1" )-                    , ( "title" , "title with single quotes" )-                    ]-                  )-                  [ Str "URL and title" ]-                  ( "/url/" , "" )-              ]-          , Para-              [ Link-                  ( "" , [] , [] )-                  [ Str "with_underscore" ]-                  ( "/url/with_underscore" , "" )-              ]-          , Para-              [ Link-                  ( "" , [] , [] )-                  [ Str "Email link" ]-                  ( "mailto:nobody@nowhere.net" , "" )-              ]-          , Para-              [ Link ( "" , [] , [] ) [ Str "Empty" ] ( "" , "" )-              , Str "."-              ]-          ]-      , Div-          ( "reference" , [ "section" ] , [ ( "wrapper" , "1" ) ] )-          [ Header 2 ( "" , [] , [] ) [ Str "Reference" ]-          , Para-              [ Str "Foo "-              , Link ( "" , [] , [] ) [ Str "bar" ] ( "/url/" , "" )-              , Str "."-              ]-          , Para-              [ Str "With "-              , Link-                  ( "" , [] , [] )-                  [ Str "embedded [brackets]" ]-                  ( "/url/" , "" )-              , Str "."-              ]-          , Para-              [ Link ( "" , [] , [] ) [ Str "b" ] ( "/url/" , "" )-              , Str " by itself should be a link."-              ]-          , Para-              [ Str "Indented "-              , Link ( "" , [] , [] ) [ Str "once" ] ( "/url" , "" )-              , Str "."-              ]-          , Para-              [ Str "Indented "-              , Link ( "" , [] , [] ) [ Str "twice" ] ( "/url" , "" )-              , Str "."-              ]-          , Para-              [ Str "Indented "-              , Link ( "" , [] , [] ) [ Str "thrice" ] ( "/url" , "" )-              , Str "."-              ]-          , Para [ Str "This should [not][] be a link." ]-          , CodeBlock ( "" , [ "" ] , [] ) "[not]: /url\n"-          , Para-              [ Str "Foo "-              , Link-                  ( ""-                  , []-                  , [ ( "wrapper" , "1" )-                    , ( "title" , "Title with \"quotes\" inside" )-                    ]-                  )-                  [ Str "bar" ]-                  ( "/url/" , "" )-              , Str "."-              ]-          , Para-              [ Str "Foo "-              , Link-                  ( ""-                  , []-                  , [ ( "wrapper" , "1" )-                    , ( "title" , "Title with \"quote\" inside" )-                    ]-                  )-                  [ Str "biz" ]-                  ( "/url/" , "" )-              , Str "."-              ]-          ]-      , Div-          ( "with-ampersands"-          , [ "section" ]-          , [ ( "wrapper" , "1" ) ]-          )-          [ Header 2 ( "" , [] , [] ) [ Str "With ampersands" ]-          , Para-              [ Str "Here\8217s a "-              , Link-                  ( "" , [] , [] )-                  [ Str "link with an ampersand in the URL" ]-                  ( "http://example.com/?foo=1&bar=2" , "" )-              , Str "."-              ]-          , Para-              [ Str-                  "Here\8217s a link with an amersand in the link text:"-              , SoftBreak-              , Link-                  ( ""-                  , []-                  , [ ( "wrapper" , "1" ) , ( "title" , "AT&T" ) ]-                  )-                  [ Str "AT&T" ]-                  ( "http://att.com/" , "" )-              , Str "."-              ]-          , Para-              [ Str "Here\8217s an "-              , Link-                  ( "" , [] , [] )-                  [ Str "inline link" ]-                  ( "/script?foo=1&bar=2" , "" )-              , Str "."-              ]-          , Para-              [ Str "Here\8217s an "-              , Link-                  ( "" , [] , [] )-                  [ Str "inline link in pointy braces" ]-                  ( "/script?foo=1&bar=2" , "" )-              , Str "."-              ]-          ]-      , Div-          ( "autolinks" , [ "section" ] , [ ( "wrapper" , "1" ) ] )-          [ Header 2 ( "" , [] , [] ) [ Str "Autolinks" ]-          , Para-              [ Str "With an ampersand: "-              , Link-                  ( "" , [ "uri" ] , [] )-                  [ Str "http://example.com/?foo=1&bar=2" ]-                  ( "http://example.com/?foo=1&bar=2" , "" )-              ]-          , BulletList-              [ [ Plain [ Str "In a list?" ] ]-              , [ Plain-                    [ Link-                        ( "" , [ "uri" ] , [] )-                        [ Str "http://example.com/" ]-                        ( "http://example.com/" , "" )-                    ]-                ]-              , [ Plain [ Str "It should." ] ]-              ]-          , Para-              [ Str "An e-mail address: "-              , Link-                  ( "" , [ "email" ] , [] )-                  [ Str "nobody@nowhere.net" ]-                  ( "mailto:nobody@nowhere.net" , "" )-              ]-          , BlockQuote-              [ Para-                  [ Str "Blockquoted: "-                  , Link-                      ( "" , [ "uri" ] , [] )-                      [ Str "http://example.com/" ]-                      ( "http://example.com/" , "" )-                  ]-              ]-          , Para-              [ Str "Auto-links should not occur here: "-              , Code ( "" , [] , [] ) "<http://example.com/>"-              ]-          , CodeBlock-              ( "" , [ "" ] , [] ) "or here: <http://example.com/>\n"-          , HorizontalRule-          ]-      ]-  , Div-      ( "images" , [ "section" ] , [ ( "wrapper" , "1" ) ] )-      [ Header 1 ( "" , [] , [] ) [ Str "Images" ]-      , Para-          [ Str "From "-          , Quoted DoubleQuote [ Str "Voyage dans la Lune" ]-          , Str " by Georges Melies (1902):"-          ]-      , Div-          ( "" , [] , [] )-          [ Para-              [ Image-                  ( ""-                  , []-                  , [ ( "wrapper" , "1" )-                    , ( "title" , "Voyage dans la Lune" )-                    ]-                  )-                  [ Str "lalune" ]-                  ( "lalune.jpg" , "" )-              ]-          , Div-              ( "" , [ "caption" ] , [ ( "wrapper" , "1" ) ] )-              [ Para [ Str "lalune" ] ]-          ]-      , Para-          [ Str "Here is a movie "-          , Image-              ( "" , [] , [] ) [ Str "movie" ] ( "movie.jpg" , "" )-          , Str " icon."-          ]-      , HorizontalRule-      ]-  , Div-      ( "footnotes" , [ "section" ] , [ ( "wrapper" , "1" ) ] )-      [ Header 1 ( "" , [] , [] ) [ Str "Footnotes" ]-      , Para-          [ Str "Here is a footnote reference,"-          , Note-              [ Para-                  [ Str-                      "Here is the footnote. It can go anywhere after the footnote reference. It"-                  , SoftBreak-                  , Str "need not be placed at the end of the document."-                  ]-              ]-          , Str " and another."-          , Note-              [ Para-                  [ Str-                      "Here\8217s the long note. This one contains multiple blocks."-                  ]-              , Para-                  [ Str-                      "Subsequent blocks are indented to show that they belong to the footnote (as"-                  , SoftBreak-                  , Str "with list items)."-                  ]-              , CodeBlock ( "" , [ "" ] , [] ) "{ <code> }\n"-              , Para-                  [ Str-                      "If you want, you can indent every line, but you can also be lazy and just"-                  , SoftBreak-                  , Str "indent the first line of each block."-                  ]-              ]-          , Str " This should "-          , Emph [ Str "not" ]-          , Str " be a"-          , SoftBreak-          , Str-              "footnote reference, because it contains a space.[^my note] Here is an inline"-          , SoftBreak-          , Str "note."-          , Note-              [ Para-                  [ Str "This is "-                  , Emph [ Str "easier" ]-                  , Str " to type. Inline notes may contain"-                  , SoftBreak-                  , Link-                      ( "" , [] , [] )-                      [ Str "links" ]-                      ( "http://google.com" , "" )-                  , Str " and "-                  , Code ( "" , [] , [] ) "]"-                  , Str " verbatim characters, as well as"-                  , SoftBreak-                  , Str "[bracketed text]."-                  ]-              ]-          ]-      , BlockQuote-          [ Para-              [ Str "Notes can go in quotes."-              , Note [ Para [ Str "In quote." ] ]-              ]-          ]-      , OrderedList-          ( 1 , Decimal , Period )-          [ [ Plain-                [ Str "And in list items."-                , Note [ Para [ Str "In list." ] ]-                ]-            ]-          ]-      , Para-          [ Str-              "This paragraph should not be part of the note, as it is not indented."+      ( "Pandoc-Test-Suite" , [ "section" ] , [] )+      [ Header+          1+          ( "" , [] , [] )+          [ Str "Pandoc" , Space , Str "Test" , Space , Str "Suite" ]+      , Para+          [ Str "John"+          , Space+          , Str "MacFarlane"+          , SoftBreak+          , Str "Anonymous"+          ]+      , Para+          [ Str "July" , Space , Str "17," , Space , Str "2006" ]+      , Para+          [ Str "This"+          , Space+          , Str "is"+          , Space+          , Str "a"+          , Space+          , Str "set"+          , Space+          , Str "of"+          , Space+          , Str "tests"+          , Space+          , Str "for"+          , Space+          , Str "pandoc."+          , Space+          , Str "Most"+          , Space+          , Str "of"+          , Space+          , Str "them"+          , Space+          , Str "are"+          , Space+          , Str "adapted"+          , Space+          , Str "from"+          , Space+          , Str "John"+          , Space+          , Str "Gruber\8217s"+          , SoftBreak+          , Str "markdown"+          , Space+          , Str "test"+          , Space+          , Str "suite."+          ]+      , HorizontalRule+      ]+  , Div+      ( "headers" , [ "section" ] , [] )+      [ Header 1 ( "" , [] , [] ) [ Str "Headers" ]+      , Div+          ( "level-2-with-an-embedded-link" , [ "section" ] , [] )+          [ Header+              2+              ( "" , [] , [] )+              [ Str "Level"+              , Space+              , Str "2"+              , Space+              , Str "with"+              , Space+              , Str "an"+              , Space+              , Link+                  ( "" , [] , [] )+                  [ Str "embedded" , Space , Str "link" ]+                  ( "/url" , "" )+              ]+          , Div+              ( "level-3-with-emphasis" , [ "section" ] , [] )+              [ Header+                  3+                  ( "" , [] , [] )+                  [ Str "Level"+                  , Space+                  , Str "3"+                  , Space+                  , Str "with"+                  , Space+                  , Emph [ Str "emphasis" ]+                  ]+              , Div+                  ( "level-4" , [ "section" ] , [] )+                  [ Header+                      4+                      ( "" , [] , [] )+                      [ Str "Level" , Space , Str "4" ]+                  , Div+                      ( "level-5" , [ "section" ] , [] )+                      [ Header+                          5+                          ( "" , [] , [] )+                          [ Str "Level" , Space , Str "5" ]+                      ]+                  ]+              ]+          ]+      ]+  , Div+      ( "level-1" , [ "section" ] , [] )+      [ Header+          1 ( "" , [] , [] ) [ Str "Level" , Space , Str "1" ]+      , Div+          ( "level-2-with-emphasis" , [ "section" ] , [] )+          [ Header+              2+              ( "" , [] , [] )+              [ Str "Level"+              , Space+              , Str "2"+              , Space+              , Str "with"+              , Space+              , Emph [ Str "emphasis" ]+              ]+          , Div+              ( "level-3" , [ "section" ] , [] )+              [ Header+                  3 ( "" , [] , [] ) [ Str "Level" , Space , Str "3" ]+              , Para+                  [ Str "with"+                  , Space+                  , Str "no"+                  , Space+                  , Str "blank"+                  , Space+                  , Str "line"+                  ]+              ]+          ]+      , Div+          ( "level-2" , [ "section" ] , [] )+          [ Header+              2 ( "" , [] , [] ) [ Str "Level" , Space , Str "2" ]+          , Para+              [ Str "with"+              , Space+              , Str "no"+              , Space+              , Str "blank"+              , Space+              , Str "line"+              ]+          , HorizontalRule+          ]+      ]+  , Div+      ( "paragraphs" , [ "section" ] , [] )+      [ Header 1 ( "" , [] , [] ) [ Str "Paragraphs" ]+      , Para+          [ Str "Here\8217s"+          , Space+          , Str "a"+          , Space+          , Str "regular"+          , Space+          , Str "paragraph."+          ]+      , Para+          [ Str "In"+          , Space+          , Str "Markdown"+          , Space+          , Str "1.0.0"+          , Space+          , Str "and"+          , Space+          , Str "earlier."+          , Space+          , Str "Version"+          , Space+          , Str "8."+          , Space+          , Str "This"+          , Space+          , Str "line"+          , Space+          , Str "turns"+          , Space+          , Str "into"+          , Space+          , Str "a"+          , Space+          , Str "list"+          , Space+          , Str "item."+          , SoftBreak+          , Str "Because"+          , Space+          , Str "a"+          , Space+          , Str "hard-wrapped"+          , Space+          , Str "line"+          , Space+          , Str "in"+          , Space+          , Str "the"+          , Space+          , Str "middle"+          , Space+          , Str "of"+          , Space+          , Str "a"+          , Space+          , Str "paragraph"+          , Space+          , Str "looked"+          , Space+          , Str "like"+          , Space+          , Str "a"+          , Space+          , Str "list"+          , SoftBreak+          , Str "item."+          ]+      , Para+          [ Str "Here\8217s"+          , Space+          , Str "one"+          , Space+          , Str "with"+          , Space+          , Str "a"+          , Space+          , Str "bullet."+          , Space+          , Str "*"+          , Space+          , Str "criminey."+          ]+      , Para+          [ Str "There"+          , Space+          , Str "should"+          , Space+          , Str "be"+          , Space+          , Str "a"+          , Space+          , Str "hard"+          , Space+          , Str "line"+          , Space+          , Str "break"+          , LineBreak+          , Str "here."+          ]+      , HorizontalRule+      ]+  , Div+      ( "block-quotes" , [ "section" ] , [] )+      [ Header+          1 ( "" , [] , [] ) [ Str "Block" , Space , Str "Quotes" ]+      , Para [ Str "E-mail" , Space , Str "style:" ]+      , BlockQuote+          [ Para+              [ Str "This"+              , Space+              , Str "is"+              , Space+              , Str "a"+              , Space+              , Str "block"+              , Space+              , Str "quote."+              , Space+              , Str "It"+              , Space+              , Str "is"+              , Space+              , Str "pretty"+              , Space+              , Str "short."+              ]+          ]+      , BlockQuote+          [ Para+              [ Str "Code"+              , Space+              , Str "in"+              , Space+              , Str "a"+              , Space+              , Str "block"+              , Space+              , Str "quote:"+              ]+          , CodeBlock+              ( "" , [ "" ] , [] )+              "sub status {\n    print \"working\";\n}\n"+          , Para [ Str "A" , Space , Str "list:" ]+          , OrderedList+              ( 1 , Decimal , Period )+              [ [ Plain [ Str "item" , Space , Str "one" ] ]+              , [ Plain [ Str "item" , Space , Str "two" ] ]+              ]+          , Para+              [ Str "Nested"+              , Space+              , Str "block"+              , Space+              , Str "quotes:"+              ]+          , BlockQuote [ Para [ Str "nested" ] ]+          , BlockQuote [ Para [ Str "nested" ] ]+          ]+      , Para+          [ Str "This"+          , Space+          , Str "should"+          , Space+          , Str "not"+          , Space+          , Str "be"+          , Space+          , Str "a"+          , Space+          , Str "block"+          , Space+          , Str "quote:"+          , Space+          , Str "2"+          , Space+          , Str ">"+          , Space+          , Str "1."+          ]+      , Para+          [ Str "And"+          , Space+          , Str "a"+          , Space+          , Str "following"+          , Space+          , Str "paragraph."+          ]+      , HorizontalRule+      ]+  , Div+      ( "code-blocks" , [ "section" ] , [] )+      [ Header+          1 ( "" , [] , [] ) [ Str "Code" , Space , Str "Blocks" ]+      , Para [ Str "Code:" ]+      , CodeBlock+          ( "" , [ "" ] , [] )+          "---- (should be four hyphens)\n\nsub status {\n    print \"working\";\n}\n\nthis code block is indented by one tab\n"+      , Para [ Str "And:" ]+      , CodeBlock+          ( "" , [ "" ] , [] )+          "    this code block is indented by two tabs\n\nThese should not be escaped:  \\$ \\\\ \\> \\[ \\{\n"+      , HorizontalRule+      ]+  , Div+      ( "lists" , [ "section" ] , [] )+      [ Header 1 ( "" , [] , [] ) [ Str "Lists" ]+      , Div+          ( "unordered" , [ "section" ] , [] )+          [ Header 2 ( "" , [] , [] ) [ Str "Unordered" ]+          , Para [ Str "Asterisks" , Space , Str "tight:" ]+          , BulletList+              [ [ Plain [ Str "asterisk" , Space , Str "1" ] ]+              , [ Plain [ Str "asterisk" , Space , Str "2" ] ]+              , [ Plain [ Str "asterisk" , Space , Str "3" ] ]+              ]+          , Para [ Str "Asterisks" , Space , Str "loose:" ]+          , BulletList+              [ [ Para [ Str "asterisk" , Space , Str "1" ] ]+              , [ Para [ Str "asterisk" , Space , Str "2" ] ]+              , [ Para [ Str "asterisk" , Space , Str "3" ] ]+              ]+          , Para [ Str "Pluses" , Space , Str "tight:" ]+          , BulletList+              [ [ Plain [ Str "Plus" , Space , Str "1" ] ]+              , [ Plain [ Str "Plus" , Space , Str "2" ] ]+              , [ Plain [ Str "Plus" , Space , Str "3" ] ]+              ]+          , Para [ Str "Pluses" , Space , Str "loose:" ]+          , BulletList+              [ [ Para [ Str "Plus" , Space , Str "1" ] ]+              , [ Para [ Str "Plus" , Space , Str "2" ] ]+              , [ Para [ Str "Plus" , Space , Str "3" ] ]+              ]+          , Para [ Str "Minuses" , Space , Str "tight:" ]+          , BulletList+              [ [ Plain [ Str "Minus" , Space , Str "1" ] ]+              , [ Plain [ Str "Minus" , Space , Str "2" ] ]+              , [ Plain [ Str "Minus" , Space , Str "3" ] ]+              ]+          , Para [ Str "Minuses" , Space , Str "loose:" ]+          , BulletList+              [ [ Para [ Str "Minus" , Space , Str "1" ] ]+              , [ Para [ Str "Minus" , Space , Str "2" ] ]+              , [ Para [ Str "Minus" , Space , Str "3" ] ]+              ]+          ]+      , Div+          ( "ordered" , [ "section" ] , [] )+          [ Header 2 ( "" , [] , [] ) [ Str "Ordered" ]+          , Para [ Str "Tight:" ]+          , OrderedList+              ( 1 , Decimal , Period )+              [ [ Plain [ Str "First" ] ]+              , [ Plain [ Str "Second" ] ]+              , [ Plain [ Str "Third" ] ]+              ]+          , Para [ Str "and:" ]+          , OrderedList+              ( 1 , Decimal , Period )+              [ [ Plain [ Str "One" ] ]+              , [ Plain [ Str "Two" ] ]+              , [ Plain [ Str "Three" ] ]+              ]+          , Para+              [ Str "Loose"+              , Space+              , Str "using"+              , Space+              , Str "tabs:"+              ]+          , OrderedList+              ( 1 , Decimal , Period )+              [ [ Para [ Str "First" ] ]+              , [ Para [ Str "Second" ] ]+              , [ Para [ Str "Third" ] ]+              ]+          , Para+              [ Str "and"+              , Space+              , Str "using"+              , Space+              , Str "spaces:"+              ]+          , OrderedList+              ( 1 , Decimal , Period )+              [ [ Para [ Str "One" ] ]+              , [ Para [ Str "Two" ] ]+              , [ Para [ Str "Three" ] ]+              ]+          , Para [ Str "Multiple" , Space , Str "paragraphs:" ]+          , OrderedList+              ( 1 , Decimal , Period )+              [ [ Para+                    [ Str "Item"+                    , Space+                    , Str "1,"+                    , Space+                    , Str "graf"+                    , Space+                    , Str "one."+                    ]+                , Para+                    [ Str "Item"+                    , Space+                    , Str "1."+                    , Space+                    , Str "graf"+                    , Space+                    , Str "two."+                    , Space+                    , Str "The"+                    , Space+                    , Str "quick"+                    , Space+                    , Str "brown"+                    , Space+                    , Str "fox"+                    , Space+                    , Str "jumped"+                    , Space+                    , Str "over"+                    , Space+                    , Str "the"+                    , Space+                    , Str "lazy"+                    , Space+                    , Str "dog\8217s"+                    , Space+                    , Str "back."+                    ]+                ]+              , [ Para [ Str "Item" , Space , Str "2." ] ]+              , [ Para [ Str "Item" , Space , Str "3." ] ]+              ]+          ]+      , Div+          ( "nested" , [ "section" ] , [] )+          [ Header 2 ( "" , [] , [] ) [ Str "Nested" ]+          , BulletList+              [ [ Plain [ Str "Tab" ]+                , BulletList+                    [ [ Plain [ Str "Tab" ]+                      , BulletList [ [ Plain [ Str "Tab" ] ] ]+                      ]+                    ]+                ]+              ]+          , Para [ Str "Here\8217s" , Space , Str "another:" ]+          , OrderedList+              ( 1 , Decimal , Period )+              [ [ Plain [ Str "First" ] ]+              , [ Plain [ Str "Second:" ]+                , BulletList+                    [ [ Plain [ Str "Fee" ] ]+                    , [ Plain [ Str "Fie" ] ]+                    , [ Plain [ Str "Foe" ] ]+                    ]+                ]+              , [ Plain [ Str "Third" ] ]+              ]+          , Para+              [ Str "Same"+              , Space+              , Str "thing"+              , Space+              , Str "but"+              , Space+              , Str "with"+              , Space+              , Str "paragraphs:"+              ]+          , OrderedList+              ( 1 , Decimal , Period )+              [ [ Para [ Str "First" ] ]+              , [ Para [ Str "Second:" ]+                , BulletList+                    [ [ Plain [ Str "Fee" ] ]+                    , [ Plain [ Str "Fie" ] ]+                    , [ Plain [ Str "Foe" ] ]+                    ]+                ]+              , [ Para [ Str "Third" ] ]+              ]+          ]+      , Div+          ( "tabs-and-spaces" , [ "section" ] , [] )+          [ Header+              2+              ( "" , [] , [] )+              [ Str "Tabs" , Space , Str "and" , Space , Str "spaces" ]+          , BulletList+              [ [ Para+                    [ Str "this"+                    , Space+                    , Str "is"+                    , Space+                    , Str "a"+                    , Space+                    , Str "list"+                    , Space+                    , Str "item"+                    , Space+                    , Str "indented"+                    , Space+                    , Str "with"+                    , Space+                    , Str "tabs"+                    ]+                ]+              , [ Para+                    [ Str "this"+                    , Space+                    , Str "is"+                    , Space+                    , Str "a"+                    , Space+                    , Str "list"+                    , Space+                    , Str "item"+                    , Space+                    , Str "indented"+                    , Space+                    , Str "with"+                    , Space+                    , Str "spaces"+                    ]+                , BulletList+                    [ [ Para+                          [ Str "this"+                          , Space+                          , Str "is"+                          , Space+                          , Str "an"+                          , Space+                          , Str "example"+                          , Space+                          , Str "list"+                          , Space+                          , Str "item"+                          , Space+                          , Str "indented"+                          , Space+                          , Str "with"+                          , Space+                          , Str "tabs"+                          ]+                      ]+                    , [ Para+                          [ Str "this"+                          , Space+                          , Str "is"+                          , Space+                          , Str "an"+                          , Space+                          , Str "example"+                          , Space+                          , Str "list"+                          , Space+                          , Str "item"+                          , Space+                          , Str "indented"+                          , Space+                          , Str "with"+                          , Space+                          , Str "spaces"+                          ]+                      ]+                    ]+                ]+              ]+          ]+      , Div+          ( "fancy-list-markers" , [ "section" ] , [] )+          [ Header+              2+              ( "" , [] , [] )+              [ Str "Fancy"+              , Space+              , Str "list"+              , Space+              , Str "markers"+              ]+          , OrderedList+              ( 2 , Decimal , TwoParens )+              [ [ Para+                    [ Str "begins"+                    , Space+                    , Str "with"+                    , Space+                    , Str "2"+                    ]+                ]+              , [ Para+                    [ Str "and" , Space , Str "now" , Space , Str "3" ]+                , Para+                    [ Str "with"+                    , Space+                    , Str "a"+                    , Space+                    , Str "continuation"+                    ]+                , OrderedList+                    ( 4 , LowerRoman , Period )+                    [ [ Plain+                          [ Str "sublist"+                          , Space+                          , Str "with"+                          , Space+                          , Str "roman"+                          , Space+                          , Str "numerals,"+                          , Space+                          , Str "starting"+                          , Space+                          , Str "with"+                          , Space+                          , Str "4"+                          ]+                      ]+                    , [ Plain [ Str "more" , Space , Str "items" ]+                      , OrderedList+                          ( 1 , UpperAlpha , TwoParens )+                          [ [ Plain+                                [ Str "a" , Space , Str "subsublist" ]+                            ]+                          , [ Plain+                                [ Str "a" , Space , Str "subsublist" ]+                            ]+                          ]+                      ]+                    ]+                ]+              ]+          , Para [ Str "Nesting:" ]+          , OrderedList+              ( 1 , UpperAlpha , Period )+              [ [ Plain [ Str "Upper" , Space , Str "Alpha" ]+                , OrderedList+                    ( 1 , UpperRoman , Period )+                    [ [ Plain [ Str "Upper" , Space , Str "Roman." ]+                      , OrderedList+                          ( 6 , Decimal , TwoParens )+                          [ [ Plain+                                [ Str "Decimal"+                                , Space+                                , Str "start"+                                , Space+                                , Str "with"+                                , Space+                                , Str "6"+                                ]+                            , OrderedList+                                ( 3 , LowerAlpha , OneParen )+                                [ [ Plain+                                      [ Str "Lower"+                                      , Space+                                      , Str "alpha"+                                      , Space+                                      , Str "with"+                                      , Space+                                      , Str "paren"+                                      ]+                                  ]+                                ]+                            ]+                          ]+                      ]+                    ]+                ]+              ]+          , Para [ Str "Autonumbering:" ]+          , OrderedList+              ( 1 , Decimal , Period )+              [ [ Plain [ Str "Autonumber." ] ]+              , [ Plain [ Str "More." ]+                , OrderedList+                    ( 1 , Decimal , Period )+                    [ [ Plain [ Str "Nested." ] ] ]+                ]+              ]+          , Para+              [ Str "Should"+              , Space+              , Str "not"+              , Space+              , Str "be"+              , Space+              , Str "a"+              , Space+              , Str "list"+              , Space+              , Str "item:"+              ]+          , Para [ Str "M.A.\160\&2007" ]+          , OrderedList+              ( 2 , UpperAlpha , Period )+              [ [ Plain [ Str "Williams" ] ] ]+          , HorizontalRule+          ]+      ]+  , Div+      ( "definition-lists" , [ "section" ] , [] )+      [ Header+          1+          ( "" , [] , [] )+          [ Str "Definition" , Space , Str "Lists" ]+      , Para+          [ Str "Tight"+          , Space+          , Str "using"+          , Space+          , Str "spaces:"+          ]+      , DefinitionList+          [ ( [ Str "apple" ]+            , [ [ Plain [ Str "red" , Space , Str "fruit" ] ] ]+            )+          , ( [ Str "orange" ]+            , [ [ Plain [ Str "orange" , Space , Str "fruit" ] ] ]+            )+          , ( [ Str "banana" ]+            , [ [ Plain [ Str "yellow" , Space , Str "fruit" ] ] ]+            )+          ]+      , Para+          [ Str "Tight" , Space , Str "using" , Space , Str "tabs:" ]+      , DefinitionList+          [ ( [ Str "apple" ]+            , [ [ Plain [ Str "red" , Space , Str "fruit" ] ] ]+            )+          , ( [ Str "orange" ]+            , [ [ Plain [ Str "orange" , Space , Str "fruit" ] ] ]+            )+          , ( [ Str "banana" ]+            , [ [ Plain [ Str "yellow" , Space , Str "fruit" ] ] ]+            )+          ]+      , Para [ Str "Loose:" ]+      , DefinitionList+          [ ( [ Str "apple" ]+            , [ [ Para [ Str "red" , Space , Str "fruit" ] ] ]+            )+          , ( [ Str "orange" ]+            , [ [ Para [ Str "orange" , Space , Str "fruit" ] ] ]+            )+          , ( [ Str "banana" ]+            , [ [ Para [ Str "yellow" , Space , Str "fruit" ] ] ]+            )+          ]+      , Para+          [ Str "Multiple"+          , Space+          , Str "blocks"+          , Space+          , Str "with"+          , Space+          , Str "italics:"+          ]+      , DefinitionList+          [ ( [ Emph [ Str "apple" ] ]+            , [ [ Para [ Str "red" , Space , Str "fruit" ]+                , Para+                    [ Str "contains"+                    , Space+                    , Str "seeds,"+                    , Space+                    , Str "crisp,"+                    , Space+                    , Str "pleasant"+                    , Space+                    , Str "to"+                    , Space+                    , Str "taste"+                    ]+                ]+              ]+            )+          , ( [ Emph [ Str "orange" ] ]+            , [ [ Para [ Str "orange" , Space , Str "fruit" ]+                , CodeBlock+                    ( "" , [ "" ] , [] ) "{ orange code block }\n"+                , BlockQuote+                    [ Para+                        [ Str "orange"+                        , Space+                        , Str "block"+                        , Space+                        , Str "quote"+                        ]+                    ]+                ]+              ]+            )+          ]+      , Para+          [ Str "Multiple"+          , Space+          , Str "definitions,"+          , Space+          , Str "tight:"+          ]+      , DefinitionList+          [ ( [ Str "apple" ]+            , [ [ Para [ Str "red" , Space , Str "fruit" ]+                , Para [ Str "computer" ]+                ]+              ]+            )+          , ( [ Str "orange" ]+            , [ [ Para [ Str "orange" , Space , Str "fruit" ]+                , Para [ Str "bank" ]+                ]+              ]+            )+          ]+      , Para+          [ Str "Multiple"+          , Space+          , Str "definitions,"+          , Space+          , Str "loose:"+          ]+      , DefinitionList+          [ ( [ Str "apple" ]+            , [ [ Para [ Str "red" , Space , Str "fruit" ]+                , Para [ Str "computer" ]+                ]+              ]+            )+          , ( [ Str "orange" ]+            , [ [ Para [ Str "orange" , Space , Str "fruit" ]+                , Para [ Str "bank" ]+                ]+              ]+            )+          ]+      , Para+          [ Str "Blank"+          , Space+          , Str "line"+          , Space+          , Str "after"+          , Space+          , Str "term,"+          , Space+          , Str "indented"+          , Space+          , Str "marker,"+          , Space+          , Str "alternate"+          , Space+          , Str "markers:"+          ]+      , DefinitionList+          [ ( [ Str "apple" ]+            , [ [ Para [ Str "red" , Space , Str "fruit" ]+                , Para [ Str "computer" ]+                ]+              ]+            )+          , ( [ Str "orange" ]+            , [ [ Para [ Str "orange" , Space , Str "fruit" ]+                , OrderedList+                    ( 1 , Decimal , Period )+                    [ [ Plain [ Str "sublist" ] ]+                    , [ Plain [ Str "sublist" ] ]+                    ]+                ]+              ]+            )+          ]+      ]+  , Div+      ( "html-blocks" , [ "section" ] , [] )+      [ Header+          1 ( "" , [] , [] ) [ Str "HTML" , Space , Str "Blocks" ]+      , Para+          [ Str "Simple"+          , Space+          , Str "block"+          , Space+          , Str "on"+          , Space+          , Str "one"+          , Space+          , Str "line:"+          ]+      , Div ( "" , [] , [] ) [ Para [ Str "foo" ] ]+      , Para+          [ Str "And"+          , Space+          , Str "nested"+          , Space+          , Str "without"+          , Space+          , Str "indentation:"+          ]+      , Div+          ( "" , [] , [] )+          [ Div+              ( "" , [] , [] )+              [ Div ( "" , [] , [] ) [ Para [ Str "foo" ] ] ]+          , Div ( "" , [] , [] ) [ Para [ Str "bar" ] ]+          ]+      , Para+          [ Str "Interpreted"+          , Space+          , Str "markdown"+          , Space+          , Str "in"+          , Space+          , Str "a"+          , Space+          , Str "table:"+          ]+      , Para+          [ Str "This"+          , Space+          , Str "is"+          , Space+          , Emph [ Str "emphasized" ]+          ]+      , Para+          [ Str "And"+          , Space+          , Str "this"+          , Space+          , Str "is"+          , Space+          , Strong [ Str "strong" ]+          ]+      , Para+          [ Str "Here\8217s"+          , Space+          , Str "a"+          , Space+          , Str "simple"+          , Space+          , Str "block:"+          ]+      , Div ( "" , [] , [] ) [ Para [ Str "foo" ] ]+      , Para+          [ Str "This"+          , Space+          , Str "should"+          , Space+          , Str "be"+          , Space+          , Str "a"+          , Space+          , Str "code"+          , Space+          , Str "block,"+          , Space+          , Str "though:"+          ]+      , CodeBlock ( "" , [ "" ] , [] ) "<div>\n    foo\n</div>\n"+      , Para+          [ Str "As" , Space , Str "should" , Space , Str "this:" ]+      , CodeBlock ( "" , [ "" ] , [] ) "<div>foo</div>\n"+      , Para [ Str "Now," , Space , Str "nested:" ]+      , Div+          ( "" , [] , [] )+          [ Div+              ( "" , [] , [] )+              [ Div ( "" , [] , [] ) [ Para [ Str "foo" ] ] ]+          ]+      , Para+          [ Str "This"+          , Space+          , Str "should"+          , Space+          , Str "just"+          , Space+          , Str "be"+          , Space+          , Str "an"+          , Space+          , Str "HTML"+          , Space+          , Str "comment:"+          ]+      , Para [ Str "Multiline:" ]+      , Para [ Str "Code" , Space , Str "block:" ]+      , CodeBlock ( "" , [ "" ] , [] ) "<!-- Comment -->\n"+      , Para+          [ Str "Just"+          , Space+          , Str "plain"+          , Space+          , Str "comment,"+          , Space+          , Str "with"+          , Space+          , Str "trailing"+          , Space+          , Str "spaces"+          , Space+          , Str "on"+          , Space+          , Str "the"+          , Space+          , Str "line:"+          ]+      , Para [ Str "Code:" ]+      , CodeBlock ( "" , [ "" ] , [] ) "<hr />\n"+      , Para [ Str "Hr\8217s:" ]+      , HorizontalRule+      ]+  , Div+      ( "inline-markup" , [ "section" ] , [] )+      [ Header+          1 ( "" , [] , [] ) [ Str "Inline" , Space , Str "Markup" ]+      , Para+          [ Str "This"+          , Space+          , Str "is"+          , Space+          , Emph [ Str "emphasized" ]+          , Str ","+          , Space+          , Str "and"+          , Space+          , Str "so"+          , Space+          , Emph [ Str "is" , Space , Str "this" ]+          , Str "."+          ]+      , Para+          [ Str "This"+          , Space+          , Str "is"+          , Space+          , Strong [ Str "strong" ]+          , Str ","+          , Space+          , Str "and"+          , Space+          , Str "so"+          , Space+          , Strong [ Str "is" , Space , Str "this" ]+          , Str "."+          ]+      , Para+          [ Str "An"+          , Space+          , Emph+              [ Link+                  ( "" , [] , [] )+                  [ Str "emphasized" , Space , Str "link" ]+                  ( "/url" , "" )+              ]+          , Str "."+          ]+      , Para+          [ Strong+              [ Emph+                  [ Str "This"+                  , Space+                  , Str "is"+                  , Space+                  , Str "strong"+                  , Space+                  , Str "and"+                  , Space+                  , Str "em."+                  ]+              ]+          ]+      , Para+          [ Str "So"+          , Space+          , Str "is"+          , Space+          , Strong [ Emph [ Str "this" ] ]+          , Space+          , Str "word."+          ]+      , Para+          [ Strong+              [ Emph+                  [ Str "This"+                  , Space+                  , Str "is"+                  , Space+                  , Str "strong"+                  , Space+                  , Str "and"+                  , Space+                  , Str "em."+                  ]+              ]+          ]+      , Para+          [ Str "So"+          , Space+          , Str "is"+          , Space+          , Strong [ Emph [ Str "this" ] ]+          , Space+          , Str "word."+          ]+      , Para+          [ Str "This"+          , Space+          , Str "is"+          , Space+          , Str "code:"+          , Space+          , Code ( "" , [] , [] ) ">"+          , Str ","+          , Space+          , Code ( "" , [] , [] ) "$"+          , Str ","+          , Space+          , Code ( "" , [] , [] ) "\\`, "+          , Str "$"+          , Code ( "" , [] , [] ) ", "+          , Str "<html>"+          , Code ( "" , [] , [] ) "."+          ]+      , Para+          [ Span+              ( "" , [ "deleted" ] , [] )+              [ Str "This"+              , Space+              , Str "is"+              , Space+              , Emph [ Str "strikeout" ]+              , Str "."+              ]+          ]+      , Para+          [ Str "Superscripts:"+          , Space+          , Str "a"+          , Superscript [ Str "bc" ]+          , Str "d"+          , Space+          , Str "a"+          , Superscript [ Emph [ Str "hello" ] ]+          , Space+          , Str "a"+          , Superscript [ Str "hello\160there" ]+          , Str "."+          ]+      , Para+          [ Str "Subscripts:"+          , Space+          , Str "H"+          , Subscript [ Str "2" ]+          , Str "O,"+          , Space+          , Str "H"+          , Subscript [ Str "23" ]+          , Str "O,"+          , Space+          , Str "H"+          , Subscript [ Str "many\160of\160them" ]+          , Str "O."+          ]+      , Para+          [ Str "These"+          , Space+          , Str "should"+          , Space+          , Str "not"+          , Space+          , Str "be"+          , Space+          , Str "superscripts"+          , Space+          , Str "or"+          , Space+          , Str "subscripts,"+          , Space+          , Str "because"+          , Space+          , Str "of"+          , Space+          , Str "the"+          , Space+          , Str "unescaped"+          , Space+          , Str "spaces:"+          , SoftBreak+          , Str "a^b"+          , Space+          , Str "c^d,"+          , Space+          , Str "a~b"+          , Space+          , Str "c~d."+          ]+      , HorizontalRule+      ]+  , Div+      ( "smart-quotes-ellipses-dashes" , [ "section" ] , [] )+      [ Header+          1+          ( "" , [] , [] )+          [ Str "Smart"+          , Space+          , Str "quotes,"+          , Space+          , Str "ellipses,"+          , Space+          , Str "dashes"+          ]+      , Para+          [ Quoted DoubleQuote [ Str "Hello," ]+          , Space+          , Str "said"+          , Space+          , Str "the"+          , Space+          , Str "spider."+          , Space+          , Quoted+              DoubleQuote+              [ Quoted SingleQuote [ Str "Shelob" ]+              , Space+              , Str "is"+              , Space+              , Str "my"+              , Space+              , Str "name."+              ]+          ]+      , Para+          [ Quoted SingleQuote [ Str "A" ]+          , Str ","+          , Space+          , Quoted SingleQuote [ Str "B" ]+          , Str ","+          , Space+          , Str "and"+          , Space+          , Quoted SingleQuote [ Str "C" ]+          , Space+          , Str "are"+          , Space+          , Str "letters."+          ]+      , Para+          [ Quoted SingleQuote [ Str "Oak," ]+          , Space+          , Quoted SingleQuote [ Str "elm," ]+          , Space+          , Str "and"+          , Space+          , Quoted SingleQuote [ Str "beech" ]+          , Space+          , Str "are"+          , Space+          , Str "names"+          , Space+          , Str "of"+          , Space+          , Str "trees."+          , Space+          , Str "So"+          , Space+          , Str "is"+          , Space+          , Quoted SingleQuote [ Str "pine." ]+          ]+      , Para+          [ Quoted+              SingleQuote+              [ Str "He"+              , Space+              , Str "said,"+              , Space+              , Quoted+                  DoubleQuote+                  [ Str "I"+                  , Space+                  , Str "want"+                  , Space+                  , Str "to"+                  , Space+                  , Str "go."+                  ]+              ]+          , Space+          , Str "Were"+          , Space+          , Str "you"+          , Space+          , Str "alive"+          , Space+          , Str "in"+          , Space+          , Str "the"+          , Space+          , Str "70\8217s?"+          ]+      , Para+          [ Str "Here"+          , Space+          , Str "is"+          , Space+          , Str "some"+          , Space+          , Str "quoted"+          , Space+          , Quoted SingleQuote [ Code ( "" , [] , [] ) "code" ]+          , Space+          , Str "and"+          , Space+          , Str "a"+          , Space+          , Quoted+              DoubleQuote+              [ Link+                  ( "" , [] , [] )+                  [ Str "quoted" , SoftBreak , Str "link" ]+                  ( "http://example.com/?foo=1&bar=2" , "" )+              ]+          , Str "."+          ]+      , Para+          [ Str "Some"+          , Space+          , Str "dashes:"+          , Space+          , Str "one\8212two"+          , Space+          , Str "\8212"+          , Space+          , Str "three\8212four"+          , Space+          , Str "\8212"+          , Space+          , Str "five."+          ]+      , Para+          [ Str "Dashes"+          , Space+          , Str "between"+          , Space+          , Str "numbers:"+          , Space+          , Str "5\8211\&7,"+          , Space+          , Str "255\8211\&66,"+          , Space+          , Str "1987\8211\&1999."+          ]+      , Para [ Str "Ellipses\8230and\8230and\8230." ]+      , HorizontalRule+      ]+  , Div+      ( "latex" , [ "section" ] , [] )+      [ Header 1 ( "" , [] , [] ) [ Str "LaTeX" ]+      , BulletList+          [ []+          , [ Plain [ Math InlineMath "2+2=4" ] ]+          , [ Plain [ Math InlineMath "x \\in y" ] ]+          , [ Plain [ Math InlineMath "\\alpha \\wedge \\omega" ] ]+          , [ Plain [ Math InlineMath "223" ] ]+          , [ Plain [ Math InlineMath "p" , Str "-Tree" ] ]+          , [ Plain+                [ Str "Here\8217s"+                , Space+                , Str "some"+                , Space+                , Str "display"+                , Space+                , Str "math:"+                , SoftBreak+                , Math+                    DisplayMath+                    "\\frac{d}{dx}f(x)=\\lim_{h\\to 0}\\frac{f(x+h)-f(x)}{h}"+                ]+            ]+          , [ Plain+                [ Str "Here\8217s"+                , Space+                , Str "one"+                , Space+                , Str "that"+                , Space+                , Str "has"+                , Space+                , Str "a"+                , Space+                , Str "line"+                , Space+                , Str "break"+                , Space+                , Str "in"+                , Space+                , Str "it:"+                , Space+                , Math InlineMath "\\alpha + \\omega \\times x^2"+                , Str "."+                ]+            ]+          ]+      , Para+          [ Str "These"+          , Space+          , Str "shouldn\8217t"+          , Space+          , Str "be"+          , Space+          , Str "math:"+          ]+      , BulletList+          [ [ Plain+                [ Str "To"+                , Space+                , Str "get"+                , Space+                , Str "the"+                , Space+                , Str "famous"+                , Space+                , Str "equation,"+                , Space+                , Str "write"+                , Space+                , Code ( "" , [] , [] ) "$e = mc^2$"+                , Str "."+                ]+            ]+          , [ Plain+                [ Str "$22,000"+                , Space+                , Str "is"+                , Space+                , Str "a"+                , Space+                , Emph [ Str "lot" ]+                , Space+                , Str "of"+                , Space+                , Str "money."+                , Space+                , Str "So"+                , Space+                , Str "is"+                , Space+                , Str "$34,000."+                , Space+                , Str "(It"+                , Space+                , Str "worked"+                , Space+                , Str "if"+                , Space+                , Quoted DoubleQuote [ Str "lot" ]+                , Space+                , Str "is"+                , SoftBreak+                , Str "emphasized.)"+                ]+            ]+          , [ Plain+                [ Str "Shoes"+                , Space+                , Str "($20)"+                , Space+                , Str "and"+                , Space+                , Str "socks"+                , Space+                , Str "($5)."+                ]+            ]+          , [ Plain+                [ Str "Escaped"+                , Space+                , Code ( "" , [] , [] ) "$"+                , Str ":"+                , Space+                , Str "$73"+                , Space+                , Emph+                    [ Str "this"+                    , Space+                    , Str "should"+                    , Space+                    , Str "be"+                    , Space+                    , Str "emphasized"+                    ]+                , Space+                , Str "23$."+                ]+            ]+          ]+      , Para+          [ Str "Here\8217s"+          , Space+          , Str "a"+          , Space+          , Str "LaTeX"+          , Space+          , Str "table:"+          ]+      , HorizontalRule+      ]+  , Div+      ( "special-characters" , [ "section" ] , [] )+      [ Header+          1+          ( "" , [] , [] )+          [ Str "Special" , Space , Str "Characters" ]+      , Para+          [ Str "Here"+          , Space+          , Str "is"+          , Space+          , Str "some"+          , Space+          , Str "unicode:"+          ]+      , BulletList+          [ [ Plain+                [ Str "I" , Space , Str "hat:" , Space , Str "\206" ]+            ]+          , [ Plain+                [ Str "o" , Space , Str "umlaut:" , Space , Str "\246" ]+            ]+          , [ Plain [ Str "section:" , Space , Str "\167" ] ]+          , [ Plain+                [ Str "set"+                , Space+                , Str "membership:"+                , Space+                , Str "\8712"+                ]+            ]+          , [ Plain [ Str "copyright:" , Space , Str "\169" ] ]+          ]+      , Para+          [ Str "AT&T"+          , Space+          , Str "has"+          , Space+          , Str "an"+          , Space+          , Str "ampersand"+          , Space+          , Str "in"+          , Space+          , Str "their"+          , Space+          , Str "name."+          ]+      , Para+          [ Str "AT&T"+          , Space+          , Str "is"+          , Space+          , Str "another"+          , Space+          , Str "way"+          , Space+          , Str "to"+          , Space+          , Str "write"+          , Space+          , Str "it."+          ]+      , Para+          [ Str "This" , Space , Str "&" , Space , Str "that." ]+      , Para [ Str "4" , Space , Str "<" , Space , Str "5." ]+      , Para [ Str "6" , Space , Str ">" , Space , Str "5." ]+      , Para [ Str "Backslash:" , Space , Str "\\" ]+      , Para [ Str "Backtick:" , Space , Str "`" ]+      , Para [ Str "Asterisk:" , Space , Str "*" ]+      , Para [ Str "Underscore:" , Space , Str "_" ]+      , Para+          [ Str "Left" , Space , Str "brace:" , Space , Str "{" ]+      , Para+          [ Str "Right" , Space , Str "brace:" , Space , Str "}" ]+      , Para+          [ Str "Left" , Space , Str "bracket:" , Space , Str "[" ]+      , Para+          [ Str "Right" , Space , Str "bracket:" , Space , Str "]" ]+      , Para+          [ Str "Left" , Space , Str "paren:" , Space , Str "(" ]+      , Para+          [ Str "Right" , Space , Str "paren:" , Space , Str ")" ]+      , Para [ Str "Greater-than:" , Space , Str ">" ]+      , Para [ Str "Hash:" , Space , Str "#" ]+      , Para [ Str "Period:" , Space , Str "." ]+      , Para [ Str "Bang:" , Space , Str "!" ]+      , Para [ Str "Plus:" , Space , Str "+" ]+      , Para [ Str "Minus:" , Space , Str "-" ]+      , HorizontalRule+      ]+  , Div+      ( "links" , [ "section" ] , [] )+      [ Header 1 ( "" , [] , [] ) [ Str "Links" ]+      , Div+          ( "explicit" , [ "section" ] , [] )+          [ Header 2 ( "" , [] , [] ) [ Str "Explicit" ]+          , Para+              [ Str "Just"+              , Space+              , Str "a"+              , Space+              , Link ( "" , [] , [] ) [ Str "URL" ] ( "/url/" , "" )+              , Str "."+              ]+          , Para+              [ Link+                  ( "" , [] , [ ( "title" , "title" ) ] )+                  [ Str "URL"+                  , Space+                  , Str "and"+                  , Space+                  , Str "title"+                  ]+                  ( "/url/" , "" )+              , Str "."+              ]+          , Para+              [ Link+                  ( ""+                  , []+                  , [ ( "title" , "title preceded by two spaces" ) ]+                  )+                  [ Str "URL"+                  , Space+                  , Str "and"+                  , Space+                  , Str "title"+                  ]+                  ( "/url/" , "" )+              , Str "."+              ]+          , Para+              [ Link+                  ( ""+                  , []+                  , [ ( "title" , "title preceded by a tab" ) ]+                  )+                  [ Str "URL"+                  , Space+                  , Str "and"+                  , Space+                  , Str "title"+                  ]+                  ( "/url/" , "" )+              , Str "."+              ]+          , Para+              [ Link+                  ( ""+                  , []+                  , [ ( "title" , "title with \"quotes\" in it" ) ]+                  )+                  [ Str "URL"+                  , Space+                  , Str "and"+                  , Space+                  , Str "title"+                  ]+                  ( "/url/" , "" )+              ]+          , Para+              [ Link+                  ( ""+                  , []+                  , [ ( "title" , "title with single quotes" ) ]+                  )+                  [ Str "URL"+                  , Space+                  , Str "and"+                  , Space+                  , Str "title"+                  ]+                  ( "/url/" , "" )+              ]+          , Para+              [ Link+                  ( "" , [] , [] )+                  [ Str "with_underscore" ]+                  ( "/url/with_underscore" , "" )+              ]+          , Para+              [ Link+                  ( "" , [] , [] )+                  [ Str "Email" , Space , Str "link" ]+                  ( "mailto:nobody@nowhere.net" , "" )+              ]+          , Para+              [ Link ( "" , [] , [] ) [ Str "Empty" ] ( "" , "" )+              , Str "."+              ]+          ]+      , Div+          ( "reference" , [ "section" ] , [] )+          [ Header 2 ( "" , [] , [] ) [ Str "Reference" ]+          , Para+              [ Str "Foo"+              , Space+              , Link ( "" , [] , [] ) [ Str "bar" ] ( "/url/" , "" )+              , Str "."+              ]+          , Para+              [ Str "With"+              , Space+              , Link+                  ( "" , [] , [] )+                  [ Str "embedded" , Space , Str "[brackets]" ]+                  ( "/url/" , "" )+              , Str "."+              ]+          , Para+              [ Link ( "" , [] , [] ) [ Str "b" ] ( "/url/" , "" )+              , Space+              , Str "by"+              , Space+              , Str "itself"+              , Space+              , Str "should"+              , Space+              , Str "be"+              , Space+              , Str "a"+              , Space+              , Str "link."+              ]+          , Para+              [ Str "Indented"+              , Space+              , Link ( "" , [] , [] ) [ Str "once" ] ( "/url" , "" )+              , Str "."+              ]+          , Para+              [ Str "Indented"+              , Space+              , Link ( "" , [] , [] ) [ Str "twice" ] ( "/url" , "" )+              , Str "."+              ]+          , Para+              [ Str "Indented"+              , Space+              , Link ( "" , [] , [] ) [ Str "thrice" ] ( "/url" , "" )+              , Str "."+              ]+          , Para+              [ Str "This"+              , Space+              , Str "should"+              , Space+              , Str "[not][]"+              , Space+              , Str "be"+              , Space+              , Str "a"+              , Space+              , Str "link."+              ]+          , CodeBlock ( "" , [ "" ] , [] ) "[not]: /url\n"+          , Para+              [ Str "Foo"+              , Space+              , Link+                  ( ""+                  , []+                  , [ ( "title" , "Title with \"quotes\" inside" ) ]+                  )+                  [ Str "bar" ]+                  ( "/url/" , "" )+              , Str "."+              ]+          , Para+              [ Str "Foo"+              , Space+              , Link+                  ( ""+                  , []+                  , [ ( "title" , "Title with \"quote\" inside" ) ]+                  )+                  [ Str "biz" ]+                  ( "/url/" , "" )+              , Str "."+              ]+          ]+      , Div+          ( "with-ampersands" , [ "section" ] , [] )+          [ Header+              2+              ( "" , [] , [] )+              [ Str "With" , Space , Str "ampersands" ]+          , Para+              [ Str "Here\8217s"+              , Space+              , Str "a"+              , Space+              , Link+                  ( "" , [] , [] )+                  [ Str "link"+                  , Space+                  , Str "with"+                  , Space+                  , Str "an"+                  , Space+                  , Str "ampersand"+                  , Space+                  , Str "in"+                  , Space+                  , Str "the"+                  , Space+                  , Str "URL"+                  ]+                  ( "http://example.com/?foo=1&bar=2" , "" )+              , Str "."+              ]+          , Para+              [ Str "Here\8217s"+              , Space+              , Str "a"+              , Space+              , Str "link"+              , Space+              , Str "with"+              , Space+              , Str "an"+              , Space+              , Str "amersand"+              , Space+              , Str "in"+              , Space+              , Str "the"+              , Space+              , Str "link"+              , Space+              , Str "text:"+              , SoftBreak+              , Link+                  ( "" , [] , [ ( "title" , "AT&T" ) ] )+                  [ Str "AT&T" ]+                  ( "http://att.com/" , "" )+              , Str "."+              ]+          , Para+              [ Str "Here\8217s"+              , Space+              , Str "an"+              , Space+              , Link+                  ( "" , [] , [] )+                  [ Str "inline" , Space , Str "link" ]+                  ( "/script?foo=1&bar=2" , "" )+              , Str "."+              ]+          , Para+              [ Str "Here\8217s"+              , Space+              , Str "an"+              , Space+              , Link+                  ( "" , [] , [] )+                  [ Str "inline"+                  , Space+                  , Str "link"+                  , Space+                  , Str "in"+                  , Space+                  , Str "pointy"+                  , Space+                  , Str "braces"+                  ]+                  ( "/script?foo=1&bar=2" , "" )+              , Str "."+              ]+          ]+      , Div+          ( "autolinks" , [ "section" ] , [] )+          [ Header 2 ( "" , [] , [] ) [ Str "Autolinks" ]+          , Para+              [ Str "With"+              , Space+              , Str "an"+              , Space+              , Str "ampersand:"+              , Space+              , Link+                  ( "" , [ "uri" ] , [] )+                  [ Str "http://example.com/?foo=1&bar=2" ]+                  ( "http://example.com/?foo=1&bar=2" , "" )+              ]+          , BulletList+              [ [ Plain+                    [ Str "In" , Space , Str "a" , Space , Str "list?" ]+                ]+              , [ Plain+                    [ Link+                        ( "" , [ "uri" ] , [] )+                        [ Str "http://example.com/" ]+                        ( "http://example.com/" , "" )+                    ]+                ]+              , [ Plain [ Str "It" , Space , Str "should." ] ]+              ]+          , Para+              [ Str "An"+              , Space+              , Str "e-mail"+              , Space+              , Str "address:"+              , Space+              , Link+                  ( "" , [ "email" ] , [] )+                  [ Str "nobody@nowhere.net" ]+                  ( "mailto:nobody@nowhere.net" , "" )+              ]+          , BlockQuote+              [ Para+                  [ Str "Blockquoted:"+                  , Space+                  , Link+                      ( "" , [ "uri" ] , [] )+                      [ Str "http://example.com/" ]+                      ( "http://example.com/" , "" )+                  ]+              ]+          , Para+              [ Str "Auto-links"+              , Space+              , Str "should"+              , Space+              , Str "not"+              , Space+              , Str "occur"+              , Space+              , Str "here:"+              , Space+              , Code ( "" , [] , [] ) "<http://example.com/>"+              ]+          , CodeBlock+              ( "" , [ "" ] , [] ) "or here: <http://example.com/>\n"+          , HorizontalRule+          ]+      ]+  , Div+      ( "images" , [ "section" ] , [] )+      [ Header 1 ( "" , [] , [] ) [ Str "Images" ]+      , Para+          [ Str "From"+          , Space+          , Quoted+              DoubleQuote+              [ Str "Voyage"+              , Space+              , Str "dans"+              , Space+              , Str "la"+              , Space+              , Str "Lune"+              ]+          , Space+          , Str "by"+          , Space+          , Str "Georges"+          , Space+          , Str "Melies"+          , Space+          , Str "(1902):"+          ]+      , Div+          ( "" , [] , [] )+          [ Para+              [ Image+                  ( "" , [] , [ ( "title" , "Voyage dans la Lune" ) ] )+                  [ Str "lalune" ]+                  ( "lalune.jpg" , "" )+              ]+          , Div ( "" , [ "caption" ] , [] ) [ Para [ Str "lalune" ] ]+          ]+      , Para+          [ Str "Here"+          , Space+          , Str "is"+          , Space+          , Str "a"+          , Space+          , Str "movie"+          , Space+          , Image+              ( "" , [] , [] ) [ Str "movie" ] ( "movie.jpg" , "" )+          , Space+          , Str "icon."+          ]+      , HorizontalRule+      ]+  , Div+      ( "footnotes" , [ "section" ] , [] )+      [ Header 1 ( "" , [] , [] ) [ Str "Footnotes" ]+      , Para+          [ Str "Here"+          , Space+          , Str "is"+          , Space+          , Str "a"+          , Space+          , Str "footnote"+          , Space+          , Str "reference,"+          , Note+              [ Para+                  [ Str "Here"+                  , Space+                  , Str "is"+                  , Space+                  , Str "the"+                  , Space+                  , Str "footnote."+                  , Space+                  , Str "It"+                  , Space+                  , Str "can"+                  , Space+                  , Str "go"+                  , Space+                  , Str "anywhere"+                  , Space+                  , Str "after"+                  , Space+                  , Str "the"+                  , Space+                  , Str "footnote"+                  , Space+                  , Str "reference."+                  , Space+                  , Str "It"+                  , SoftBreak+                  , Str "need"+                  , Space+                  , Str "not"+                  , Space+                  , Str "be"+                  , Space+                  , Str "placed"+                  , Space+                  , Str "at"+                  , Space+                  , Str "the"+                  , Space+                  , Str "end"+                  , Space+                  , Str "of"+                  , Space+                  , Str "the"+                  , Space+                  , Str "document."+                  ]+              ]+          , Space+          , Str "and"+          , Space+          , Str "another."+          , Note+              [ Para+                  [ Str "Here\8217s"+                  , Space+                  , Str "the"+                  , Space+                  , Str "long"+                  , Space+                  , Str "note."+                  , Space+                  , Str "This"+                  , Space+                  , Str "one"+                  , Space+                  , Str "contains"+                  , Space+                  , Str "multiple"+                  , Space+                  , Str "blocks."+                  ]+              , Para+                  [ Str "Subsequent"+                  , Space+                  , Str "blocks"+                  , Space+                  , Str "are"+                  , Space+                  , Str "indented"+                  , Space+                  , Str "to"+                  , Space+                  , Str "show"+                  , Space+                  , Str "that"+                  , Space+                  , Str "they"+                  , Space+                  , Str "belong"+                  , Space+                  , Str "to"+                  , Space+                  , Str "the"+                  , Space+                  , Str "footnote"+                  , Space+                  , Str "(as"+                  , SoftBreak+                  , Str "with"+                  , Space+                  , Str "list"+                  , Space+                  , Str "items)."+                  ]+              , CodeBlock ( "" , [ "" ] , [] ) "{ <code> }\n"+              , Para+                  [ Str "If"+                  , Space+                  , Str "you"+                  , Space+                  , Str "want,"+                  , Space+                  , Str "you"+                  , Space+                  , Str "can"+                  , Space+                  , Str "indent"+                  , Space+                  , Str "every"+                  , Space+                  , Str "line,"+                  , Space+                  , Str "but"+                  , Space+                  , Str "you"+                  , Space+                  , Str "can"+                  , Space+                  , Str "also"+                  , Space+                  , Str "be"+                  , Space+                  , Str "lazy"+                  , Space+                  , Str "and"+                  , Space+                  , Str "just"+                  , SoftBreak+                  , Str "indent"+                  , Space+                  , Str "the"+                  , Space+                  , Str "first"+                  , Space+                  , Str "line"+                  , Space+                  , Str "of"+                  , Space+                  , Str "each"+                  , Space+                  , Str "block."+                  ]+              ]+          , Space+          , Str "This"+          , Space+          , Str "should"+          , Space+          , Emph [ Str "not" ]+          , Space+          , Str "be"+          , Space+          , Str "a"+          , SoftBreak+          , Str "footnote"+          , Space+          , Str "reference,"+          , Space+          , Str "because"+          , Space+          , Str "it"+          , Space+          , Str "contains"+          , Space+          , Str "a"+          , Space+          , Str "space.[^my"+          , Space+          , Str "note]"+          , Space+          , Str "Here"+          , Space+          , Str "is"+          , Space+          , Str "an"+          , Space+          , Str "inline"+          , SoftBreak+          , Str "note."+          , Note+              [ Para+                  [ Str "This"+                  , Space+                  , Str "is"+                  , Space+                  , Emph [ Str "easier" ]+                  , Space+                  , Str "to"+                  , Space+                  , Str "type."+                  , Space+                  , Str "Inline"+                  , Space+                  , Str "notes"+                  , Space+                  , Str "may"+                  , Space+                  , Str "contain"+                  , SoftBreak+                  , Link+                      ( "" , [] , [] )+                      [ Str "links" ]+                      ( "http://google.com" , "" )+                  , Space+                  , Str "and"+                  , Space+                  , Code ( "" , [] , [] ) "]"+                  , Space+                  , Str "verbatim"+                  , Space+                  , Str "characters,"+                  , Space+                  , Str "as"+                  , Space+                  , Str "well"+                  , Space+                  , Str "as"+                  , SoftBreak+                  , Str "[bracketed"+                  , Space+                  , Str "text]."+                  ]+              ]+          ]+      , BlockQuote+          [ Para+              [ Str "Notes"+              , Space+              , Str "can"+              , Space+              , Str "go"+              , Space+              , Str "in"+              , Space+              , Str "quotes."+              , Note [ Para [ Str "In" , Space , Str "quote." ] ]+              ]+          ]+      , OrderedList+          ( 1 , Decimal , Period )+          [ [ Plain+                [ Str "And"+                , Space+                , Str "in"+                , Space+                , Str "list"+                , Space+                , Str "items."+                , Note [ Para [ Str "In" , Space , Str "list." ] ]+                ]+            ]+          ]+      , Para+          [ Str "This"+          , Space+          , Str "paragraph"+          , Space+          , Str "should"+          , Space+          , Str "not"+          , Space+          , Str "be"+          , Space+          , Str "part"+          , Space+          , Str "of"+          , Space+          , Str "the"+          , Space+          , Str "note,"+          , Space+          , Str "as"+          , Space+          , Str "it"+          , Space+          , Str "is"+          , Space+          , Str "not"+          , Space+          , Str "indented."           ]       ]   ]
test/docbook-reader.docbook view
@@ -27,9 +27,9 @@   This is a set of tests for pandoc. Most of them are adapted from John   Gruber’s markdown test suite. </para>-<sect1 id="headers">+<sect1 id="headers" role="sect1role">   <title>Headers</title>-  <sect2 id="level-2-with-an-embedded-link">+  <sect2 id="level-2-with-an-embedded-link" role="sect2role">     <title>Level 2 with an <ulink url="/url">embedded link</ulink></title>     <sect3 id="level-3-with-emphasis">       <title>Level 3 with <emphasis>emphasis</emphasis></title>@@ -74,6 +74,9 @@   <para>     Here’s a regular paragraph.   </para>+  <para role="pararole">+    And here’s a regular paragraph with a role.+  </para>   <para>     In Markdown 1.0.0 and earlier. Version 8. This line turns into a list     item. Because a hard-wrapped line in the middle of a paragraph looked like@@ -93,6 +96,11 @@       This is a block quote. It is pretty short.     </para>   </blockquote>+  <blockquote role="roleblockquote">+    <para>+      This is a block quote with a role.+    </para>+  </blockquote>   <blockquote>     <para>       Code in a block quote:@@ -234,6 +242,26 @@       </listitem>     </orderedlist>     <para>+      with role:+    </para>+    <orderedlist role="listrole" numeration="arabic">+      <listitem>+        <para>+          First+        </para>+      </listitem>+      <listitem>+        <para>+          Second+        </para>+      </listitem>+      <listitem>+        <para>+          Third+        </para>+      </listitem>+    </orderedlist>+    <para>       and tight:     </para>     <orderedlist spacing="compact" numeration="arabic">@@ -405,8 +433,8 @@   </sect2>   <sect2 id="fancy-list-markers">     <title>Fancy list markers</title>-    <orderedlist numeration="arabic">-      <listitem override="2">+    <orderedlist numeration="arabic" startingnumber="2">+      <listitem>         <para>           begins with 2         </para>@@ -418,8 +446,8 @@         <para>           with a continuation         </para>-        <orderedlist numeration="lowerroman">-          <listitem override="4">+        <orderedlist numeration="lowerroman" startingnumber="4">+          <listitem>             <para>               sublist with roman numerals, starting with 4             </para>@@ -457,13 +485,13 @@             <para>               Upper Roman.             </para>-            <orderedlist numeration="arabic">-              <listitem override="6">+            <orderedlist numeration="arabic" startingnumber="6">+              <listitem>                 <para>                   Decimal start with 6                 </para>-                <orderedlist numeration="loweralpha">-                  <listitem override="3">+                <orderedlist numeration="loweralpha" startingnumber="3">+                  <listitem>                     <para>                       Lower alpha with paren                     </para>@@ -703,6 +731,12 @@     So is <emphasis role="strong"><emphasis>this</emphasis></emphasis> word.   </para>   <para>+    So is <emphasis role="emphasisrole"><emphasis>this</emphasis></emphasis> word with a role.+  </para>+  <para>+    So is <phrase role="phraserole"><phrase>this</phrase></phrase> phrase with a role.+  </para>+  <para>     This is code: <literal>&gt;</literal>, <literal>$</literal>,     <literal>\</literal>, <literal>\$</literal>,     <literal>&lt;html&gt;</literal>.@@ -1406,6 +1440,75 @@     </tgroup>   </table>   <para>+    Table with attributes+  </para>+  <table xml:id="mytableid1" class="mytableclass1 mytableclass2" tabstyle="mytabstyle1" role="tablerole1">+    <title>+      Attribute table caption+    </title>+    <tgroup>+      <thead>+	<th>+	  <para>+	    header cell 1+	  </para>+	</th>+	<th>+	  <para>+	    header cell 2+	  </para>+	</th>+      </thead>+      <tbody>+	<tr>+	  <td>+	    <para>+	      body cell 1+	    </para>+	  </td>+	  <td>+	    <para>+	      body cell 2+	    </para>+	  </td>+	</tr>+      </tbody>+    </tgroup>+  </table>+  <para>+    Table with attributes, without caption+  </para>+  <informaltable xml:id="mytableid2" class="mytableclass3 mytableclass4" tabstyle="mytabstyle2" role="tablerole2">+    <tgroup>+      <thead>+	<th>+	  <para>+	    header cell 1+	  </para>+	</th>+	<th>+	  <para>+	    header cell 2+	  </para>+	</th>+      </thead>+      <tbody>+	<tr>+	  <td>+	    <para>+	      body cell 1+	    </para>+	  </td>+	  <td>+	    <para>+	      body cell 2+	    </para>+	  </td>+	</tr>+      </tbody>+    </tgroup>+  </informaltable>+  <para>     Multiline table without caption:   </para>   <informaltable>@@ -1555,6 +1658,39 @@             Here's another one. Note the blank line between rows.           </entry>         </row>+      </tbody>+    </tgroup>+  </informaltable>+  <para>+    Multiline table with cells spanning multiple columns and rows without caption.+  </para>+  <informaltable>+    <tgroup cols="3">+      <colspec align="left" colname="c1" />+      <colspec align="left" colname="c2" />+      <colspec align="left" colname="c3" />+      <colspec align="left" colname="c4" />+      <thead>+  <tr>+    <th namest="c1" nameend="c3">Columns</th>+  </tr>+  <tr>+    <th>A</th>+    <th>B</th>+    <th>C</th>+  </tr>+      </thead>+      <tbody>+	<tr>+	  <td namest="c1" nameend="c2">A1 + B1</td>+	  <td morerows="1">C1 + C2</td>+	</tr>+  <tr>+	  <td namest="c1" nameend="c2" morerows="1">A2 + B2 + A3 + B3</td>+	</tr>+  <tr>+	  <td>C3</td>+	</tr>       </tbody>     </tgroup>   </informaltable>
test/docbook-reader.native view
@@ -62,10 +62,16 @@       , Space       , Str "suite."       ]-  , Header 1 ( "headers" , [] , [] ) [ Str "Headers" ]   , Header+      1+      ( "headers" , [] , [ ( "role" , "sect1role" ) ] )+      [ Str "Headers" ]+  , Header       2-      ( "level-2-with-an-embedded-link" , [] , [] )+      ( "level-2-with-an-embedded-link"+      , []+      , [ ( "role" , "sect2role" ) ]+      )       [ Str "Level"       , Space       , Str "2"@@ -151,6 +157,29 @@       , Space       , Str "paragraph."       ]+  , Div+      ( ""+      , []+      , [ ( "wrapper" , "1" ) , ( "role" , "pararole" ) ]+      )+      [ Para+          [ Str "And"+          , Space+          , Str "here\8217s"+          , Space+          , Str "a"+          , Space+          , Str "regular"+          , Space+          , Str "paragraph"+          , Space+          , Str "with"+          , Space+          , Str "a"+          , Space+          , Str "role."+          ]+      ]   , Para       [ Str "In"       , Space@@ -251,6 +280,31 @@           , Str "short."           ]       ]+  , Div+      ( ""+      , []+      , [ ( "wrapper" , "1" ) , ( "role" , "roleblockquote" ) ]+      )+      [ BlockQuote+          [ Para+              [ Str "This"+              , Space+              , Str "is"+              , Space+              , Str "a"+              , Space+              , Str "block"+              , Space+              , Str "quote"+              , Space+              , Str "with"+              , Space+              , Str "a"+              , Space+              , Str "role."+              ]+          ]+      ]   , BlockQuote       [ Para           [ Str "Code"@@ -348,6 +402,19 @@       , [ Para [ Str "Second" ] ]       , [ Para [ Str "Third" ] ]       ]+  , Para [ Str "with" , Space , Str "role:" ]+  , Div+      ( ""+      , []+      , [ ( "wrapper" , "1" ) , ( "role" , "listrole" ) ]+      )+      [ OrderedList+          ( 1 , Decimal , DefaultDelim )+          [ [ Para [ Str "First" ] ]+          , [ Para [ Str "Second" ] ]+          , [ Para [ Str "Third" ] ]+          ]+      ]   , Para [ Str "and" , Space , Str "tight:" ]   , OrderedList       ( 1 , Decimal , DefaultDelim )@@ -932,6 +999,38 @@       , Str "word."       ]   , Para+      [ Str "So"+      , Space+      , Str "is"+      , Space+      , Emph [ Emph [ Str "this" ] ]+      , Space+      , Str "word"+      , Space+      , Str "with"+      , Space+      , Str "a"+      , Space+      , Str "role."+      ]+  , Para+      [ Str "So"+      , Space+      , Str "is"+      , Space+      , Span+          ( "" , [ "phraserole" ] , [ ( "role" , "phraserole" ) ] )+          [ Str "this" ]+      , Space+      , Str "phrase"+      , Space+      , Str "with"+      , Space+      , Str "a"+      , Space+      , Str "role."+      ]+  , Para       [ Str "This"       , Space       , Str "is"@@ -2561,6 +2660,129 @@       ]       (TableFoot ( "" , [] , [] ) [])   , Para+      [ Str "Table"+      , Space+      , Str "with"+      , Space+      , Str "attributes"+      ]+  , Table+      ( "mytableid1"+      , [ "mytableclass1" , "mytableclass2" ]+      , [ ( "role" , "tablerole1" )+        , ( "custom-style" , "mytabstyle1" )+        ]+      )+      (Caption+         Nothing+         [ Plain+             [ Str "Attribute"+             , Space+             , Str "table"+             , Space+             , Str "caption"+             ]+         ])+      [ ( AlignDefault , ColWidthDefault )+      , ( AlignDefault , ColWidthDefault )+      ]+      (TableHead ( "" , [] , [] ) [])+      [ TableBody+          ( "" , [] , [] )+          (RowHeadColumns 0)+          []+          [ Row+              ( "" , [] , [] )+              [ Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Para+                      [ Str "body"+                      , Space+                      , Str "cell"+                      , Space+                      , Str "1"+                      ]+                  ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Para+                      [ Str "body"+                      , Space+                      , Str "cell"+                      , Space+                      , Str "2"+                      ]+                  ]+              ]+          ]+      ]+      (TableFoot ( "" , [] , [] ) [])+  , Para+      [ Str "Table"+      , Space+      , Str "with"+      , Space+      , Str "attributes,"+      , Space+      , Str "without"+      , Space+      , Str "caption"+      ]+  , Table+      ( "mytableid2"+      , [ "mytableclass3" , "mytableclass4" ]+      , [ ( "role" , "tablerole2" )+        , ( "custom-style" , "mytabstyle2" )+        ]+      )+      (Caption Nothing [])+      [ ( AlignDefault , ColWidthDefault )+      , ( AlignDefault , ColWidthDefault )+      ]+      (TableHead ( "" , [] , [] ) [])+      [ TableBody+          ( "" , [] , [] )+          (RowHeadColumns 0)+          []+          [ Row+              ( "" , [] , [] )+              [ Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Para+                      [ Str "body"+                      , Space+                      , Str "cell"+                      , Space+                      , Str "1"+                      ]+                  ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Para+                      [ Str "body"+                      , Space+                      , Str "cell"+                      , Space+                      , Str "2"+                      ]+                  ]+              ]+          ]+      ]+      (TableFoot ( "" , [] , [] ) [])+  , Para       [ Str "Multiline"       , Space       , Str "table"@@ -2923,6 +3145,128 @@                       , Str "rows."                       ]                   ]+              ]+          ]+      ]+      (TableFoot ( "" , [] , [] ) [])+  , Para+      [ Str "Multiline"+      , Space+      , Str "table"+      , Space+      , Str "with"+      , Space+      , Str "cells"+      , Space+      , Str "spanning"+      , Space+      , Str "multiple"+      , Space+      , Str "columns"+      , Space+      , Str "and"+      , Space+      , Str "rows"+      , Space+      , Str "without"+      , Space+      , Str "caption."+      ]+  , Table+      ( "" , [] , [] )+      (Caption Nothing [])+      [ ( AlignLeft , ColWidthDefault )+      , ( AlignLeft , ColWidthDefault )+      , ( AlignLeft , ColWidthDefault )+      ]+      (TableHead+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 3)+                 [ Plain [ Str "Columns" ] ]+             ]+         , Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Plain [ Str "A" ] ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Plain [ Str "B" ] ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Plain [ Str "C" ] ]+             ]+         ])+      [ TableBody+          ( "" , [] , [] )+          (RowHeadColumns 0)+          []+          [ Row+              ( "" , [] , [] )+              [ Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 2)+                  [ Plain+                      [ Str "A1" , Space , Str "+" , Space , Str "B1" ]+                  ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 2)+                  (ColSpan 1)+                  [ Plain+                      [ Str "C1" , Space , Str "+" , Space , Str "C2" ]+                  ]+              ]+          , Row+              ( "" , [] , [] )+              [ Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 2)+                  (ColSpan 2)+                  [ Plain+                      [ Str "A2"+                      , Space+                      , Str "+"+                      , Space+                      , Str "B2"+                      , Space+                      , Str "+"+                      , Space+                      , Str "A3"+                      , Space+                      , Str "+"+                      , Space+                      , Str "B3"+                      ]+                  ]+              ]+          , Row+              ( "" , [] , [] )+              [ Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [ Str "C3" ] ]               ]           ]       ]
test/docbook-xref.native view
@@ -310,7 +310,7 @@           ]       ]   , Table-      ( "" , [] , [] )+      ( "table01" , [] , [] )       (Caption          Nothing          [ Plain
test/docx/0_level_headers.native view
@@ -1,52 +1,146 @@-[Table ("",[],[]) (Caption Nothing- [])- [(AlignDefault,ColWidth 1.0)]- (TableHead ("",[],[])- [])- [(TableBody ("",[],[]) (RowHeadColumns 0)-  []-  [Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    []]-  ,Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "User\8217s",Space,Str "Guide"]]]-  ,Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    []]-  ,Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    []]-  ,Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    []]-  ,Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "11",Space,Str "August",Space,Str "2017"]]]-  ,Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    []]-  ,Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    []]-  ,Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    []]-  ,Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    []]])]- (TableFoot ("",[],[])- [])-,Para [Str "CONTENTS"]-,Para [Strong [Str "Section",Space,Str "Page"]]-,Para [Str "FIGURES",Space,Link ("",[],[]) [Str "iv"] ("#figures","")]-,Para [Str "TABLES",Space,Link ("",[],[]) [Str "v"] ("#tables","")]-,Para [Str "SECTION",Space,Str "1",Space,Str "Introduction",Space,Link ("",[],[]) [Str "2"] ("#introduction","")]-,Header 1 ("figures",["Heading-0"],[]) [Str "FIGURES"]-,Para [Strong [Str "Figure",Space,Str "Page"]]-,Para [Strong [Str "No",Space,Str "table",Space,Str "of",Space,Str "figures",Space,Str "entries",Space,Str "found."]]-,Header 1 ("tables",["Heading-0"],[]) [Str "TABLES"]-,Para [Strong [Str "Table",Space,Str "Page"]]-,Para [Strong [Str "No",Space,Str "table",Space,Str "of",Space,Str "figures",Space,Str "entries",Space,Str "found."]]-,Header 1 ("introduction",[],[]) [Str "Introduction"]-,Para [Str "Nothing",Space,Str "to",Space,Str "introduce,",Space,Str "yet."]]+[ Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidth 0.8615384615384616 ) ]+    (TableHead ( "" , [] , [] ) [])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "User\8217s" , Space , Str "Guide" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain+                    [ Str "11"+                    , Space+                    , Str "August"+                    , Space+                    , Str "2017"+                    ]+                ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+, Para [ Str "CONTENTS" ]+, Para [ Strong [ Str "Section" , Space , Str "Page" ] ]+, Para+    [ Str "FIGURES"+    , Space+    , Link ( "" , [] , [] ) [ Str "iv" ] ( "#figures" , "" )+    ]+, Para+    [ Str "TABLES"+    , Space+    , Link ( "" , [] , [] ) [ Str "v" ] ( "#tables" , "" )+    ]+, Para+    [ Str "SECTION"+    , Space+    , Str "1"+    , Space+    , Str "Introduction"+    , Space+    , Link ( "" , [] , [] ) [ Str "2" ] ( "#introduction" , "" )+    ]+, Header+    1 ( "figures" , [ "Heading-0" ] , [] ) [ Str "FIGURES" ]+, Para [ Strong [ Str "Figure" , Space , Str "Page" ] ]+, Para+    [ Strong+        [ Str "No"+        , Space+        , Str "table"+        , Space+        , Str "of"+        , Space+        , Str "figures"+        , Space+        , Str "entries"+        , Space+        , Str "found."+        ]+    ]+, Header+    1 ( "tables" , [ "Heading-0" ] , [] ) [ Str "TABLES" ]+, Para [ Strong [ Str "Table" , Space , Str "Page" ] ]+, Para+    [ Strong+        [ Str "No"+        , Space+        , Str "table"+        , Space+        , Str "of"+        , Space+        , Str "figures"+        , Space+        , Str "entries"+        , Space+        , Str "found."+        ]+    ]+, Header+    1 ( "introduction" , [] , [] ) [ Str "Introduction" ]+, Para+    [ Str "Nothing"+    , Space+    , Str "to"+    , Space+    , Str "introduce,"+    , Space+    , Str "yet."+    ]+]
+ test/docx/anchor_header_after_anchor.docx view

binary file changed (absent → 27098 bytes)

+ test/docx/anchor_header_after_anchor.native view
@@ -0,0 +1,6 @@+[Para [Link ("",[],[]) [Str "A",Space,Str "link",Space,Str "to",Space,Str "the",Space,Str "bookmark"] ("#referenced-title" , "")]+,Para [Strong [Str "Accomplices:"]]+,Para [Str "There",Space,Str "are",Space,Str "bookmarks",Space,Str "around",Space,Str "here."]+,Para []+,Header 1 ("referenced-title",[],[]) [Str "Referenced" ,Space ,Str "title"]+,Para [Str "Content"]]
+ test/docx/cross_reference.docx view

binary file changed (absent → 14978 bytes)

+ test/docx/cross_reference.native view
@@ -0,0 +1,7 @@+[ Header 1 ( "title" , [] , [] ) [ Str "TITLE" ]+, Para+    [ Str "Cross-reference:"+    , Space+    , Link ( "" , [] , [] ) [ Str "TITLE" ] ( "#title" , "" )+    ]+]
test/docx/custom-style-reference.docx view

binary file changed (14846 → 14838 bytes)

test/docx/deep_normalize.native view
@@ -1,6 +1,6 @@ [OrderedList (1,Decimal,OneParen)  [[Para [Str "This",Space,Str "is",Space,Str "at",Space,Str "the",Space,Str "first",Space,Str "level"]-  ,OrderedList (1,LowerAlpha,DefaultDelim)+  ,OrderedList (1,LowerAlpha,OneParen)    [[Para [Str "This",Space,Str "is",Space,Str "at",Space,Str "the",Space,Str "second",Space,Str "level"]-    ,OrderedList (1,LowerRoman,DefaultDelim)+    ,OrderedList (1,LowerRoman,OneParen)      [[Para [Str "This",Space,Str "is",Space,Emph [Str "at",Space,Strong [Str "the",Space,Span ("",["mark"],[]) [Str "th"],Str "i",Span ("",["mark"],[]) [Str "rd"],Space,Str "level"],Str ",",Space,Str "and",Space,Str "I",Space,Str "want",Space,Str "to"],Space,Str "test",Space,Str "normalization",Space,Str "here."]]]]]]]]
test/docx/definition_list.docx view

binary file changed (8455 → 9174 bytes)

test/docx/definition_list.native view
@@ -1,7 +1,33 @@-[DefinitionList- [([Str "Term",Space,Str "1"],-   [[Para [Str "Definition",Space,Str "1"]]])- ,([Str "Term",Space,Str "2",Space,Str "with",Space,Emph [Str "inline",Space,Str "markup"]],-   [[Para [Str "Definition",Space,Str "2"]-    ,CodeBlock ("",[],[]) "{ some code, part of Definition 2 }"-    ,Para [Str "Third",Space,Str "paragraph",Space,Str "of",Space,Str "definition",Space,Str "2."]]])]]+[ DefinitionList+    [ ( [ Str "Term" , Space , Str "1" ]+      , [ [ Para [ Str "Definition" , Space , Str "1" ] ] ]+      )+    , ( [ Str "Term"+        , Space+        , Str "2"+        , Space+        , Str "with"+        , Space+        , Emph [ Str "inline" , Space , Str "markup" ]+        ]+      , [ [ Para [ Str "Definition" , Space , Str "2" ]+          , Para+              [ Code+                  ( "" , [] , [] ) "{ some code, part of Definition 2 }"+              ]+          , Para+              [ Str "Third"+              , Space+              , Str "paragraph"+              , Space+              , Str "of"+              , Space+              , Str "definition"+              , Space+              , Str "2."+              ]+          ]+        ]+      )+    ]+]
test/docx/empty_field.native view
@@ -1,5 +1,5 @@ [Para-    [Str "\24076\26395\28145\20837\20102\35299\30340\35835\32773\21487\20197\21435\30475David",Space,Str "French",Space,Str "Belding\21644Kevin",Space,Str "J.",Space,Str "Mitchell\30340"+    [Str "\24076\26395\28145\20837\20102\35299\30340\35835\32773\21487\20197\21435\30475David",Space,Str "French",Span ( "" , [ "indexref" ] , [ ( "entry" , "French" ) ] ) [],Space,Str "Belding\21644Kevin",Space,Str "J.",Space,Str "Mitchell\30340"     ,Link ("",[],[]) [Str "Foundations",Space,Str "of",Space,Str "Analysis,",Space,Str "2nd",Space,Str "Edition"] ("https://books.google.com/books?id=sp_Zcb9ot90C&lpg=PR4&hl=zh-CN&pg=PA19#v=onepage&q&f=true",""),Str ",\21487\20174\&19\39029\30475\36215\65292\25110D.C.",Space,Str "Goldrei\30340",Space     ,Link ("",[],[]) [Str "Classic",Space,Str "Set",Space,Str "Theory:",Space,Str "For",Space,Str "Guided",Space,Str "Independent",Space,Str "Study"] ("https://books.google.ae/books?id=dlc0DwAAQBAJ&lpg=PT29&hl=zh-CN&pg=PT26#v=onepage&q&f=true","")     ,Str "\65292\20174\31532\20108\31456\30475\36215\65292\38405\35835\26102\35201\27880\24847\26412\25991\19982\36825\20123\20070\25152\19981\21516\30340\26159\24182\27809\26377\25226\23454\25968\30475\20316\26159\26377\29702\25968\38598\30340\20998\21106\12290"]
+ test/docx/german-reference.docx view

binary file changed (absent → 10405 bytes)

test/docx/golden/block_quotes.docx view

binary file changed (9961 → 10692 bytes)

test/docx/golden/codeblock.docx view

binary file changed (9776 → 10510 bytes)

test/docx/golden/comments.docx view

binary file changed (10109 → 10824 bytes)

test/docx/golden/custom_style_no_reference.docx view

binary file changed (9876 → 10609 bytes)

test/docx/golden/custom_style_preserve.docx view

binary file changed (10507 → 11236 bytes)

test/docx/golden/custom_style_reference.docx view

binary file changed (12517 → 12542 bytes)

test/docx/golden/definition_list.docx view

binary file changed (9775 → 10501 bytes)

test/docx/golden/document-properties-short-desc.docx view

binary file changed (9781 → 10515 bytes)

test/docx/golden/document-properties.docx view

binary file changed (10268 → 11000 bytes)

test/docx/golden/headers.docx view

binary file changed (9915 → 10655 bytes)

test/docx/golden/image.docx view

binary file changed (26657 → 27383 bytes)

test/docx/golden/inline_code.docx view

binary file changed (9715 → 10451 bytes)

test/docx/golden/inline_formatting.docx view

binary file changed (9896 → 10627 bytes)

test/docx/golden/inline_images.docx view

binary file changed (26655 → 27383 bytes)

binary file changed (9937 → 10664 bytes)

test/docx/golden/links.docx view

binary file changed (10108 → 10842 bytes)

test/docx/golden/lists.docx view

binary file changed (10179 → 11034 bytes)

+ test/docx/golden/lists_9994.docx view

binary file changed (absent → 10788 bytes)

test/docx/golden/lists_continuing.docx view

binary file changed (9971 → 10702 bytes)

test/docx/golden/lists_div_bullets.docx view

binary file changed (9825 → 10685 bytes)

test/docx/golden/lists_multiple_initial.docx view

binary file changed (10056 → 10918 bytes)

test/docx/golden/lists_restarting.docx view

binary file changed (9969 → 10699 bytes)

test/docx/golden/nested_anchors_in_header.docx view

binary file changed (10108 → 10845 bytes)

test/docx/golden/notes.docx view

binary file changed (9884 → 10615 bytes)

test/docx/golden/raw-blocks.docx view

binary file changed (9816 → 10544 bytes)

test/docx/golden/raw-bookmarks.docx view

binary file changed (9950 → 10683 bytes)

test/docx/golden/table_one_row.docx view

binary file changed (9799 → 10496 bytes)

test/docx/golden/table_with_list_cell.docx view

binary file changed (10119 → 10946 bytes)

test/docx/golden/tables-default-widths.docx view

binary file changed (10144 → 10882 bytes)

test/docx/golden/tables.docx view

binary file changed (10158 → 10870 bytes)

test/docx/golden/tables_separated_with_rawblock.docx view

binary file changed (9797 → 10519 bytes)

+ test/docx/golden/task_list.docx view

binary file changed (absent → 10783 bytes)

test/docx/golden/track_changes_deletion.docx view

binary file changed (9759 → 10492 bytes)

test/docx/golden/track_changes_insertion.docx view

binary file changed (9742 → 10476 bytes)

test/docx/golden/track_changes_move.docx view

binary file changed (9776 → 10506 bytes)

test/docx/golden/track_changes_scrubbed_metadata.docx view

binary file changed (9885 → 10617 bytes)

test/docx/golden/unicode.docx view

binary file changed (9701 → 10468 bytes)

test/docx/golden/verbatim_subsuper.docx view

binary file changed (9748 → 10479 bytes)

+ test/docx/image_with_textbox_caption.docx view

binary file changed (absent → 19882 bytes)

+ test/docx/image_with_textbox_caption.native view
@@ -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" , "" )+        ]+    ]+]
test/docx/lists.native view
@@ -2,7 +2,7 @@ ,OrderedList (1,Decimal,Period)  [[Para [Str "one"]]  ,[Para [Str "two"]-  ,OrderedList (1,LowerAlpha,DefaultDelim)+  ,OrderedList (1,LowerAlpha,Period)    [[Para [Str "a"]]    ,[Para [Str "b"]]]]] ,BulletList
+ test/docx/lists_9994.native view
@@ -0,0 +1,8 @@+[ OrderedList+    ( 1 , Decimal , Period )+    [ [ Plain [ Str "one" ]+      , BulletList [ [ Plain [ Str "bul" ] ] ]+      ]+    , [ Plain [ Str "two" ] ]+    ]+]
test/docx/mendeley_citations_plus.native view
@@ -7,9 +7,9 @@                 [ MetaMap                     (fromList                        [ ( "DOI"-                         , MetaInlines [ Str "10.1145/1929887.1929902" ]+                         , MetaString "10.1145/1929887.1929902"                          )-                       , ( "ISSN" , MetaInlines [ Str "2153-2184" ] )+                       , ( "ISSN" , MetaString "2153-2184" )                        , ( "author"                          , MetaList                              [ MetaMap@@ -121,9 +121,9 @@                              [ Str "ACM" , Space , Str "Inroads" ]                          )                        , ( "id" , MetaString "ITEM-1" )-                       , ( "issue" , MetaString "1" )+                       , ( "issue" , MetaInlines [ Str "1" ] )                        , ( "issued" , MetaString "2011-02" )-                       , ( "page" , MetaString "32-37" )+                       , ( "page" , MetaInlines [ Str "32-37" ] )                        , ( "publisher" , MetaInlines [ Str "ACM" ] )                        , ( "publisher-place"                          , MetaInlines@@ -152,7 +152,7 @@                              ]                          )                        , ( "type" , MetaString "article-journal" )-                       , ( "volume" , MetaString "2" )+                       , ( "volume" , MetaInlines [ Str "2" ] )                        ])                 , MetaMap                     (fromList@@ -206,7 +206,7 @@                              ]                          )                        , ( "id" , MetaString "ITEM-2" )-                       , ( "issue" , MetaString "4" )+                       , ( "issue" , MetaInlines [ Str "4" ] )                        , ( "issued" , MetaString "2015" )                        , ( "title"                          , MetaInlines@@ -246,7 +246,7 @@                              ]                          )                        , ( "type" , MetaString "article-journal" )-                       , ( "volume" , MetaString "6" )+                       , ( "volume" , MetaInlines [ Str "6" ] )                        ])                 ]             )@@ -268,7 +268,7 @@               { citationId = "ITEM-1"               , citationPrefix = [ Str "prefix" ]               , citationSuffix =-                  [ Str ",", Space , Str "123" , Space , Str "suffix" ]+                  [ Str "," , Space , Str "123" , Space , Str "suffix" ]               , citationMode = NormalCitation               , citationNoteNum = 0               , citationHash = 0@@ -302,7 +302,12 @@               { citationId = "ITEM-1"               , citationPrefix = [ Str "prefix" ]               , citationSuffix =-                  [ Str ",", Space , Str "10-20" , Space , Str "suffix" ]+                  [ Str ","+                  , Space+                  , Str "10-20"+                  , Space+                  , Str "suffix"+                  ]               , citationMode = NormalCitation               , citationNoteNum = 0               , citationHash = 0
test/docx/normalize.docx view

binary file changed (14622 → 14672 bytes)

test/docx/sdt_elements.native view
@@ -1,24 +1,60 @@-[Table ("",[],[]) (Caption Nothing- [])- [(AlignDefault,ColWidth 0.22069570301081556)- ,(AlignDefault,ColWidth 0.22069570301081556)- ,(AlignDefault,ColWidth 0.5586085939783689)]- (TableHead ("",[],[])- [Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Strong [Str "col1Header"]]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Strong [Str "col2Header"]]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Strong [Str "col3Header"]]]]])- [(TableBody ("",[],[]) (RowHeadColumns 0)-  []-  [Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "col1",Space,Str "content"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "Body",Space,Str "copy"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "col3",Space,Str "content"]]]])]- (TableFoot ("",[],[])- [])]+[ Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidth 0.16167023554603854 )+    , ( AlignDefault , ColWidth 0.16167023554603854 )+    , ( AlignDefault , ColWidth 0.40920770877944324 )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignCenter+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Strong [ Str "col1Header" ] ] ]+           , Cell+               ( "" , [] , [] )+               AlignCenter+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Strong [ Str "col2Header" ] ] ]+           , Cell+               ( "" , [] , [] )+               AlignCenter+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Strong [ Str "col3Header" ] ] ]+           ]+       ])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "col1" , Space , Str "content" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Body" , Space , Str "copy" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "col3" , Space , Str "content" ] ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+]
test/docx/table_captions_no_field.docx view

binary file changed (40482 → 40487 bytes)

test/docx/table_captions_no_field.native view
@@ -1,33 +1,81 @@-[Para [Str "See",Space,Str "Table",Space,Str "5.1."]-,Table ("",[],[])- (Caption Nothing [ Para [ Str "Table" , Space , Str "5.1" ] ])- [(AlignDefault,ColWidth 0.7605739372523825)- ,(AlignDefault,ColWidth 0.11971303137380876)- ,(AlignDefault,ColWidth 0.11971303137380876)]- (TableHead ("",[],[])-[Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-  []- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-  [Plain [Str "Count"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-  [Plain [Str "%"]]]])- [(TableBody ("",[],[]) (RowHeadColumns 0)-  []-  [Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-  [Plain [Str "First",Space,Str "option"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-  [Plain [Str "242"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-  [Plain [Str "45"]]]-,Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-  [Plain [Str "Second",Space,Str "option"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-  [Plain [Str "99"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-  [Plain [Str "18"]]]])]- (TableFoot ("",[],[])- [])-,Header 2 ("section", [], []) []]+[ Para+    [ Str "See" , Space , Str "Table" , Space , Str "5.1." ]+, Table+    ( "" , [] , [] )+    (Caption+       Nothing [ Para [ Str "Table" , Space , Str "5.1" ] ])+    [ ( AlignDefault , ColWidth 0.7605739372523824 )+    , ( AlignDefault , ColWidth 0.11971303137380876 )+    , ( AlignDefault , ColWidth 0.11971303137380876 )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Count" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "%" ] ]+           ]+       ])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "First" , Space , Str "option" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "242" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "45" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Second" , Space , Str "option" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "99" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "18" ] ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+, Header 2 ( "section" , [] , [] ) []+]
test/docx/table_captions_with_field.native view
@@ -1,52 +1,145 @@-[Para [Str "See",Space,Str "Table",Space,Str "1."]-,Table ("",[],[])- (Caption Nothing [ Para [ Str "Table" , Space , Str "1" ] ])- [(AlignDefault,ColWidth 0.7605739372523825)- ,(AlignDefault,ColWidth 0.11971303137380876)- ,(AlignDefault,ColWidth 0.11971303137380876)]- (TableHead ("",[],[])-[Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-  []- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-  [Plain [Str "Count"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-  [Plain [Str "%"]]]])- [(TableBody ("",[],[]) (RowHeadColumns 0)-  []-  [Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-  [Plain [Str "First",Space,Str "option"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-  [Plain [Str "242"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-  [Plain [Str "45"]]]-,Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-  [Plain [Str "Second",Space,Str "option"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-  [Plain [Str "99"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-  [Plain [Str "18"]]]])]- (TableFoot ("",[],[])- [])-,Header 2 ("section", [], []) []-,Table ("",[],[])- (Caption Nothing [Para [Str "Table", Space, Str "2"]])- [(AlignDefault,ColWidth 0.3332963620230701)- ,(AlignDefault,ColWidth 0.3332963620230701)- ,(AlignDefault,ColWidth 0.3334072759538598)]- (TableHead ("",[],[])- [Row ("",[],[])-  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-   [Plain [Str "One"]]-  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-   [Plain [Str "Two"]]-  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-   [Plain [Str "Three"]]]])- [(TableBody ("",[],[]) (RowHeadColumns 0)-  []-  [])]- (TableFoot ("",[],[])- [])-,Para [Str "See",Space,Str "Table",Space,Str "2."]]+[ Para+    [ Str "See"+    , Space+    , Link+        ( "" , [] , [] )+        [ Str "Table" , Space , Str "1" ]+        ( "#_Ref71265628" , "" )+    , Str "."+    ]+, Table+    ( "" , [] , [] )+    (Caption+       Nothing+       [ Para+           [ Span ( "_Ref71265628" , [ "anchor" ] , [] ) []+           , Str "Table"+           , Space+           , Str "1"+           ]+       ])+    [ ( AlignDefault , ColWidth 0.7605739372523824 )+    , ( AlignDefault , ColWidth 0.11971303137380876 )+    , ( AlignDefault , ColWidth 0.11971303137380876 )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Count" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "%" ] ]+           ]+       ])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "First" , Space , Str "option" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "242" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "45" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Second" , Space , Str "option" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "99" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "18" ] ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+, Header 2 ( "section" , [] , [] ) []+, Table+    ( "" , [] , [] )+    (Caption+       Nothing+       [ Para+           [ Span ( "_Ref71265695" , [ "anchor" ] , [] ) []+           , Str "Table"+           , Space+           , Str "2"+           ]+       ])+    [ ( AlignDefault , ColWidth 0.33329636202307006 )+    , ( AlignDefault , ColWidth 0.33329636202307006 )+    , ( AlignDefault , ColWidth 0.33340727595385977 )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "One" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Two" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Three" ] ]+           ]+       ])+    [ TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [] ]+    (TableFoot ( "" , [] , [] ) [])+, Para+    [ Str "See"+    , Space+    , Link+        ( "" , [] , [] )+        [ Str "Table" , Space , Str "2" ]+        ( "#_Ref71265695" , "" )+    , Str "."+    ]+]
+ test/docx/table_gridbefore.docx view

binary file changed (absent → 13143 bytes)

+ test/docx/table_gridbefore.native view
@@ -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 ( "" , [] , [] ) [])+]
test/docx/table_header_rowspan.native view
@@ -1,189 +1,542 @@-[Table ("",[],[]) (Caption Nothing- [])- [(AlignDefault,ColWidth 0.30701754385964913)- ,(AlignDefault,ColWidth 0.1364522417153996)- ,(AlignDefault,ColWidth 0.10009746588693957)- ,(AlignDefault,ColWidth 9.707602339181287e-2)- ,(AlignDefault,ColWidth 7.719298245614035e-2)- ,(AlignDefault,ColWidth 7.085769980506823e-2)- ,(AlignDefault,ColWidth 7.09551656920078e-2)- ,(AlignDefault,ColWidth 0.14035087719298245)]- (TableHead ("",[],[])-[Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 2) (ColSpan 1)-  [Plain [Str "A"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 2) (ColSpan 1)-  [Plain [Strong [Str "B"]]]- ,Cell ("",[],[]) AlignDefault (RowSpan 2) (ColSpan 1)-  [Plain [Strong [Str "C"]]]- ,Cell ("",[],[]) AlignDefault (RowSpan 2) (ColSpan 1)-  [Plain [Strong [Str "D"]]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 3)-  [Plain [Str "E"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 2) (ColSpan 1)-  [Plain [Str "F"]]]-,Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-  [Plain [Strong [Str "G"]]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-  [Plain [Strong [Str "H"]]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-  [Plain [Strong [Str "I"]]]]])- [(TableBody ("",[],[]) (RowHeadColumns 0)-  []-  [Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "1"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "2"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "3"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "4"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "5"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "6"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "7"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "8"]]]-  ,Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "1"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "2"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "3"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "4"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "5"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "6"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "7"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "8"]]]-  ,Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "1"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "2"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "3"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "4"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "5"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "6"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "7"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "8"]]]-  ,Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "1"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "2"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "3"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "4"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "5"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "6"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "7"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "8"]]]-  ,Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "1"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "2"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "3"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "4"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "5"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "6"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "7"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "8"]]]-  ,Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "1"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "2"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "3"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "4"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "5"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "6"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "7"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "8"]]]-  ,Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "1"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "2"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "3"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "4"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "5"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "6"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "7"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "8"]]]-  ,Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "1"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "2"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "3"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "4"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "5"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "6"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "7"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "8"]]]-  ,Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "1"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "2"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "3"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "4"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "5"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "6"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "7"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "8"]]]-  ])]- (TableFoot ("",[],[])- [])]+[ Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignLeft , ColWidth 0.30701754385964913 )+    , ( AlignDefault , ColWidth 0.13645224171539963 )+    , ( AlignDefault , ColWidth 0.10009746588693959 )+    , ( AlignDefault , ColWidth 9.707602339181289e-2 )+    , ( AlignDefault , ColWidth 7.719298245614035e-2 )+    , ( AlignDefault , ColWidth 7.085769980506823e-2 )+    , ( AlignDefault , ColWidth 7.09551656920078e-2 )+    , ( AlignDefault , ColWidth 0.14035087719298248 )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 2)+               (ColSpan 1)+               [ Plain [ Str "A" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 2)+               (ColSpan 1)+               [ Plain [ Strong [ Str "B" ] ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 2)+               (ColSpan 1)+               [ Plain [ Strong [ Str "C" ] ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 2)+               (ColSpan 1)+               [ Plain [ Strong [ Str "D" ] ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 3)+               [ Plain [ Str "E" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 2)+               (ColSpan 1)+               [ Plain [ Str "F" ] ]+           ]+       , Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Strong [ Str "G" ] ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Strong [ Str "H" ] ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Strong [ Str "I" ] ] ]+           ]+       ])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignLeft+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "3" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "4" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "5" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "6" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "7" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "8" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignLeft+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "3" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "4" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "5" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "6" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "7" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "8" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignLeft+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "3" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "4" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "5" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "6" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "7" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "8" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignLeft+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "3" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "4" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "5" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "6" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "7" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "8" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignLeft+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "3" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "4" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "5" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "6" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "7" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "8" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignLeft+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "3" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "4" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "5" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "6" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "7" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "8" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignLeft+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "3" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "4" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "5" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "6" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "7" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "8" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignLeft+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "3" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "4" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "5" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "6" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "7" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "8" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignLeft+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "3" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "4" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "5" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "6" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "7" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "8" ] ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+]
test/docx/table_one_header_row.native view
@@ -1,18 +1,34 @@-[Table ("",[],[]) (Caption Nothing- [])- [(AlignDefault,ColWidth 0.33302433371958284)- ,(AlignDefault,ColWidth 0.3332560834298957)- ,(AlignDefault,ColWidth 0.33371958285052145)]- (TableHead ("",[],[])- [Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "One"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "Row"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "Table"]]]])- [(TableBody ("",[],[]) (RowHeadColumns 0)-  []-  [])]- (TableFoot ("",[],[])- [])]+[ Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidth 0.3330243337195829 )+    , ( AlignDefault , ColWidth 0.33325608342989577 )+    , ( AlignDefault , ColWidth 0.33371958285052145 )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "One" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Row" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Table" ] ]+           ]+       ])+    [ TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [] ]+    (TableFoot ( "" , [] , [] ) [])+]
test/docx/table_one_row.native view
@@ -1,18 +1,37 @@-[Table ("",[],[]) (Caption Nothing- [])- [(AlignDefault,ColWidth 0.3333333333333333)- ,(AlignDefault,ColWidth 0.3333333333333333)- ,(AlignDefault,ColWidth 0.3333333333333333)]- (TableHead ("",[],[])- [])- [(TableBody ("",[],[]) (RowHeadColumns 0)-  []-  [Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "One"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "Row"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "Table"]]]])]- (TableFoot ("",[],[])- [])]+[ Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidth 0.33333333333333337 )+    , ( AlignDefault , ColWidth 0.33333333333333337 )+    , ( AlignDefault , ColWidth 0.33333333333333337 )+    ]+    (TableHead ( "" , [] , [] ) [])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "One" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Row" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Table" ] ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+]
test/docx/table_variable_width.native view
@@ -1,40 +1,78 @@-[Table ("",[],[]) (Caption Nothing- [])- [(AlignDefault,ColWidth 2.0096205237840725e-2)- ,(AlignDefault,ColWidth 1.9882415820416888e-2)- ,(AlignDefault,ColWidth 0.22202030999465527)- ,(AlignDefault,ColWidth 0.4761090326028862)- ,(AlignDefault,ColWidth 1.0689470871191876e-4)- ,(AlignDefault,ColWidth 0.26178514163548905)]- (TableHead ("",[],[])- [Row ("",[],[])-  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-   []-  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-   []-  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-   [Plain [Str "h3"]]-  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 2)-   [Plain [Str "h4"]]-  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-   [Plain [Str "h5"]]]])- [(TableBody ("",[],[]) (RowHeadColumns 0)-  []-  [Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 3)-    [Plain [Str "c11"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    []-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 2)-    []]-  ,Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    []-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 2)-    [Plain [Str "c22"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "c23"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 2)-    []]])]- (TableFoot ("",[],[])- [])]+[ Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidth 1.9673503557974047e-2 )+    , ( AlignDefault , ColWidth 1.946421096693177e-2 )+    , ( AlignDefault , ColWidth 0.21735035579740478 )+    , ( AlignDefault , ColWidth 0.4660946002511511 )+    , ( AlignDefault , ColWidth 1.0464629552113855e-4 )+    , ( AlignDefault , ColWidth 0.25627877773126834 )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+           , Cell+               ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "h3" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 2)+               [ Plain [ Str "h4" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "h5" ] ]+           ]+       ])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 3)+                [ Plain [ Str "c11" ] ]+            , Cell+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+            , Cell+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 2) []+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 2)+                [ Plain [ Str "c22" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "c23" ] ]+            , Cell+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 2) []+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+]
test/docx/table_with_list_cell.native view
@@ -1,25 +1,72 @@-[Table ("",[],[]) (Caption Nothing- [])- [(AlignDefault,ColWidth 0.5)- ,(AlignDefault,ColWidth 0.5)]- (TableHead ("",[],[])- [Row ("",[],[])-  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-   [Plain [Str "Cell",Space,Str "with",Space,Str "text"]]-  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-   [Plain [Str "Cell",Space,Str "with",Space,Str "text"]]]])- [(TableBody ("",[],[]) (RowHeadColumns 0)-  []-  [Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [BulletList-     [[Para [Str "Cell",Space,Str "with"]]-     ,[Para [Str "A"]]-     ,[Para [Str "Bullet",Space,Str "list"]]]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [OrderedList (1,Decimal,Period)-     [[Para [Str "Cell",Space,Str "with"]]-     ,[Para [Str "A"]]-     ,[Para [Str "Numbered",Space,Str "list."]]]]]])]- (TableFoot ("",[],[])- [])]+[ Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidth 0.5 )+    , ( AlignDefault , ColWidth 0.5 )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain+                   [ Str "Cell"+                   , Space+                   , Str "with"+                   , Space+                   , Str "text"+                   ]+               ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain+                   [ Str "Cell"+                   , Space+                   , Str "with"+                   , Space+                   , Str "text"+                   ]+               ]+           ]+       ])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ BulletList+                    [ [ Para [ Str "Cell" , Space , Str "with" ] ]+                    , [ Para [ Str "A" ] ]+                    , [ Para [ Str "Bullet" , Space , Str "list" ] ]+                    ]+                ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ OrderedList+                    ( 1 , Decimal , Period )+                    [ [ Para [ Str "Cell" , Space , Str "with" ] ]+                    , [ Para [ Str "A" ] ]+                    , [ Para [ Str "Numbered" , Space , Str "list." ] ]+                    ]+                ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+]
test/docx/tables.native view
@@ -1,92 +1,238 @@-[Header 2 ("a-table-with-and-without-a-header-row",[],[]) [Str "A",Space,Str "table,",Space,Str "with",Space,Str "and",Space,Str "without",Space,Str "a",Space,Str "header",Space,Str "row"]-,Table ("",[],[]) (Caption Nothing- [])- [(AlignDefault,ColWidth 0.25)- ,(AlignDefault,ColWidth 0.25)- ,(AlignDefault,ColWidth 0.25)- ,(AlignDefault,ColWidth 0.25)]- (TableHead ("",[],[])- [Row ("",[],[])-  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-   [Plain [Str "Name"]]-  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-   [Plain [Str "Game"]]-  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-   [Plain [Str "Fame"]]-  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-   [Plain [Str "Blame"]]]])- [(TableBody ("",[],[]) (RowHeadColumns 0)-  []-  [Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "Lebron",Space,Str "James"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "Basketball"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "Very",Space,Str "High"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "Leaving",Space,Str "Cleveland"]]]-  ,Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "Ryan",Space,Str "Braun"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "Baseball"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "Moderate"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "Steroids"]]]-  ,Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "Russell",Space,Str "Wilson"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "Football"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "High"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "Tacky",Space,Str "uniform"]]]])]- (TableFoot ("",[],[])- [])-,Table ("",[],[]) (Caption Nothing- [])- [(AlignDefault,ColWidth 0.5)- ,(AlignDefault,ColWidth 0.5)]- (TableHead ("",[],[])- [])- [(TableBody ("",[],[]) (RowHeadColumns 0)-  []-  [Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "Sinple"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "Table"]]]-  ,Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "Without"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "Header"]]]])]- (TableFoot ("",[],[])- [])-,Table ("",[],[]) (Caption Nothing- [])- [(AlignDefault,ColWidth 0.5)- ,(AlignDefault,ColWidth 0.5)]- (TableHead ("",[],[])- [])- [(TableBody ("",[],[]) (RowHeadColumns 0)-  []-  [Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Para [Str "Simple"]-    ,Para [Str "Multiparagraph"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Para [Str "Table"]-    ,Para [Str "Full"]]]-  ,Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Para [Str "Of"]-    ,Para [Str "Paragraphs"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Para [Str "In",Space,Str "each"]-    ,Para [Str "Cell."]]]])]- (TableFoot ("",[],[])- [])]+[ Header+    2+    ( "a-table-with-and-without-a-header-row" , [] , [] )+    [ Str "A"+    , Space+    , Str "table,"+    , Space+    , Str "with"+    , Space+    , Str "and"+    , Space+    , Str "without"+    , Space+    , Str "a"+    , Space+    , Str "header"+    , Space+    , Str "row"+    ]+, Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidth 0.25 )+    , ( AlignDefault , ColWidth 0.25 )+    , ( AlignDefault , ColWidth 0.25 )+    , ( AlignDefault , ColWidth 0.25 )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Name" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Game" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Fame" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Blame" ] ]+           ]+       ])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Lebron" , Space , Str "James" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Basketball" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Very" , Space , Str "High" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Leaving" , Space , Str "Cleveland" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Ryan" , Space , Str "Braun" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Baseball" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Moderate" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Steroids" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Russell" , Space , Str "Wilson" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Football" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "High" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Tacky" , Space , Str "uniform" ] ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+, Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidth 0.5 )+    , ( AlignDefault , ColWidth 0.5 )+    ]+    (TableHead ( "" , [] , [] ) [])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Sinple" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Table" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Without" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Header" ] ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+, Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidth 0.5 )+    , ( AlignDefault , ColWidth 0.5 )+    ]+    (TableHead ( "" , [] , [] ) [])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Para [ Str "Simple" ]+                , Para [ Str "Multiparagraph" ]+                ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Para [ Str "Table" ] , Para [ Str "Full" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Para [ Str "Of" ] , Para [ Str "Paragraphs" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Para [ Str "In" , Space , Str "each" ]+                , Para [ Str "Cell." ]+                ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+]
+ test/docx/task_list.docx view

binary file changed (absent → 10749 bytes)

+ test/docx/task_list.native view
@@ -0,0 +1,40 @@+[ BulletList+    [ [ Para [ Str "\9744" , Space , Str "Unchecked" ] ]+    , [ Para [ Str "\9746" , Space , Str "Checked" ]+      , Para+          [ Str "with"+          , Space+          , Str "continuation"+          , Space+          , Str "paragraph"+          ]+      ]+    , [ Para [ Str "\9744" , Space , Str "Unchecked" ]+      , BulletList+          [ [ Plain+                [ Str "\9746"+                , Space+                , Str "Checked"+                , Space+                , Str "sublist"+                ]+            , BulletList+                [ [ Plain+                      [ Str "\9744"+                      , Space+                      , Str "Unchecked"+                      , Space+                      , Str "subsublist"+                      ]+                  , OrderedList+                      ( 1 , Decimal , Period )+                      [ [ Plain [ Str "Numbered" , Space , Str "child" ]+                        ]+                      ]+                  ]+                ]+            ]+          ]+      ]+    ]+]
+ test/docx/textbox_image.docx view

binary file changed (absent → 40379 bytes)

+ test/docx/textbox_image.native view
@@ -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."+    ]+]
+ test/docx/textbox_image_duplicate_encoding.docx view

binary file changed (absent → 36750 bytes)

+ test/docx/textbox_image_duplicate_encoding.native view
@@ -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."+    ]+]
test/docx/zotero_citations_plus.native view
@@ -6,9 +6,7 @@             , MetaList                 [ MetaMap                     (fromList-                       [ ( "DOI"-                         , MetaInlines [ Str "10.1002/2016GL069961" ]-                         )+                       [ ( "DOI" , MetaString "10.1002/2016GL069961" )                        , ( "author"                          , MetaList                              [ MetaMap@@ -54,10 +52,12 @@                              ]                          )                        , ( "id" , MetaString "10" )-                       , ( "issue" , MetaString "18" )+                       , ( "issue" , MetaInlines [ Str "18" ] )                        , ( "issued" , MetaString "2016" )                        , ( "language" , MetaInlines [ Str "en" ] )-                       , ( "page" , MetaString "9852\8211\&9859" )+                       , ( "page"+                         , MetaInlines [ Str "9852\8211\&9859" ]+                         )                        , ( "title"                          , MetaInlines                              [ Str "New"@@ -90,21 +90,14 @@                              ]                          )                        , ( "type" , MetaString "article-journal" )-                       , ( "volume" , MetaString "43" )+                       , ( "volume" , MetaInlines [ Str "43" ] )                        ])                 , MetaMap                     (fromList                        [ ( "DOI"-                         , MetaInlines-                             [ Str "10.1007/s00382-013-1683-2" ]-                         )-                       , ( "ISSN"-                         , MetaInlines-                             [ Str "0930-7575,"-                             , Space-                             , Str "1432-0894"-                             ]+                         , MetaString "10.1007/s00382-013-1683-2"                          )+                       , ( "ISSN" , MetaString "0930-7575, 1432-0894" )                        , ( "author"                          , MetaList                              [ MetaMap@@ -131,10 +124,12 @@                              [ Str "Climate" , Space , Str "Dynamics" ]                          )                        , ( "id" , MetaString "109" )-                       , ( "issue" , MetaString "11-12" )+                       , ( "issue" , MetaInlines [ Str "11-12" ] )                        , ( "issued" , MetaString "2013-12" )                        , ( "language" , MetaInlines [ Str "en" ] )-                       , ( "page" , MetaString "3325\8211\&3338" )+                       , ( "page"+                         , MetaInlines [ Str "3325\8211\&3338" ]+                         )                        , ( "title"                          , MetaInlines                              [ Str "A"@@ -165,12 +160,12 @@                              ]                          )                        , ( "type" , MetaString "article-journal" )-                       , ( "volume" , MetaString "41" )+                       , ( "volume" , MetaInlines [ Str "41" ] )                        ])                 , MetaMap                     (fromList                        [ ( "DOI"-                         , MetaInlines [ Str "10.5194/gmd-9-3751-2016" ]+                         , MetaString "10.5194/gmd-9-3751-2016"                          )                        , ( "author"                          , MetaList@@ -280,7 +275,9 @@                        , ( "id" , MetaString "6" )                        , ( "issued" , MetaString "2016" )                        , ( "language" , MetaInlines [ Str "en" ] )-                       , ( "page" , MetaString "3751\8211\&3777" )+                       , ( "page"+                         , MetaInlines [ Str "3751\8211\&3777" ]+                         )                        , ( "title"                          , MetaInlines                              [ Str "The"@@ -297,7 +294,7 @@                              ]                          )                        , ( "type" , MetaString "article-journal" )-                       , ( "volume" , MetaString "9" )+                       , ( "volume" , MetaInlines [ Str "9" ] )                        ])                 ]             )@@ -412,7 +409,7 @@               { citationId = "10"               , citationPrefix = [ Str "prefix" ]               , citationSuffix =-                  [ Str ",", Space , Str "2" , Space , Str "suffix" ]+                  [ Str "," , Space , Str "2" , Space , Str "suffix" ]               , citationMode = NormalCitation               , citationNoteNum = 0               , citationHash = 0
test/jats-reader.native view
@@ -536,7 +536,7 @@       , Space       , Str "the"       , Space-      , Str "pragraph,"+      , Str "paragraph,"       , Space       , Str "but"       , Space@@ -568,7 +568,12 @@       ]   , Para       [ Strong-          [ Str "Outside" , Space , Str "a" , Space , Str "pararaph" ]+          [ Str "Outside"+          , Space+          , Str "a"+          , Space+          , Str "paragraph"+          ]       , Str ","       , Space       , Str "should"@@ -613,7 +618,7 @@       ]   , Para       [ Strong-          [ Str "Inside" , Space , Str "a" , Space , Str "pragraph" ]+          [ Str "Inside" , Space , Str "a" , Space , Str "paragraph" ]       , Str ","       , Space       , Str "should"
test/jats-reader.xml view
@@ -84,7 +84,7 @@ <sec id="statements">   <title> Statements </title>   <statement>-    <label> A label for a statment</label>+    <label> A label for a statement</label>     <title> CAP TITLE </title>     <p> Some text to make this regular </p>   </statement>@@ -163,12 +163,12 @@   </sec>   <sec id="disp-formulae">     <title>Block formulae with <italic>disp-formula</italic></title>-    <p><bold>Inside a paragraph</bold>, should be natively coded inside the pragraph, but show as block:</p>+    <p><bold>Inside a paragraph</bold>, should be natively coded inside the paragraph, but show as block:</p>     <p>Einstein showed that <disp-formula><alternatives>       <tex-math><![CDATA[e=mc^2]]></tex-math>       <mml:math display="block" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mi>e</mml:mi><mml:mo>=</mml:mo><mml:mi>m</mml:mi><mml:msup><mml:mi>c</mml:mi><mml:mn>2</mml:mn></mml:msup></mml:mrow></mml:math></alternatives></disp-formula>.       This formula is important because…</p>-    <p><bold>Outside a pararaph</bold>, should show as block:</p>+    <p><bold>Outside a paragraph</bold>, should show as block:</p>     <p>Einstein showed that </p>     <disp-formula><alternatives>       <tex-math><![CDATA[e=mc^2]]></tex-math>@@ -177,7 +177,7 @@   </sec>   <sec id="no-formula-wrapper">     <title>Without a formula wrapper</title>-    <p><bold>Inside a pragraph</bold>, should show inline:</p>+    <p><bold>Inside a paragraph</bold>, should show inline:</p>     <p>Einstein showed that <alternatives>       <tex-math><![CDATA[e=mc^2]]></tex-math>       <mml:math display="inline" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mi>e</mml:mi><mml:mo>=</mml:mo><mml:mi>m</mml:mi><mml:msup><mml:mi>c</mml:mi><mml:mn>2</mml:mn></mml:msup></mml:mrow></mml:math></alternatives>.
test/man-reader.man view
@@ -1,4 +1,4 @@-.TH "Pandoc Man tests" "" "Oct 17, 2018" "" ""+.TH "PANDOC-MAN-TESTS" "1" "Oct 17, 2018" "v1.0.1" "Pandoc Tests" .PP This is a set of tests for pandoc. .PP
test/man-reader.native view
@@ -6,16 +6,12 @@             , MetaInlines                 [ Str "Oct" , Space , Str "17," , Space , Str "2018" ]             )-          , ( "section" , MetaInlines [] )-          , ( "title"-            , MetaInlines-                [ Str "Pandoc"-                , Space-                , Str "Man"-                , Space-                , Str "tests"-                ]+          , ( "footer" , MetaInlines [ Str "v1.0.1" ] )+          , ( "header"+            , MetaInlines [ Str "Pandoc" , Space , Str "Tests" ]             )+          , ( "section" , MetaInlines [ Str "1" ] )+          , ( "title" , MetaInlines [ Str "PANDOC-MAN-TESTS" ] )           ]     }   [ Para@@ -46,11 +42,11 @@       , Space       , Str "*"       ]-  , Header 1 ( "" , [] , [] ) [ Str "Headers" ]+  , Header 1 ( "headers" , [] , [] ) [ Str "Headers" ]   , Header-      1 ( "" , [] , [] ) [ Str "Level" , Space , Str "1" ]+      1 ( "level-1" , [] , [] ) [ Str "Level" , Space , Str "1" ]   , Header-      2 ( "" , [] , [] ) [ Str "Level" , Space , Str "2" ]+      2 ( "level-2" , [] , [] ) [ Str "Level" , Space , Str "2" ]   , Para       [ Str "*"       , Space@@ -62,7 +58,7 @@       , Space       , Str "*"       ]-  , Header 1 ( "" , [] , [] ) [ Str "Paragraphs" ]+  , Header 1 ( "paragraphs" , [] , [] ) [ Str "Paragraphs" ]   , Para       [ Str "Here's"       , Space@@ -163,7 +159,9 @@       , Str "*"       ]   , Header-      1 ( "" , [] , [] ) [ Str "Block" , Space , Str "Quotes" ]+      1+      ( "block-quotes" , [] , [] )+      [ Str "Block" , Space , Str "Quotes" ]   , Para       [ Str "Code"       , Space@@ -186,7 +184,9 @@       , [ Para [ Str "item" , Space , Str "two" ] ]       ]   , Header-      1 ( "" , [] , [] ) [ Str "Code" , Space , Str "Blocks" ]+      1+      ( "code-blocks" , [] , [] )+      [ Str "Code" , Space , Str "Blocks" ]   , Para [ Str "Code:" ]   , CodeBlock       ( "" , [] , [] )@@ -205,22 +205,22 @@       , Space       , Str "*"       ]-  , Header 1 ( "" , [] , [] ) [ Str "Lists" ]-  , Header 2 ( "" , [] , [] ) [ Str "Unordered" ]+  , Header 1 ( "lists" , [] , [] ) [ Str "Lists" ]+  , Header 2 ( "unordered" , [] , [] ) [ Str "Unordered" ]   , Para [ Str "Asterisks:" ]   , BulletList       [ [ Para [ Str "asterisk" , Space , Str "1" ] ]       , [ Para [ Str "asterisk" , Space , Str "2" ] ]       , [ Para [ Str "asterisk" , Space , Str "3" ] ]       ]-  , Header 2 ( "" , [] , [] ) [ Str "Ordered" ]+  , Header 2 ( "ordered" , [] , [] ) [ Str "Ordered" ]   , OrderedList       ( 1 , Decimal , Period )       [ [ Para [ Str "First" ] ]       , [ Para [ Str "Second" ] ]       , [ Para [ Str "Third" ] ]       ]-  , Header 2 ( "" , [] , [] ) [ Str "Nested" ]+  , Header 2 ( "nested" , [] , [] ) [ Str "Nested" ]   , BulletList       [ [ Para [ Str "Tab" ]         , BulletList@@ -258,7 +258,7 @@       ]   , Header       2-      ( "" , [] , [] )+      ( "different-styles" , [] , [] )       [ Str "different" , Space , Str "styles:" ]   , OrderedList       ( 1 , UpperAlpha , Period )@@ -296,7 +296,7 @@             ]         ]       ]-  , Header 2 ( "" , [] , [] ) [ Str "Ordered" ]+  , Header 2 ( "ordered-1" , [] , [] ) [ Str "Ordered" ]   , Para [ Str "Definition" , Space , Str "lists" ]   , DefinitionList       [ ( [ Strong [ Str "term1" ] ]@@ -327,7 +327,7 @@       ]   , Header       1-      ( "" , [] , [] )+      ( "special-characters" , [] , [] )       [ Str "Special" , Space , Str "Characters" ]   , Para       [ Str "AT&T"@@ -368,7 +368,7 @@   , Para [ Str "Bang:" , Space , Str "!" ]   , Para [ Str "Plus:" , Space , Str "+" ]   , Para [ Str "Minus:" , Space , Str "-" ]-  , Header 1 ( "" , [] , [] ) [ Str "Links" ]+  , Header 1 ( "links" , [] , [] ) [ Str "Links" ]   , Para       [ Link           ( "" , [] , [] )@@ -383,7 +383,7 @@           ( "mailto:me@example.com" , "" )       , Str "."       ]-  , Header 1 ( "" , [] , [] ) [ Str "Macros" ]+  , Header 1 ( "macros" , [] , [] ) [ Str "Macros" ]   , Para       [ Strong [ Str "Me" , Space , Str "Myself" ]       , Space@@ -410,7 +410,7 @@       , Strong [ Str "Author" ]       , Str "."       ]-  , Header 1 ( "" , [] , [] ) [ Str "Tables" ]+  , Header 1 ( "tables" , [] , [] ) [ Str "Tables" ]   , Table       ( "" , [] , [] )       (Caption Nothing [])
test/markdown-reader-more.native view
@@ -200,12 +200,8 @@       , Str "item"       ]   , BulletList-      [ [ Plain-            [ Str "one"-            , SoftBreak-            , RawInline (Format "html") "<!--\n- two\n-->"-            ]-        ]+      [ [ Plain [ Str "one" , SoftBreak , Str "<!\8211" ] ]+      , [ Plain [ Str "two" , SoftBreak , Str "\8211>" ] ]       , [ Plain [ Str "three" ] ]       ]   , Header@@ -316,8 +312,8 @@       2       ( "curly-smart-quotes" , [] , [] )       [ Str "Curly" , Space , Str "smart" , Space , Str "quotes" ]-  , Para [ Quoted DoubleQuote [ Str "Hi" ] ]-  , Para [ Quoted SingleQuote [ Str "Hi" ] ]+  , Para [ Str "\8220Hi\8221" ]+  , Para [ Str "\8216Hi\8217" ]   , Header       2       ( "consecutive-lists" , [] , [] )
test/mediawiki-reader.native view
@@ -254,40 +254,46 @@       [ Str "internal" , Space , Str "links" ]   , Para       [ Link-          ( "" , [] , [] ) [ Str "Help" ] ( "Help" , "wikilink" )+          ( "" , [ "wikilink" ] , [] )+          [ Str "Help" ]+          ( "Help" , "Help" )       ]   , Para       [ Link-          ( "" , [] , [] )+          ( "" , [ "wikilink" ] , [] )           [ Str "the" , Space , Str "help" , Space , Str "page" ]-          ( "Help" , "wikilink" )+          ( "Help" , "the help page" )       ]   , Para       [ Link-          ( "" , [] , [] ) [ Str "Helpers" ] ( "Help" , "wikilink" )+          ( "" , [ "wikilink" ] , [] )+          [ Str "Helpers" ]+          ( "Help" , "Help" )       ]   , Para       [ Link-          ( "" , [] , [] ) [ Str "Help" ] ( "Help" , "wikilink" )+          ( "" , [ "wikilink" ] , [] )+          [ Str "Help" ]+          ( "Help" , "Help" )       , Str "ers"       ]   , Para       [ Link-          ( "" , [] , [] )+          ( "" , [ "wikilink" ] , [] )           [ Str "Contents" ]-          ( "Help:Contents" , "wikilink" )+          ( "Help:Contents" , "Contents" )       ]   , Para       [ Link-          ( "" , [] , [] )+          ( "" , [ "wikilink" ] , [] )           [ Str "#My" , Space , Str "anchor" ]-          ( "#My_anchor" , "wikilink" )+          ( "#My_anchor" , "#My anchor" )       ]   , Para       [ Link-          ( "" , [] , [] )+          ( "" , [ "wikilink" ] , [] )           [ Str "and" , Space , Str "text" ]-          ( "Page#with_anchor" , "wikilink" )+          ( "Page#with_anchor" , "and text" )       ]   , Header 2 ( "images" , [] , [] ) [ Str "images" ]   , Figure
test/odt/native/imageIndex.native view
@@ -1,1 +1,28 @@-[Para [Image ("",[],[("width","5.292cm"),("height","5.292cm")]) [Str "Abbildung",Space,Str "1:",Space,Str "Image",Space,Str "caption"] ("Pictures/10000000000000FA000000FAD6A15225.jpg","fig:")]]+[ Figure+  ( "" , [] , [] )+  (Caption+     Nothing+     [ Plain+         [ Str "Image"+         , Space+         , Str "caption"+         ]+     ])+  [ Plain+      [ Image+          ( ""+          , []+          , [ ( "width" , "5.292cm" ) , ( "height" , "5.292cm" ) ]+          )+          [ Str "Abbildung"+          , Space+          , Str "1:"+          , Space+          , Str "Image"+          , Space+          , Str "caption"+          ]+          ( "Pictures/10000000000000FA000000FAD6A15225.jpg" , "" )+      ]+  ]+]
+ test/odt/native/imageRelative.native view
@@ -0,0 +1,10 @@+[ Para+    [ Image+        ( ""+        , []+        , [ ( "width" , "5.292cm" ) , ( "height" , "5.292cm" ) ]+        )+        []+        ( "../../lalune.jpg" , "" )+    ]+]
test/odt/native/imageWithCaption.native view
@@ -1,1 +1,28 @@-[Para [Image ("",[],[("width","5.292cm"),("height","5.292cm")]) [Str "Abbildung",Space,Str "1:",Space,Str "Image",Space,Str "caption"] ("Pictures/10000000000000FA000000FAD6A15225.jpg","fig:")]]+[ Figure+  ( "" , [] , [] )+  (Caption+     Nothing+     [ Plain+         [ Str "Image"+         , Space+         , Str "caption"+         ]+     ])+  [ Plain+      [ Image+          ( ""+          , []+          , [ ( "width" , "5.292cm" ) , ( "height" , "5.292cm" ) ]+          )+          [ Str "Abbildung"+          , Space+          , Str "1:"+          , Space+          , Str "Image"+          , Space+          , Str "caption"+          ]+          ( "Pictures/10000000000000FA000000FAD6A15225.jpg" , "" )+      ]+  ]+]
test/odt/native/listContinueNumbering2.native view
@@ -1,27 +1,23 @@ [ OrderedList     ( 1 , Decimal , Period )-    [ [ BlockQuote [ Para [ Str "Top" , Space , Str "one" ] ]+    [ [ Para [ Str "Top" , Space , Str "one" ]       , OrderedList           ( 1 , LowerAlpha , Period )-          [ [ BlockQuote-                [ Para-                    [ Str "Sub"-                    , Space-                    , Str "item"-                    , Space-                    , Str "1.a"-                    ]-                ]+          [[ Plain+             [ Str "Sub"+             , Space+             , Str "item"+             , Space+             , Str "1.a"+             ]             ]-          , [ BlockQuote-                [ Para-                    [ Str "Sub"-                    , Space-                    , Str "item"-                    , Space-                    , Str "1.b"-                    ]-                ]+          , [ Plain+              [ Str "Sub"+              , Space+              , Str "item"+              , Space+              , Str "1.b"+              ]             ]           ]       ]@@ -39,28 +35,24 @@ , Para [] , OrderedList     ( 2 , Decimal , Period )-    [ [ BlockQuote [ Para [ Str "Top" , Space , Str "two" ] ]+    [ [ Para [ Str "Top" , Space , Str "two" ]       , OrderedList           ( 1 , LowerAlpha , Period )-          [ [ BlockQuote-                [ Para-                    [ Str "Sub"-                    , Space-                    , Str "item"-                    , Space-                    , Str "2.a"-                    ]-                ]+          [ [ Plain+              [ Str "Sub"+              , Space+              , Str "item"+              , Space+              , Str "2.a"+              ]             ]-          , [ BlockQuote-                [ Para-                    [ Str "Sub"-                    , Space-                    , Str "item"-                    , Space-                    , Str "2.b"-                    ]-                ]+          , [ Plain+              [ Str "Sub"+              , Space+              , Str "item"+              , Space+              , Str "2.b"+              ]             ]           ]       ]@@ -78,28 +70,24 @@ , Para [] , OrderedList     ( 3 , Decimal , Period )-    [ [ BlockQuote [ Para [ Str "Top" , Space , Str "three" ] ]+    [ [ Para [ Str "Top" , Space , Str "three" ]       , OrderedList           ( 1 , LowerAlpha , Period )-          [ [ BlockQuote-                [ Para-                    [ Str "Sub"-                    , Space-                    , Str "item"-                    , Space-                    , Str "3.a"-                    ]-                ]+          [ [ Plain+              [ Str "Sub"+              , Space+              , Str "item"+              , Space+              , Str "3.a"+              ]             ]-          , [ BlockQuote-                [ Para-                    [ Str "Sub"-                    , Space-                    , Str "item"-                    , Space-                    , Str "3.b"-                    ]-                ]+          , [ Plain+              [ Str "Sub"+              , Space+              , Str "item"+              , Space+              , Str "3.b"+              ]             ]           ]       ]
+ test/odt/native/preformattedText.native view
@@ -0,0 +1,4 @@+[ CodeBlock+    ( "" , [] , [] )+    "void main() {\n    printf(\"Hello world\");\n}"+]
+ test/odt/native/preformattedTextParentStyle.native view
@@ -0,0 +1,4 @@+[ CodeBlock+    ( "" , [] , [] )+    "void main() {\n    printf(\"Hello world\");\n}"+]
test/odt/native/simpleTable.native view
@@ -1,1 +1,1 @@-[Table ("",[],[]) (Caption Nothing []) [(AlignDefault,ColWidthDefault),(AlignDefault,ColWidthDefault)] (TableHead ("",[],[]) [Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [],Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) []]]) [TableBody ("",[],[]) (RowHeadColumns 0) [] [Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Content"]],Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "More",Space,Str "content"]]]]] (TableFoot ("",[],[]) []),Para []]+[Table ("",[],[]) (Caption Nothing []) [(AlignDefault,ColWidthDefault),(AlignDefault,ColWidthDefault)] (TableHead ("",[],[]) []) [TableBody ("",[],[]) (RowHeadColumns 0) [] [Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Content"]],Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "More",Space,Str "content"]]]]] (TableFoot ("",[],[]) []),Para []]
test/odt/native/simpleTableWithCaption.native view
@@ -1,1 +1,1 @@-[Table ("",[],[]) (Caption Nothing [Para [Str "Table",Space,Str "1:",Space,Str "Some",Space,Str "caption",Space,Str "for",Space,Str "a",Space,Str "table"]]) [(AlignDefault,ColWidthDefault),(AlignDefault,ColWidthDefault)] (TableHead ("",[],[]) [Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [],Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) []]]) [TableBody ("",[],[]) (RowHeadColumns 0) [] [Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Content"]],Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "More",Space,Str "content"]]]]] (TableFoot ("",[],[]) []),Para []]+[Table ("",[],[]) (Caption Nothing [Para [Str "Table",Space,Str "1:",Space,Str "Some",Space,Str "caption",Space,Str "for",Space,Str "a",Space,Str "table"]]) [(AlignDefault,ColWidthDefault),(AlignDefault,ColWidthDefault)] (TableHead ("",[],[]) []) [TableBody ("",[],[]) (RowHeadColumns 0) [] [Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Content"]],Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "More",Space,Str "content"]]]]] (TableFoot ("",[],[]) []),Para []]
+ test/odt/native/simpleTableWithHeader.native view
@@ -0,0 +1,79 @@+[ Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "A" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "B" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "C" ] ]+           ]+       ])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [ Plain [] ]+            , Cell+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [ Plain [] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "2" ] ]+            , Cell+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [ Plain [] ]+            , Cell+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [ Plain [] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "3" ] ]+            , Cell+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [ Plain [] ]+            , Cell+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [ Plain [] ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+, Para []+]
+ test/odt/native/simpleTableWithMultipleHeaderRows.native view
@@ -0,0 +1,125 @@+[ Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "A" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "B" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "C" ] ]+           ]+       , Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "I" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "II" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "II" ] ]+           ]+       ])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "3" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [] ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+, Para []+]+
+ test/odt/native/sourceText.native view
@@ -0,0 +1,11 @@+[ Header+    1+    ( "test-foo" , [] , [] )+    [ Span ( "anchor" , [] , [] ) []+    , Str "Test"+    , Space+    , Code ( "" , [] , [] ) "foo"+    ]+, Para+    [ Str "Hello" , Space , Code ( "" , [] , [] ) "world" ]+]
test/odt/native/tableWithContents.native view
@@ -1,1 +1,1 @@-[Table ("",[],[]) (Caption Nothing []) [(AlignDefault,ColWidthDefault),(AlignDefault,ColWidthDefault)] (TableHead ("",[],[]) [Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [],Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) []]]) [TableBody ("",[],[]) (RowHeadColumns 0) [] [Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "A"]],Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "B"]]],Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "C"]],Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "D"]]]]] (TableFoot ("",[],[]) []),Para []]+[Table ("",[],[]) (Caption Nothing []) [(AlignDefault,ColWidthDefault),(AlignDefault,ColWidthDefault)] (TableHead ("",[],[]) []) [TableBody ("",[],[]) (RowHeadColumns 0) [] [Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "A"]],Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "B"]]],Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "C"]],Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "D"]]]]] (TableFoot ("",[],[]) []),Para []]
+ test/odt/native/tableWithSpans.native view
@@ -0,0 +1,134 @@+[ Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 2)+               (ColSpan 1)+               [ Plain+                   [ Str "H1"+                   , Space+                   , Str "Rowspan"+                   , Space+                   , Str "2"+                   ]+               ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "H1-2" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "H1-3" ] ]+           ]+       , Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 2)+               [ Plain [ Str "H2-2/3" ] ]+           ]+       ])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "B1-1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "B1-2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 3)+                (ColSpan 1)+                [ Plain [ Str "Rowspan" , Space , Str "3" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "B2-1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "B2-2" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 2)+                [ Plain [ Str "Columnspan" , Space , Str "2" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "B4-1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 2)+                (ColSpan 2)+                [ Plain+                    [ Str "Columnspan"+                    , Space+                    , Str "&"+                    , Space+                    , Str "Rowspan"+                    , Space+                    , Str "2"+                    ]+                ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "B5-1" ] ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+, Para []+]
+ test/odt/odt/imageRelative.odt view

binary file changed (absent → 16213 bytes)

+ test/odt/odt/preformattedText.odt view

binary file changed (absent → 7342 bytes)

+ test/odt/odt/preformattedTextParentStyle.odt view

binary file changed (absent → 7150 bytes)

+ test/odt/odt/simpleTableWithHeader.odt view

binary file changed (absent → 10377 bytes)

+ test/odt/odt/simpleTableWithMultipleHeaderRows.odt view

binary file changed (absent → 10173 bytes)

+ test/odt/odt/sourceText.odt view

binary file changed (absent → 6805 bytes)

+ test/odt/odt/tableWithSpans.odt view

binary file changed (absent → 10695 bytes)

+ test/pod-reader.native view
@@ -0,0 +1,393 @@+[ Header+    1+    ( "" , [] , [] )+    [ Str "POD" , Space , Str "TEST" , Space , Str "SUITE" ]+, Para+    [ Str "This"+    , Space+    , Str "is"+    , Space+    , Str "a"+    , Space+    , Str "test"+    , Space+    , Link+        ( "" , [] , [] )+        [ Str "Pod" ]+        ( "https://perldoc.pl/perlpod" , "" )+    , Space+    , Str "document"+    , Space+    , Str "for"+    , Space+    , Str "pandoc."+    ]+, Header 2 ( "" , [] , [] ) [ Str "Head" , Space , Str "2" ]+, Header+    3+    ( "" , [] , [] )+    [ Str "Head"+    , Space+    , Str "3:"+    , Space+    , Emph [ Str "The>" , Space , Str "<Return" ]+    ]+, Header+    4+    ( "" , [] , [] )+    [ Str "How"+    , Space+    , Str "to"+    , Space+    , Str "use"+    , Space+    , Str "the"+    , Space+    , Link+        ( "" , [] , [ ( "manual" , "ls(1)" ) ] )+        [ Str "ls(1)" ]+        ( "" , "" )+    , Space+    , Str "command,"+    , Space+    , Str "an"+    , Space+    , Str "introduction"+    ]+, Header+    5+    ( "" , [] , [] )+    [ Code ( "" , [] , [] ) "Ricky Jay"+    , Space+    , Str "and"+    , Space+    , Str "his"+    , Space+    , Str "52"+    , Space+    , Str "assistants"+    ]+, Header+    6+    ( "" , [] , [] )+    [ Str "The"+    , Space+    , Str "=head5"+    , Space+    , Str "and"+    , Space+    , Str "=head6"+    , Space+    , Str "commands"+    , Space+    , Str "are"+    , Space+    , Str "newer"+    , Space+    , Str "and"+    , Space+    , Str "my"+    , Space+    , Str "syntax"+    , Space+    , Str "highlighting"+    , Space+    , Str "doesn't"+    , Space+    , Str "recognize"+    , Space+    , Str "them."+    , Space+    , Str "In"+    , Space+    , Str "any"+    , Space+    , Str "case,"+    , Space+    , Str "it"+    , Space+    , Str "should"+    , Space+    , Str "be"+    , Space+    , Str "possible"+    , Space+    , Str "to"+    , Space+    , Str "have"+    , Space+    , Str "a"+    , Space+    , Str "very"+    , Space+    , Str "long"+    , Space+    , Str "paragraph"+    , Space+    , Str "in"+    , Space+    , Str "the"+    , Space+    , Str "heading."+    ]+, Header+    6+    ( "" , [] , [] )+    [ Str "It"+    , Space+    , Str "should"+    , Space+    , Str "also"+    , Space+    , Str "be"+    , Space+    , Str "possible"+    , Space+    , Str "to"+    , Space+    , Str "start"+    , Space+    , Str "the"+    , Space+    , Str "heading"+    , Space+    , Str "paragraph"+    , Space+    , Str "on"+    , Space+    , Str "the"+    , Space+    , Str "next"+    , Space+    , Str "line"+    ]+, RawBlock+    (Format "html")+    "<strong>This is a raw block destined for the HTML format</strong>\n\n"+, BulletList+    [ [ Para [ Str "Bulleted" , Space , Str "list" ] ]+    , [ Para [ Str "Ordered" , Space , Str "list" ]+      , OrderedList+          ( 1 , DefaultStyle , DefaultDelim )+          [ [ Para+                [ Str "Here's"+                , Space+                , Str "a"+                , Space+                , Str "verbatim"+                , Space+                , Str "paragraph"+                , Space+                , Str "in"+                , Space+                , Str "this"+                , Space+                , Str "list"+                , Space+                , Str "item:"+                ]+            , CodeBlock+                ( "" , [] , [] )+                "    this is a code block\nthis is still part of the code block\n  so is this.\nIt seems that the prefixed spaces in verbatim blocks in pod don't get stripped.\n\n This should continue the previous code block despite the intervening blank\n line, because the first line starts with a space\n\n\n\n    the above blank lines with varying numbers of spaces should also be in\n the code block\n    pod formatters should (but not must) expand tabs by default\nso we're not special casing pandoc's behavior there in any way\n"+            , Para+                [ Str "Wow,"+                , Space+                , Str "that"+                , Space+                , Str "was"+                , Space+                , Str "fun."+                ]+            ]+          , [ Para [ Str "Definition" , Space , Str "list" ]+            , DefinitionList+                [ ( [ Span+                        ( "" , [] , [] )+                        [ Str "Marvin"+                        , Space+                        , Str "the"+                        , Space+                        , Str "Martian"+                        ]+                    ]+                  , [ [ Para+                          [ Str "A"+                          , Space+                          , Str "cartoon"+                          , Space+                          , Str "alien"+                          ]+                      ]+                    ]+                  )+                , ( [ Span+                        ( "" , [] , [] )+                        [ Emph+                            [ Str "The"+                            , Space+                            , Str "Sun"+                            , Space+                            , Str "Also"+                            , Space+                            , Str "Rises"+                            ]+                        ]+                    ]+                  , [ [ Para+                          [ Str "A"+                          , Space+                          , Str "novel"+                          , Space+                          , Str "by"+                          , Space+                          , Str "Ernest"+                          , Space+                          , Str "Hemingway"+                          ]+                      ]+                    ]+                  )+                , ( [ Span+                        ( "" , [] , [] )+                        [ Code ( "" , [] , [] ) "undefined" ]+                    ]+                  , [ [] ]+                  )+                , ( [ Span+                        ( "" , [] , [] )+                        [ Str "And"+                        , Space+                        , Str "now,"+                        , Space+                        , Str "a"+                        , Space+                        , Str "quotation"+                        ]+                    ]+                  , [ [ BlockQuote+                          [ Para+                              [ Str "Where's"+                              , Space+                              , Str "my"+                              , Space+                              , Str "space"+                              , Space+                              , Str "modulator?"+                              ]+                          ]+                      ]+                    ]+                  )+                ]+            ]+          , [ Para+                [ Str "And"+                , Space+                , Str "the"+                , Space+                , Str "list"+                , Space+                , Str "continues."+                ]+            ]+          ]+      ]+    , [ Para+          [ Str "And"+          , Space+          , Str "so"+          , Space+          , Str "does"+          , Space+          , Str "the"+          , Space+          , Str "other"+          , Space+          , Str "one,"+          , Space+          , Str "even"+          , Space+          , Str "if"+          , Space+          , Str "I"+          , Space+          , Str "forget"+          , Space+          , Str "the"+          , Space+          , Str "asterisk."+          ]+      ]+    ]+, Div+    ( "" , [ "neat" ] , [] )+    [ Para+        [ Str "This"+        , Space+        , Str "is"+        , Space+        , Str "a"+        , Space+        , Str "div"+        , Space+        , Str "for"+        , Space+        , Str "our"+        , Space+        , Str "purposes."+        ]+    , Para+        [ Str "It"+        , Space+        , Str "should"+        , Space+        , Str "parse"+        , Space+        , Strong [ Str "content" ]+        , Space+        , Str "inside"+        , Space+        , Str "of"+        , Space+        , Str "it."+        ]+    , BulletList+        [ [ Para [ Str "Like" , Space , Str "this" ] ] ]+    ]+, Div+    ( "" , [ "excitement" ] , [] )+    [ Para+        [ Str "this"+        , Space+        , Str "is"+        , Space+        , Str "its"+        , Space+        , Str "own"+        , Space+        , Str "div"+        ]+    ]+, RawBlock+    (Format "html") " <p>and this is its own raw block</p>\n"+, RawBlock (Format "html") "\n<p>so is this</p>\n"+, Header+    2+    ( "" , [] , [] )+    [ Code ( "" , [] , [] ) "=cut"+    , Space+    , Str "before"+    , Space+    , Str "any"+    , Space+    , Code ( "" , [] , [] ) "=item"+    , Space+    , Str "in"+    , Space+    , Code ( "" , [] , [] ) "=over"+    ]+, BulletList+    [ [ Para [ Str "a" ] , Para [ Str "b" ] ]+    , [ Para [ Str "c" ] ]+    ]+]
+ test/pod-reader.pod view
@@ -0,0 +1,155 @@+text before any Pod commands is not parsed, which is unusual for formats+supported by pandoc, but ++=head1 POD TEST SUITE++This is a test L<Pod|https://perldoc.pl/perlpod> document for pandoc.++=encoding utf8++=head2 Head 2++=head3 Head 3: I<< The> <Return >>++=head4 How to use the L<ls(1)> command,+an introduction++=head5 C<Ricky Jay> and his 52 assistants++=head6 The =head5 and =head6 commands are newer and my syntax highlighting+doesn't recognize them. In any case, it should be possible to have a very long+paragraph in the heading.++=head6+It should also be possible to start the heading paragraph on the next line++=cut++This doesn't get parsed at all.++=begin html++<strong>This is a raw block destined for the HTML format</strong>++=end html++=over++=item *++Bulleted list++=item *++Ordered list++=over++=item 1.++Here's a verbatim paragraph in this list item:++    this is a code block+this is still part of the code block+  so is this.+It seems that the prefixed spaces in verbatim blocks in pod don't get stripped.++ This should continue the previous code block despite the intervening blank+ line, because the first line starts with a space+    ++ +    the above blank lines with varying numbers of spaces should also be in+ the code block+	pod formatters should (but not must) expand tabs by default+so we're not special casing pandoc's behavior there in any way++Wow, that was fun.++=item 2.++Definition list++=over++=item Marvin the MZ<>artian++A cartoon alien++=item I<The Sun+Also Rises>++A novel by Ernest Hemingway++=item C<undefined>++=item And now, a quotation++=over++Where's my space modulator?++=back++=back++=item 3.++And the list continues.++=back++=item++And so does the other one, even if I forget the asterisk.++=back++=begin :neat++This is a div for our purposes.++It should parse B<< content >> inside of it.++=over++=item++Like this++=back++=end :neat++=for :excitement this is its own div++=for html <p>and this is its own raw block</p>++=for html+<p>so is this</p>++=head2 C<=cut> before any C<=item> in C<=over>++=over++=cut++blah++=item *++a++=cut++blah blah++=pod++b++=item *++c++=back
+ test/pptx-reader/basic.native view
@@ -0,0 +1,149 @@+[ Header 2 ( "slide-1" , [] , [] ) [ Str "LLMs" ]+, BulletList+    [ [ Plain+          [ Str+              "Provider  \61664 Available LLMs \8211 who manages? How?"+          ]+      ]+    , [ Plain+          [ Str+              "EW maintained list of \8220approved\8221 LLMs for Universal workers"+          ]+      ]+    , [ Plain+          [ Str+              "Rebuilding of UWs to the \8220Newgen\8221 thing completely"+          ]+      ]+    , [ Plain [ Str "Streaming support" ] ]+    , [ Plain [ Str "Multimodal (voice streaming) models?" ] ]+    ]+, Header+    2+    ( "slide-2" , [] , [] )+    [ Str "Everworker   venn   diagram" ]+, Para [ Str "SKILLS" ]+, Para [ Str "" ]+, Para [ Str "Specialized Workers / Workflows:" ]+, Para [ Str "" ]+, Para [ Str "n8n, UI Path, " ]+, Para [ Str "other RPA" ]+, Para [ Str "BRAINS" ]+, Para [ Str "" ]+, Para [ Str "Universal Workers / AI Agents:" ]+, Para [ Str "" ]+, Para [ Str "openai , anthropic," ]+, Para [ Str "Crew AI, other " ]+, Para [ Str "\8220AI natives\8221" ]+, Para [ Str "KNOWLEDGE " ]+, Para [ Str "" ]+, Para [ Str "Data / " ]+, Para [ Str "RAG Pipelines" ]+, Para [ Str "" ]+, Para+    [ Str "Vector DBs, specialized data prep vendors, \8230" ]+, Para [ Str "glean" ]+, Para [ Str "EW" ]+, Header 2 ( "slide-3" , [] , [] ) [ Str "Table" ]+, Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Col1" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Col2" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Col3" ] ]+           ]+       ])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Name" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Anton" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Antich" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Age" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "23" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "years" ] ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+, Para+    [ Image+        ( "" , [] , [] ) [] ( "ppt/media/image1.png" , "Picture 6" )+    ]+, Header 2 ( "slide-4" , [] , [] ) [ Str "Smart Art" ]+, Div+    ( ""+    , [ "smartart" , "chevron2" ]+    , [ ( "layout" , "chevron2" ) ]+    )+    [ Para [ Strong [ Str "First" ] ]+    , BulletList+        [ [ Plain [ Str "another" ] ]+        , [ Plain [ Str "subtitle" ] ]+        ]+    , Para [ Strong [ Str "Second" ] ]+    , BulletList+        [ [ Plain [ Str "and yet again" ] ]+        , [ Plain [ Str "yet more" ] ]+        ]+    ]+]
+ test/pptx-reader/basic.pptx view

binary file changed (absent → 111674 bytes)

test/pptx/background-image/output.pptx view

binary file changed (53335 → 53336 bytes)

test/pptx/background-image/templated.pptx view

binary file changed (66426 → 66427 bytes)

test/pptx/comparison/both-columns/output.pptx view

binary file changed (44543 → 44543 bytes)

test/pptx/comparison/both-columns/templated.pptx view

binary file changed (57667 → 57666 bytes)

test/pptx/comparison/extra-image/output.pptx view

binary file changed (44571 → 44572 bytes)

test/pptx/comparison/extra-image/templated.pptx view

binary file changed (57693 → 57693 bytes)

test/pptx/comparison/extra-text/output.pptx view

binary file changed (44543 → 44543 bytes)

test/pptx/comparison/extra-text/templated.pptx view

binary file changed (57667 → 57666 bytes)

test/pptx/comparison/non-text-first/output.pptx view

binary file changed (44458 → 44459 bytes)

test/pptx/comparison/non-text-first/templated.pptx view

binary file changed (57553 → 57553 bytes)

test/pptx/content-with-caption/heading-text-image/output.pptx view

binary file changed (44300 → 44302 bytes)

test/pptx/content-with-caption/heading-text-image/templated.pptx view

binary file changed (57390 → 57391 bytes)

test/pptx/content-with-caption/image-text/output.pptx view

binary file changed (44989 → 44999 bytes)

test/pptx/content-with-caption/image-text/templated.pptx view

binary file changed (58079 → 58089 bytes)

test/pptx/content-with-caption/text-image/output.pptx view

binary file changed (44241 → 44244 bytes)

test/pptx/content-with-caption/text-image/templated.pptx view

binary file changed (57330 → 57332 bytes)

test/pptx/document-properties-short-desc/output.pptx view

binary file changed (28585 → 28579 bytes)

test/pptx/document-properties-short-desc/templated.pptx view

binary file changed (41671 → 41666 bytes)

test/pptx/footer/basic/output.pptx view

binary file changed (52724 → 52718 bytes)

test/pptx/footer/fixed-date/output.pptx view

binary file changed (51349 → 51344 bytes)

test/pptx/footer/higher-slide-number/output.pptx view

binary file changed (52735 → 52729 bytes)

test/pptx/footer/no-title-slide/output.pptx view

binary file changed (52309 → 52303 bytes)

test/pptx/images/output.pptx view

binary file changed (46208 → 46224 bytes)

test/pptx/images/templated.pptx view

binary file changed (59299 → 59315 bytes)

test/pptx/incremental-lists/with-flag/output.pptx view

binary file changed (77152 → 77156 bytes)

test/pptx/incremental-lists/with-flag/templated.pptx view

binary file changed (90277 → 90284 bytes)

test/pptx/incremental-lists/without-flag/output.pptx view

binary file changed (75402 → 75406 bytes)

test/pptx/incremental-lists/without-flag/templated.pptx view

binary file changed (88522 → 88529 bytes)

test/pptx/layouts/deleted.pptx view

binary file changed (55691 → 55633 bytes)

test/pptx/layouts/moved.pptx view

binary file changed (66426 → 66368 bytes)

+ test/pptx/metadata-speaker-notes/input.native view
@@ -0,0 +1,3 @@+Pandoc (Meta {unMeta = fromList [("author",MetaInlines [Str "Jesse",Space,Str "Rosenthal"]),("notes",MetaBlocks [Para [Str "These",Space,Str "are",Space,Str "speaker",Space,Str "notes",Space,Str "from",Space,Str "metadata."]]),("title",MetaInlines [Str "Testing"])]})+[Header 1 ("a-header",[],[]) [Str "A",Space,Str "header"]+,Para [Str "And",Space,Str "a",Space,Str "new",Space,Str "slide."]]
+ test/pptx/metadata-speaker-notes/output.pptx view

binary file changed (absent → 31689 bytes)

+ test/pptx/metadata-speaker-notes/templated.pptx view

binary file changed (absent → 44773 bytes)

+ test/pptx/reference-no-slides.pptx view

binary file changed (absent → 30988 bytes)

+ test/pptx/reference-no-slides/add-slides/input.native view
@@ -0,0 +1,14 @@+[ Header+    2+    ( "first-slide" , [] , [] )+    [ Str "First" , Space , Str "Slide" ]+, Para [ Str "Title" ]+, Header+    2+    ( "second-slide" , [] , [] )+    [ Str "Second" , Space , Str "Slide" ]+, BulletList+    [ [ Plain [ Str "First" , Space , Str "item" ] ]+    , [ Plain [ Str "Second" , Space , Str "item" ] ]+    ]+]
+ test/pptx/reference-no-slides/add-slides/output.pptx view

binary file changed (absent → 28888 bytes)

+ test/pptx/reference-no-slides/with-notes/input.native view
@@ -0,0 +1,70 @@+[ Header+    2+    ( "first-slide" , [] , [] )+    [ Str "First" , Space , Str "Slide" ]+, Para+    [ Str "First"+    , Space+    , Str "slide"+    , Space+    , Str "with"+    , Space+    , Str "notes"+    ]+, Div+    ( "" , [ "notes" ] , [] )+    [ Para+        [ Str "Notes"+        , Space+        , Str "for"+        , Space+        , Str "the"+        , Space+        , Str "first"+        , Space+        , Str "slide"+        ]+    ]+, Header+    2+    ( "second-slide" , [] , [] )+    [ Str "Second" , Space , Str "Slide" ]+, Para+    [ Str "Slide"+    , Space+    , Str "without"+    , Space+    , Str "notes"+    ]+, Header+    2+    ( "third-slide" , [] , [] )+    [ Str "Third" , Space , Str "Slide" ]+, Para+    [ Str "Slide"+    , Space+    , Str "with"+    , Space+    , Str "notes"+    , Space+    , Str "again"+    ]+, BulletList+    [ [ Plain [ Str "First" , Space , Str "item" ] ]+    , [ Plain [ Str "Second" , Space , Str "item" ] ]+    ]+, Div+    ( "" , [ "notes" ] , [] )+    [ Para+        [ Str "Notes"+        , Space+        , Str "for"+        , Space+        , Str "the"+        , Space+        , Str "third"+        , Space+        , Str "slides"+        ]+    ]+]
+ test/pptx/reference-no-slides/with-notes/output.pptx view

binary file changed (absent → 33927 bytes)

+ test/pptx/single-column/image/input.native view
@@ -0,0 +1,22 @@+[ Header+    1+    ( "single-column" , [] , [] )+    [ Str "Single" , Space , Str "column" ]+, Div+    ( "" , [ "columns" ] , [] )+    [ Div+        ( "" , [ "column" ] , [] )+        [ Figure+            ( "" , [] , [] )+            (Caption+               Nothing [ Plain [ Str "an" , Space , Str "image" ] ])+            [ Plain+                [ Image+                    ( "" , [] , [] )+                    [ Str "an" , Space , Str "image" ]+                    ( "lalune.jpg" , "" )+                ]+            ]+        ]+    ]+]
+ test/pptx/single-column/image/output.pptx view

binary file changed (absent → 44216 bytes)

+ test/pptx/single-column/image/templated.pptx view

binary file changed (absent → 57307 bytes)

+ test/pptx/single-column/text/input.native view
@@ -0,0 +1,13 @@+[ Header+    1+    ( "single-column" , [] , [] )+    [ Str "Single" , Space , Str "column" ]+, Div+    ( "" , [ "columns" ] , [] )+    [ Div+        ( "" , [ "column" ] , [] )+        [ Para [ Str "One" , Space , Str "paragraph." ]+        , Para [ Str "Another" , Space , Str "paragraph." ]+        ]+    ]+]
+ test/pptx/single-column/text/output.pptx view

binary file changed (absent → 27619 bytes)

+ test/pptx/single-column/text/templated.pptx view

binary file changed (absent → 40714 bytes)

test/pptx/slide-level-0/h1-with-image/output.pptx view

binary file changed (44212 → 44217 bytes)

test/pptx/slide-level-0/h1-with-image/templated.pptx view

binary file changed (57302 → 57307 bytes)

test/pptx/slide-level-0/h2-with-image/output.pptx view

binary file changed (44212 → 44217 bytes)

test/pptx/slide-level-0/h2-with-image/templated.pptx view

binary file changed (57302 → 57307 bytes)

test/pptx/speaker-notes-after-metadata/output.pptx view

binary file changed (31580 → 31575 bytes)

test/pptx/speaker-notes-after-metadata/templated.pptx view

binary file changed (44666 → 44659 bytes)

test/pptx/speaker-notes-afterseps/output.pptx view

binary file changed (51455 → 51466 bytes)

test/pptx/speaker-notes-afterseps/templated.pptx view

binary file changed (64548 → 64559 bytes)

test/pptx/tables/output.pptx view

binary file changed (29134 → 29134 bytes)

test/pptx/tables/templated.pptx view

binary file changed (42228 → 42229 bytes)

test/pptx/two-column/text-and-image/output.pptx view

binary file changed (45489 → 45496 bytes)

test/pptx/two-column/text-and-image/templated.pptx view

binary file changed (58574 → 58582 bytes)

test/rst-reader.native view
@@ -12,7 +12,7 @@             , MetaInlines                 [ Str "July" , Space , Str "17," , Space , Str "2006" ]             )-          , ( "revision" , MetaBlocks [ Para [ Str "3" ] ] )+          , ( "revision" , MetaInlines [ Str "3" ] )           , ( "subtitle" , MetaInlines [ Str "Subtitle" ] )           , ( "title"             , MetaInlines@@ -598,11 +598,11 @@   , BlockQuote       [ DefinitionList           [ ( [ Str "address" ]-            , [ [ Para [ Str "61" , Space , Str "Main" , Space , Str "St." ] ]+            , [ [ Plain [ Str "61" , Space , Str "Main" , Space , Str "St." ] ]               ]             )           , ( [ Str "city" ]-            , [ [ Para+            , [ [ Plain                     [ Emph [ Str "Nowhere" ]                     , Str ","                     , Space@@ -613,16 +613,16 @@                 ]               ]             )-          , ( [ Str "phone" ] , [ [ Para [ Str "123-4567" ] ] ] )+          , ( [ Str "phone" ] , [ [ Plain [ Str "123-4567" ] ] ] )           ]       ]   , DefinitionList       [ ( [ Str "address" ]-        , [ [ Para [ Str "61" , Space , Str "Main" , Space , Str "St." ] ]+        , [ [ Plain [ Str "61" , Space , Str "Main" , Space , Str "St." ] ]           ]         )       , ( [ Str "city" ]-        , [ [ Para+        , [ [ Plain                 [ Emph [ Str "Nowhere" ]                 , Str ","                 , Space@@ -633,7 +633,7 @@             ]           ]         )-      , ( [ Str "phone" ] , [ [ Para [ Str "123-4567" ] ] ] )+      , ( [ Str "phone" ] , [ [ Plain [ Str "123-4567" ] ] ] )       ]   , Header       1 ( "html-blocks" , [] , [] ) [ Str "HTML" , Space , Str "Blocks" ]
test/s5-basic.html view
@@ -11,10 +11,16 @@   <meta name="date" content="2006-07-15" />   <title>My S5 Document</title>   <style type="text/css">-    code{white-space: pre-wrap;}+    /* Default styles provided by pandoc.+    ** See https://pandoc.org/MANUAL.html#variables-for-html for config info.+    */     span.smallcaps{font-variant: small-caps;}-    div.columns{display: flex; gap: min(4vw, 1.5em);}-    div.column{flex: auto; overflow-x: auto;}+    div.columns{display: flex; gap: 1.5em;}+    div.column{flex: auto;}+    @media screen {+    div.columns{gap: min(4vw, 1.5em);}+    div.column{overflow-x: auto;}+    }     div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}     /* The extra [class] is a hack that increases specificity enough to        override a similar rule in reveal.js */
test/s5-fancy.html view
@@ -11,10 +11,16 @@   <meta name="date" content="2006-07-15" />   <title>My S5 Document</title>   <style type="text/css">-    code{white-space: pre-wrap;}+    /* Default styles provided by pandoc.+    ** See https://pandoc.org/MANUAL.html#variables-for-html for config info.+    */     span.smallcaps{font-variant: small-caps;}-    div.columns{display: flex; gap: min(4vw, 1.5em);}-    div.column{flex: auto; overflow-x: auto;}+    div.columns{display: flex; gap: 1.5em;}+    div.column{flex: auto;}+    @media screen {+    div.columns{gap: min(4vw, 1.5em);}+    div.column{overflow-x: auto;}+    }     div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}     /* The extra [class] is a hack that increases specificity enough to        override a similar rule in reveal.js */@@ -36,8 +42,8 @@   <link rel="stylesheet" href="s5/default/opera.css" type="text/css" media="projection" id="operaFix" />   <!-- S5 JS -->   <script src="s5/default/slides.js" type="text/javascript"></script>-  <script-  src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml-full.js"+  <script defer=""+  src="https://cdn.jsdelivr.net/npm/mathjax@4/tex-chtml.js"   type="text/javascript"></script> </head> <body>
test/s5-inserts.html view
@@ -3,16 +3,22 @@ <head>   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />   <meta http-equiv="Content-Style-Type" content="text/css" />-  <meta name="generator" content="pandoc" />+  <meta name="generator" content="pandoc " />   <meta name="author" content="Sam Smith" />   <meta name="author" content="Jen Jones" />   <meta name="date" content="2006-07-15" />   <title>My S5 Document</title>   <style type="text/css">-    code{white-space: pre-wrap;}+    /* Default styles provided by pandoc.+    ** See https://pandoc.org/MANUAL.html#variables-for-html for config info.+    */     span.smallcaps{font-variant: small-caps;}-    div.columns{display: flex; gap: min(4vw, 1.5em);}-    div.column{flex: auto; overflow-x: auto;}+    div.columns{display: flex; gap: 1.5em;}+    div.column{flex: auto;}+    @media screen {+    div.columns{gap: min(4vw, 1.5em);}+    div.column{overflow-x: auto;}+    }     div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}     /* The extra [class] is a hack that increases specificity enough to        override a similar rule in reveal.js */
+ test/tables.bbcode view
@@ -0,0 +1,60 @@+Simple table with caption:++Demonstration of simple table syntax.+[table]+[tr][th]Right[/th][th]Left[/th][th]Center[/th][th]Default[/th][/tr]+[tr][td]12[/td][td]12[/td][td]12[/td][td]12[/td][/tr]+[tr][td]123[/td][td]123[/td][td]123[/td][td]123[/td][/tr]+[tr][td]1[/td][td]1[/td][td]1[/td][td]1[/td][/tr]+[/table]++Simple table without caption:++[table]+[tr][th]Right[/th][th]Left[/th][th]Center[/th][th]Default[/th][/tr]+[tr][td]12[/td][td]12[/td][td]12[/td][td]12[/td][/tr]+[tr][td]123[/td][td]123[/td][td]123[/td][td]123[/td][/tr]+[tr][td]1[/td][td]1[/td][td]1[/td][td]1[/td][/tr]+[/table]++Simple table indented two spaces:++Demonstration of simple table syntax.+[table]+[tr][th]Right[/th][th]Left[/th][th]Center[/th][th]Default[/th][/tr]+[tr][td]12[/td][td]12[/td][td]12[/td][td]12[/td][/tr]+[tr][td]123[/td][td]123[/td][td]123[/td][td]123[/td][/tr]+[tr][td]1[/td][td]1[/td][td]1[/td][td]1[/td][/tr]+[/table]++Multiline table with caption:++Here's the caption. It may span multiple lines.+[table]+[tr][th]Centered Header[/th][th]Left Aligned[/th][th]Right Aligned[/th][th]Default aligned[/th][/tr]+[tr][td]First[/td][td]row[/td][td]12.0[/td][td]Example of a row that spans multiple lines.[/td][/tr]+[tr][td]Second[/td][td]row[/td][td]5.0[/td][td]Here's another one. Note the blank line between rows.[/td][/tr]+[/table]++Multiline table without caption:++[table]+[tr][th]Centered Header[/th][th]Left Aligned[/th][th]Right Aligned[/th][th]Default aligned[/th][/tr]+[tr][td]First[/td][td]row[/td][td]12.0[/td][td]Example of a row that spans multiple lines.[/td][/tr]+[tr][td]Second[/td][td]row[/td][td]5.0[/td][td]Here's another one. Note the blank line between rows.[/td][/tr]+[/table]++Table without column headers:++[table]+[tr][td]12[/td][td]12[/td][td]12[/td][td]12[/td][/tr]+[tr][td]123[/td][td]123[/td][td]123[/td][td]123[/td][/tr]+[tr][td]1[/td][td]1[/td][td]1[/td][td]1[/td][/tr]+[/table]++Multiline table without column headers:++[table]+[tr][td]First[/td][td]row[/td][td]12.0[/td][td]Example of a row that spans multiple lines.[/td][/tr]+[tr][td]Second[/td][td]row[/td][td]5.0[/td][td]Here's another one. Note the blank line between rows.[/td][/tr]+[/table]
test/tables.djot view
@@ -44,11 +44,13 @@  Table without column headers: +|----:|:----|:---:|----:| |  12 | 12  | 12  |  12 | | 123 | 123 | 123 | 123 | |   1 | 1   |  1  |   1 |  Multiline table without column headers: +|:------:|:----|-----:|-----------------------------------------------------| | First  | row | 12.0 | Example of a row that spans multiple lines.           | | Second | row |  5.0 | Here's another one. Note the blank line between rows. |
test/tables.haddock view
@@ -2,7 +2,7 @@  +-------+------+--------+---------+ | Right | Left | Center | Default |-+=======+======+========+=========+++======:+:=====+:======:+=========+ | 12    | 12   | 12     | 12      | +-------+------+--------+---------+ | 123   | 123  | 123    | 123     |@@ -16,7 +16,7 @@  +-------+------+--------+---------+ | Right | Left | Center | Default |-+=======+======+========+=========+++======:+:=====+:======:+=========+ | 12    | 12   | 12     | 12      | +-------+------+--------+---------+ | 123   | 123  | 123    | 123     |@@ -28,7 +28,7 @@  +-------+------+--------+---------+ | Right | Left | Center | Default |-+=======+======+========+=========+++======:+:=====+:======:+=========+ | 12    | 12   | 12     | 12      | +-------+------+--------+---------+ | 123   | 123  | 123    | 123     |@@ -43,7 +43,7 @@ +-----------+----------+------------+---------------------------+ | Centered  | Left     | Right      | Default aligned           | | Header    | Aligned  | Aligned    |                           |-+===========+==========+============+===========================+++:=========:+:=========+===========:+:==========================+ | First     | row      | 12.0       | Example of a row that     | |           |          |            | spans multiple lines.     | +-----------+----------+------------+---------------------------+@@ -59,7 +59,7 @@ +-----------+----------+------------+---------------------------+ | Centered  | Left     | Right      | Default aligned           | | Header    | Aligned  | Aligned    |                           |-+===========+==========+============+===========================+++:=========:+:=========+===========:+:==========================+ | First     | row      | 12.0       | Example of a row that     | |           |          |            | spans multiple lines.     | +-----------+----------+------------+---------------------------+@@ -70,7 +70,7 @@  Table without column headers: -+-----+-----+-----+-----+++----:+:----+:---:+----:+ | 12  | 12  | 12  | 12  | +-----+-----+-----+-----+ | 123 | 123 | 123 | 123 |@@ -80,7 +80,7 @@  Multiline table without column headers: -+-----------+----------+------------+---------------------------+++:---------:+:---------+-----------:+---------------------------+ | First     | row      | 12.0       | Example of a row that     | |           |          |            | spans multiple lines.     | +-----------+----------+------------+---------------------------+
test/tables.html4 view
@@ -2,7 +2,7 @@ <table> <caption>Demonstration of simple table syntax.</caption> <thead>-<tr class="header">+<tr> <th align="right">Right</th> <th align="left">Left</th> <th align="center">Center</th>@@ -10,19 +10,19 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td align="right">12</td> <td align="left">12</td> <td align="center">12</td> <td>12</td> </tr>-<tr class="even">+<tr> <td align="right">123</td> <td align="left">123</td> <td align="center">123</td> <td>123</td> </tr>-<tr class="odd">+<tr> <td align="right">1</td> <td align="left">1</td> <td align="center">1</td>@@ -33,7 +33,7 @@ <p>Simple table without caption:</p> <table> <thead>-<tr class="header">+<tr> <th align="right">Right</th> <th align="left">Left</th> <th align="center">Center</th>@@ -41,19 +41,19 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td align="right">12</td> <td align="left">12</td> <td align="center">12</td> <td>12</td> </tr>-<tr class="even">+<tr> <td align="right">123</td> <td align="left">123</td> <td align="center">123</td> <td>123</td> </tr>-<tr class="odd">+<tr> <td align="right">1</td> <td align="left">1</td> <td align="center">1</td>@@ -65,7 +65,7 @@ <table> <caption>Demonstration of simple table syntax.</caption> <thead>-<tr class="header">+<tr> <th align="right">Right</th> <th align="left">Left</th> <th align="center">Center</th>@@ -73,19 +73,19 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td align="right">12</td> <td align="left">12</td> <td align="center">12</td> <td>12</td> </tr>-<tr class="even">+<tr> <td align="right">123</td> <td align="left">123</td> <td align="center">123</td> <td>123</td> </tr>-<tr class="odd">+<tr> <td align="right">1</td> <td align="left">1</td> <td align="center">1</td>@@ -103,7 +103,7 @@ <col width="35%" /> </colgroup> <thead>-<tr class="header">+<tr> <th align="center">Centered Header</th> <th align="left">Left Aligned</th> <th align="right">Right Aligned</th>@@ -111,13 +111,13 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td align="center">First</td> <td align="left">row</td> <td align="right">12.0</td> <td align="left">Example of a row that spans multiple lines.</td> </tr>-<tr class="even">+<tr> <td align="center">Second</td> <td align="left">row</td> <td align="right">5.0</td>@@ -134,7 +134,7 @@ <col width="35%" /> </colgroup> <thead>-<tr class="header">+<tr> <th align="center">Centered Header</th> <th align="left">Left Aligned</th> <th align="right">Right Aligned</th>@@ -142,13 +142,13 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td align="center">First</td> <td align="left">row</td> <td align="right">12.0</td> <td align="left">Example of a row that spans multiple lines.</td> </tr>-<tr class="even">+<tr> <td align="center">Second</td> <td align="left">row</td> <td align="right">5.0</td>@@ -159,19 +159,19 @@ <p>Table without column headers:</p> <table> <tbody>-<tr class="odd">+<tr> <td align="right">12</td> <td align="left">12</td> <td align="center">12</td> <td align="right">12</td> </tr>-<tr class="even">+<tr> <td align="right">123</td> <td align="left">123</td> <td align="center">123</td> <td align="right">123</td> </tr>-<tr class="odd">+<tr> <td align="right">1</td> <td align="left">1</td> <td align="center">1</td>@@ -188,13 +188,13 @@ <col width="35%" /> </colgroup> <tbody>-<tr class="odd">+<tr> <td align="center">First</td> <td align="left">row</td> <td align="right">12.0</td> <td>Example of a row that spans multiple lines.</td> </tr>-<tr class="even">+<tr> <td align="center">Second</td> <td align="left">row</td> <td align="right">5.0</td>
test/tables.html5 view
@@ -2,7 +2,7 @@ <table> <caption>Demonstration of simple table syntax.</caption> <thead>-<tr class="header">+<tr> <th style="text-align: right;">Right</th> <th style="text-align: left;">Left</th> <th style="text-align: center;">Center</th>@@ -10,19 +10,19 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td style="text-align: right;">12</td> <td style="text-align: left;">12</td> <td style="text-align: center;">12</td> <td>12</td> </tr>-<tr class="even">+<tr> <td style="text-align: right;">123</td> <td style="text-align: left;">123</td> <td style="text-align: center;">123</td> <td>123</td> </tr>-<tr class="odd">+<tr> <td style="text-align: right;">1</td> <td style="text-align: left;">1</td> <td style="text-align: center;">1</td>@@ -33,7 +33,7 @@ <p>Simple table without caption:</p> <table> <thead>-<tr class="header">+<tr> <th style="text-align: right;">Right</th> <th style="text-align: left;">Left</th> <th style="text-align: center;">Center</th>@@ -41,19 +41,19 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td style="text-align: right;">12</td> <td style="text-align: left;">12</td> <td style="text-align: center;">12</td> <td>12</td> </tr>-<tr class="even">+<tr> <td style="text-align: right;">123</td> <td style="text-align: left;">123</td> <td style="text-align: center;">123</td> <td>123</td> </tr>-<tr class="odd">+<tr> <td style="text-align: right;">1</td> <td style="text-align: left;">1</td> <td style="text-align: center;">1</td>@@ -65,7 +65,7 @@ <table> <caption>Demonstration of simple table syntax.</caption> <thead>-<tr class="header">+<tr> <th style="text-align: right;">Right</th> <th style="text-align: left;">Left</th> <th style="text-align: center;">Center</th>@@ -73,19 +73,19 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td style="text-align: right;">12</td> <td style="text-align: left;">12</td> <td style="text-align: center;">12</td> <td>12</td> </tr>-<tr class="even">+<tr> <td style="text-align: right;">123</td> <td style="text-align: left;">123</td> <td style="text-align: center;">123</td> <td>123</td> </tr>-<tr class="odd">+<tr> <td style="text-align: right;">1</td> <td style="text-align: left;">1</td> <td style="text-align: center;">1</td>@@ -103,7 +103,7 @@ <col style="width: 35%" /> </colgroup> <thead>-<tr class="header">+<tr> <th style="text-align: center;">Centered Header</th> <th style="text-align: left;">Left Aligned</th> <th style="text-align: right;">Right Aligned</th>@@ -111,13 +111,13 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td style="text-align: center;">First</td> <td style="text-align: left;">row</td> <td style="text-align: right;">12.0</td> <td style="text-align: left;">Example of a row that spans multiple lines.</td> </tr>-<tr class="even">+<tr> <td style="text-align: center;">Second</td> <td style="text-align: left;">row</td> <td style="text-align: right;">5.0</td>@@ -135,7 +135,7 @@ <col style="width: 35%" /> </colgroup> <thead>-<tr class="header">+<tr> <th style="text-align: center;">Centered Header</th> <th style="text-align: left;">Left Aligned</th> <th style="text-align: right;">Right Aligned</th>@@ -143,13 +143,13 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td style="text-align: center;">First</td> <td style="text-align: left;">row</td> <td style="text-align: right;">12.0</td> <td style="text-align: left;">Example of a row that spans multiple lines.</td> </tr>-<tr class="even">+<tr> <td style="text-align: center;">Second</td> <td style="text-align: left;">row</td> <td style="text-align: right;">5.0</td>@@ -161,19 +161,19 @@ <p>Table without column headers:</p> <table> <tbody>-<tr class="odd">+<tr> <td style="text-align: right;">12</td> <td style="text-align: left;">12</td> <td style="text-align: center;">12</td> <td style="text-align: right;">12</td> </tr>-<tr class="even">+<tr> <td style="text-align: right;">123</td> <td style="text-align: left;">123</td> <td style="text-align: center;">123</td> <td style="text-align: right;">123</td> </tr>-<tr class="odd">+<tr> <td style="text-align: right;">1</td> <td style="text-align: left;">1</td> <td style="text-align: center;">1</td>@@ -190,13 +190,13 @@ <col style="width: 35%" /> </colgroup> <tbody>-<tr class="odd">+<tr> <td style="text-align: center;">First</td> <td style="text-align: left;">row</td> <td style="text-align: right;">12.0</td> <td>Example of a row that spans multiple lines.</td> </tr>-<tr class="even">+<tr> <td style="text-align: center;">Second</td> <td style="text-align: left;">row</td> <td style="text-align: right;">5.0</td>
test/tables.latex view
@@ -19,6 +19,7 @@  Simple table without caption: +{\def\LTcaptype{none} % do not increment counter \begin{longtable}[]{@{}rlcl@{}} \toprule\noalign{} Right & Left & Center & Default \\@@ -30,6 +31,7 @@ 123 & 123 & 123 & 123 \\ 1 & 1 & 1 & 1 \\ \end{longtable}+}  Simple table indented two spaces: @@ -53,10 +55,10 @@ Multiline table with caption:  \begin{longtable}[]{@{}-  >{\centering\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.1500}}-  >{\raggedright\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.1375}}-  >{\raggedleft\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.1625}}-  >{\raggedright\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.3500}}@{}}+  >{\centering\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1500}}+  >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1375}}+  >{\raggedleft\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1625}}+  >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.3500}}@{}} \caption{Here's the caption. It may span multiple lines.}\tabularnewline \toprule\noalign{} \begin{minipage}[b]{\linewidth}\centering@@ -90,11 +92,12 @@  Multiline table without caption: +{\def\LTcaptype{none} % do not increment counter \begin{longtable}[]{@{}-  >{\centering\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.1500}}-  >{\raggedright\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.1375}}-  >{\raggedleft\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.1625}}-  >{\raggedright\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.3500}}@{}}+  >{\centering\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1500}}+  >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1375}}+  >{\raggedleft\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1625}}+  >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.3500}}@{}} \toprule\noalign{} \begin{minipage}[b]{\linewidth}\centering Centered Header@@ -112,9 +115,11 @@ First & row & 12.0 & Example of a row that spans multiple lines. \\ Second & row & 5.0 & Here's another one. Note the blank line between rows. \\ \end{longtable}+}  Table without column headers: +{\def\LTcaptype{none} % do not increment counter \begin{longtable}[]{@{}rlcr@{}} \toprule\noalign{} \endhead@@ -124,14 +129,16 @@ 123 & 123 & 123 & 123 \\ 1 & 1 & 1 & 1 \\ \end{longtable}+}  Multiline table without column headers: +{\def\LTcaptype{none} % do not increment counter \begin{longtable}[]{@{}-  >{\centering\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.1500}}-  >{\raggedright\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.1375}}-  >{\raggedleft\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.1625}}-  >{\raggedright\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.3500}}@{}}+  >{\centering\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1500}}+  >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1375}}+  >{\raggedleft\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1625}}+  >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.3500}}@{}} \toprule\noalign{} \endhead \bottomrule\noalign{}@@ -139,3 +146,4 @@ First & row & 12.0 & Example of a row that spans multiple lines. \\ Second & row & 5.0 & Here's another one. Note the blank line between rows. \\ \end{longtable}+}
test/tables.man view
@@ -135,7 +135,7 @@ .PP Multiline table with caption: .PP-Here\[cq]s the caption. It may span multiple lines.+Here\(cqs the caption. It may span multiple lines. .TS tab(@); cw(10.5n) lw(9.6n) rw(11.4n) lw(24.5n).@@ -165,7 +165,7 @@ T}@T{ 5.0 T}@T{-Here\[cq]s another one.+Here\(cqs another one. Note the blank line between rows. T} .TE@@ -201,7 +201,7 @@ T}@T{ 5.0 T}@T{-Here\[cq]s another one.+Here\(cqs another one. Note the blank line between rows. T} .TE@@ -261,7 +261,7 @@ T}@T{ 5.0 T}@T{-Here\[cq]s another one.+Here\(cqs another one. Note the blank line between rows. T} .TE
test/tables.markua view
@@ -28,19 +28,19 @@  Multiline table with caption: -| Centered Header | Left Aligned | Right Aligned | Default aligned                                       |-|:---------------:|:-------------|--------------:|:------------------------------------------------------|-|      First      | row          |          12.0 | Example of a row that spans multiple lines.           |-|     Second      | row          |           5.0 | Here’s another one. Note the blank line between rows. |+| Centered Header | Left Aligned | Right Aligned | Default aligned |+|:--:|:---|---:|:---|+| First | row | 12.0 | Example of a row that spans multiple lines. |+| Second | row | 5.0 | Here’s another one. Note the blank line between rows. |  Here’s the caption. It may span multiple lines.  Multiline table without caption: -| Centered Header | Left Aligned | Right Aligned | Default aligned                                       |-|:---------------:|:-------------|--------------:|:------------------------------------------------------|-|      First      | row          |          12.0 | Example of a row that spans multiple lines.           |-|     Second      | row          |           5.0 | Here’s another one. Note the blank line between rows. |+| Centered Header | Left Aligned | Right Aligned | Default aligned |+|:--:|:---|---:|:---|+| First | row | 12.0 | Example of a row that spans multiple lines. |+| Second | row | 5.0 | Here’s another one. Note the blank line between rows. |  Table without column headers: 
test/tables.ms view
@@ -141,7 +141,7 @@ .LP Multiline table with caption: .PP-Here\[cq]s the caption. It may span multiple lines.+Here\(cqs the caption. It may span multiple lines. .na .nr LLold \n[LL] .TS@@ -181,7 +181,7 @@ 5.0 T}	T{ .nr LL 24.5n-Here\[cq]s another one.+Here\(cqs another one. Note the blank line between rows. T} .TE@@ -229,7 +229,7 @@ 5.0 T}	T{ .nr LL 24.5n-Here\[cq]s another one.+Here\(cqs another one. Note the blank line between rows. T} .TE@@ -303,7 +303,7 @@ 5.0 T}	T{ .nr LL 24.5n-Here\[cq]s another one.+Here\(cqs another one. Note the blank line between rows. T} .TE
test/tables.muse view
@@ -23,6 +23,9 @@  Multiline table with caption: ++:---------:+:---------+-----------:+:--------------------------++| Centered  | Left     | Right      | Default aligned           |+| Header    | Aligned  | Aligned    |                           | +-----------+----------+------------+---------------------------+ | First     | row      | 12.0       | Example of a row that     | |           |          |            | spans multiple lines.     |@@ -33,6 +36,9 @@ +-----------+----------+------------+---------------------------+ Multiline table without caption: ++:---------:+:---------+-----------:+:--------------------------++| Centered  | Left     | Right      | Default aligned           |+| Header    | Aligned  | Aligned    |                           | +-----------+----------+------------+---------------------------+ | First     | row      | 12.0       | Example of a row that     | |           |          |            | spans multiple lines.     |@@ -49,7 +55,7 @@  Multiline table without column headers: -+-----------+----------+------------+---------------------------+++:---------:+:---------+-----------:+---------------------------+ | First     | row      | 12.0       | Example of a row that     | |           |          |            | spans multiple lines.     | +-----------+----------+------------+---------------------------+
test/tables.textile view
@@ -3,7 +3,7 @@ <table> <caption>Demonstration of simple table syntax.</caption> <thead>-<tr class="header">+<tr> <th align="right">Right</th> <th align="left">Left</th> <th align="center">Center</th>@@ -11,19 +11,19 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td align="right">12</td> <td align="left">12</td> <td align="center">12</td> <td align="left">12</td> </tr>-<tr class="even">+<tr> <td align="right">123</td> <td align="left">123</td> <td align="center">123</td> <td align="left">123</td> </tr>-<tr class="odd">+<tr> <td align="right">1</td> <td align="left">1</td> <td align="center">1</td>@@ -44,7 +44,7 @@ <table> <caption>Demonstration of simple table syntax.</caption> <thead>-<tr class="header">+<tr> <th align="right">Right</th> <th align="left">Left</th> <th align="center">Center</th>@@ -52,19 +52,19 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td align="right">12</td> <td align="left">12</td> <td align="center">12</td> <td align="left">12</td> </tr>-<tr class="even">+<tr> <td align="right">123</td> <td align="left">123</td> <td align="center">123</td> <td align="left">123</td> </tr>-<tr class="odd">+<tr> <td align="right">1</td> <td align="left">1</td> <td align="center">1</td>@@ -82,7 +82,7 @@ <col width="16%" /> <col width="35%" /> <thead>-<tr class="header">+<tr> <th align="center">Centered Header</th> <th align="left">Left Aligned</th> <th align="right">Right Aligned</th>@@ -90,13 +90,13 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td align="center">First</td> <td align="left">row</td> <td align="right">12.0</td> <td align="left">Example of a row that spans multiple lines.</td> </tr>-<tr class="even">+<tr> <td align="center">Second</td> <td align="left">row</td> <td align="right">5.0</td>@@ -113,7 +113,7 @@ <col width="16%" /> <col width="35%" /> <thead>-<tr class="header">+<tr> <th align="center">Centered Header</th> <th align="left">Left Aligned</th> <th align="right">Right Aligned</th>@@ -121,13 +121,13 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td align="center">First</td> <td align="left">row</td> <td align="right">12.0</td> <td align="left">Example of a row that spans multiple lines.</td> </tr>-<tr class="even">+<tr> <td align="center">Second</td> <td align="left">row</td> <td align="right">5.0</td>@@ -150,13 +150,13 @@ <col width="16%" /> <col width="35%" /> <tbody>-<tr class="odd">+<tr> <td align="center">First</td> <td align="left">row</td> <td align="right">12.0</td> <td align="left">Example of a row that spans multiple lines.</td> </tr>-<tr class="even">+<tr> <td align="center">Second</td> <td align="left">row</td> <td align="right">5.0</td>
test/tables.typst view
@@ -55,10 +55,10 @@       aligned],),     table.hline(),     [First], [row], [12.0], [Example of a row that spans multiple lines.],-    [Second], [row], [5.0], [Here’s another one. Note the blank line between+    [Second], [row], [5.0], [Here's another one. Note the blank line between     rows.],   )]-  , caption: [Here’s the caption. It may span multiple lines.]+  , caption: [Here's the caption. It may span multiple lines.]   , kind: table   ) @@ -72,7 +72,7 @@       aligned],),     table.hline(),     [First], [row], [12.0], [Example of a row that spans multiple lines.],-    [Second], [row], [5.0], [Here’s another one. Note the blank line between+    [Second], [row], [5.0], [Here's another one. Note the blank line between     rows.],   )]   , kind: table@@ -98,7 +98,7 @@     columns: (15%, 13.75%, 16.25%, 35%),     align: (center,left,right,auto,),     [First], [row], [12.0], [Example of a row that spans multiple lines.],-    [Second], [row], [5.0], [Here’s another one. Note the blank line between+    [Second], [row], [5.0], [Here's another one. Note the blank line between     rows.],   )]   , kind: table
+ test/tables.vimdoc view
@@ -0,0 +1,65 @@+Simple table with caption:++      Right Left    Center  Default ~+         12 12        12    12+        123 123      123    123+          1 1         1     1++    Demonstration of simple table syntax.++Simple table without caption:++      Right Left    Center  Default ~+         12 12        12    12+        123 123      123    123+          1 1         1     1++Simple table indented two spaces:++      Right Left    Center  Default ~+         12 12        12    12+        123 123      123    123+          1 1         1     1++    Demonstration of simple table syntax.++Multiline table with caption:++     Centered  Left           Right Default aligned+      Header   Aligned      Aligned  ~++      First    row             12.0 Example of a row that+                                    spans multiple lines.++      Second   row              5.0 Here's another one.+                                    Note the blank line+                                    between rows.++    Here's the caption. It may span multiple lines.++Multiline table without caption:++     Centered  Left           Right Default aligned+      Header   Aligned      Aligned  ~++      First    row             12.0 Example of a row that+                                    spans multiple lines.++      Second   row              5.0 Here's another one.+                                    Note the blank line+                                    between rows.++Table without column headers:++       12 12     12      12+      123 123    123    123+        1 1       1       1++Multiline table without column headers:++      First   row            12.0 Example of a row that+                                  spans multiple lines.++     Second   row             5.0 Here's another one.+                                  Note the blank line+                                  between rows.
test/tables/nordics.html4 view
@@ -7,7 +7,7 @@ <col width="20%" /> </colgroup> <thead class="simple-head">-<tr class="header">+<tr> <th align="center">Name</th> <th align="center">Capital</th> <th align="center">Population<br />@@ -17,38 +17,38 @@ </tr> </thead> <tbody class="souvereign-states">-<tr class="odd country">+<tr class="country"> <th align="center">Denmark</th> <td align="left">Copenhagen</td> <td align="left">5,809,502</td> <td align="left">43,094</td> </tr>-<tr class="even country">+<tr class="country"> <th align="center">Finland</th> <td align="left">Helsinki</td> <td align="left">5,537,364</td> <td align="left">338,145</td> </tr>-<tr class="odd country">+<tr class="country"> <th align="center">Iceland</th> <td align="left">Reykjavik</td> <td align="left">343,518</td> <td align="left">103,000</td> </tr>-<tr class="even country">+<tr class="country"> <th align="center">Norway</th> <td align="left">Oslo</td> <td align="left">5,372,191</td> <td align="left">323,802</td> </tr>-<tr class="odd country">+<tr class="country"> <th align="center">Sweden</th> <td align="left">Stockholm</td> <td align="left">10,313,447</td> <td align="left">450,295</td> </tr> </tbody><tfoot>-<tr id="summary" class="even">+<tr id="summary"> <td align="center">Total</td> <td align="left"></td> <td id="total-population" align="left">27,376,022</td>
test/tables/nordics.html5 view
@@ -7,7 +7,7 @@ <col style="width: 20%" /> </colgroup> <thead class="simple-head">-<tr class="header">+<tr> <th style="text-align: center;">Name</th> <th style="text-align: center;">Capital</th> <th style="text-align: center;">Population<br />@@ -17,38 +17,38 @@ </tr> </thead> <tbody class="souvereign-states">-<tr class="odd country">+<tr class="country"> <th style="text-align: center;">Denmark</th> <td style="text-align: left;">Copenhagen</td> <td style="text-align: left;">5,809,502</td> <td style="text-align: left;">43,094</td> </tr>-<tr class="even country">+<tr class="country"> <th style="text-align: center;">Finland</th> <td style="text-align: left;">Helsinki</td> <td style="text-align: left;">5,537,364</td> <td style="text-align: left;">338,145</td> </tr>-<tr class="odd country">+<tr class="country"> <th style="text-align: center;">Iceland</th> <td style="text-align: left;">Reykjavik</td> <td style="text-align: left;">343,518</td> <td style="text-align: left;">103,000</td> </tr>-<tr class="even country">+<tr class="country"> <th style="text-align: center;">Norway</th> <td style="text-align: left;">Oslo</td> <td style="text-align: left;">5,372,191</td> <td style="text-align: left;">323,802</td> </tr>-<tr class="odd country">+<tr class="country"> <th style="text-align: center;">Sweden</th> <td style="text-align: left;">Stockholm</td> <td style="text-align: left;">10,313,447</td> <td style="text-align: left;">450,295</td> </tr> </tbody><tfoot>-<tr id="summary" class="even">+<tr id="summary"> <td style="text-align: center;">Total</td> <td style="text-align: left;"></td> <td id="total-population" style="text-align: left;">27,376,022</td>
test/tables/nordics.latex view
@@ -1,8 +1,8 @@ \begin{longtable}[]{@{}-  >{\centering\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.3000}}-  >{\raggedright\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.3000}}-  >{\raggedright\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.2000}}-  >{\raggedright\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.2000}}@{}}+  >{\centering\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.3000}}+  >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.3000}}+  >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.2000}}+  >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.2000}}@{}} \caption[Nordic countries]{States belonging to the \emph{Nordics.}}\label{nordics}\tabularnewline \toprule\noalign{}
+ test/tables/nordics.markdown view
@@ -0,0 +1,18 @@++-----------------------+-----------------------+---------------+---------------++| Name                  | Capital               | Population\   | Area\         |+|                       |                       | (in 2018)     | (in km^2^)    |++:=====================:+:======================+:==============+:==============++| Denmark               | Copenhagen            | 5,809,502     | 43,094        |++-----------------------+-----------------------+---------------+---------------++| Finland               | Helsinki              | 5,537,364     | 338,145       |++-----------------------+-----------------------+---------------+---------------++| Iceland               | Reykjavik             | 343,518       | 103,000       |++-----------------------+-----------------------+---------------+---------------++| Norway                | Oslo                  | 5,372,191     | 323,802       |++-----------------------+-----------------------+---------------+---------------++| Sweden                | Stockholm             | 10,313,447    | 450,295       |++=======================+=======================+===============+===============++| Total                 |                       | 27,376,022    | 1,258,336     |++=======================+=======================+===============+===============+++: States belonging to the *Nordics.* {#nordics source="wikipedia"}
test/tables/nordics.mediawiki view
@@ -1,4 +1,4 @@-{| id="nordics" class="wikitable" source="wikipedia"+{| id="nordics" class="wikitable" data-source="wikipedia" |+ States belonging to the ''Nordics.'' |- ! style="text-align: center;"| Name
test/tables/nordics.typst view
@@ -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],
test/tables/planets.html4 view
@@ -1,7 +1,7 @@ <table> <caption><p>Data about the planets of our solar system.</p></caption> <thead>-<tr class="header">+<tr> <th colspan="2" align="center"></th> <th>Name</th> <th align="right">Mass (10^24kg)</th>@@ -16,7 +16,7 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <th colspan="2" rowspan="4" align="center">Terrestrial planets</th> <th>Mercury</th> <td align="right">0.330</td>@@ -29,7 +29,7 @@ <td align="right">0</td> <td>Closest to the Sun</td> </tr>-<tr class="even">+<tr> <th>Venus</th> <td align="right">4.87</td> <td align="right">12,104</td>@@ -41,7 +41,7 @@ <td align="right">0</td> <td></td> </tr>-<tr class="odd">+<tr> <th>Earth</th> <td align="right">5.97</td> <td align="right">12,756</td>@@ -53,7 +53,7 @@ <td align="right">1</td> <td>Our world</td> </tr>-<tr class="even">+<tr> <th>Mars</th> <td align="right">0.642</td> <td align="right">6,792</td>@@ -65,7 +65,7 @@ <td align="right">2</td> <td>The red planet</td> </tr>-<tr class="odd">+<tr> <th rowspan="4" align="center">Jovian planets</th> <th rowspan="2" align="center">Gas giants</th> <th>Jupiter</th>@@ -79,7 +79,7 @@ <td align="right">67</td> <td>The largest planet</td> </tr>-<tr class="even">+<tr> <th>Saturn</th> <td align="right">568</td> <td align="right">120,536</td>@@ -91,7 +91,7 @@ <td align="right">62</td> <td></td> </tr>-<tr class="odd">+<tr> <th rowspan="2" align="center">Ice giants</th> <th>Uranus</th> <td align="right">86.8</td>@@ -104,7 +104,7 @@ <td align="right">27</td> <td></td> </tr>-<tr class="even">+<tr> <th>Neptune</th> <td align="right">102</td> <td align="right">49,528</td>@@ -116,7 +116,7 @@ <td align="right">14</td> <td></td> </tr>-<tr class="odd">+<tr> <th colspan="2" align="center">Dwarf planets</th> <th>Pluto</th> <td align="right">0.0146</td>
test/tables/planets.html5 view
@@ -1,7 +1,7 @@ <table> <caption><p>Data about the planets of our solar system.</p></caption> <thead>-<tr class="header">+<tr> <th colspan="2" style="text-align: center;"></th> <th>Name</th> <th style="text-align: right;">Mass (10^24kg)</th>@@ -16,7 +16,7 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <th colspan="2" rowspan="4" style="text-align: center;">Terrestrial planets</th> <th>Mercury</th> <td style="text-align: right;">0.330</td>@@ -29,7 +29,7 @@ <td style="text-align: right;">0</td> <td>Closest to the Sun</td> </tr>-<tr class="even">+<tr> <th>Venus</th> <td style="text-align: right;">4.87</td> <td style="text-align: right;">12,104</td>@@ -41,7 +41,7 @@ <td style="text-align: right;">0</td> <td></td> </tr>-<tr class="odd">+<tr> <th>Earth</th> <td style="text-align: right;">5.97</td> <td style="text-align: right;">12,756</td>@@ -53,7 +53,7 @@ <td style="text-align: right;">1</td> <td>Our world</td> </tr>-<tr class="even">+<tr> <th>Mars</th> <td style="text-align: right;">0.642</td> <td style="text-align: right;">6,792</td>@@ -65,7 +65,7 @@ <td style="text-align: right;">2</td> <td>The red planet</td> </tr>-<tr class="odd">+<tr> <th rowspan="4" style="text-align: center;">Jovian planets</th> <th rowspan="2" style="text-align: center;">Gas giants</th> <th>Jupiter</th>@@ -79,7 +79,7 @@ <td style="text-align: right;">67</td> <td>The largest planet</td> </tr>-<tr class="even">+<tr> <th>Saturn</th> <td style="text-align: right;">568</td> <td style="text-align: right;">120,536</td>@@ -91,7 +91,7 @@ <td style="text-align: right;">62</td> <td></td> </tr>-<tr class="odd">+<tr> <th rowspan="2" style="text-align: center;">Ice giants</th> <th>Uranus</th> <td style="text-align: right;">86.8</td>@@ -104,7 +104,7 @@ <td style="text-align: right;">27</td> <td></td> </tr>-<tr class="even">+<tr> <th>Neptune</th> <td style="text-align: right;">102</td> <td style="text-align: right;">49,528</td>@@ -116,7 +116,7 @@ <td style="text-align: right;">14</td> <td></td> </tr>-<tr class="odd">+<tr> <th colspan="2" style="text-align: center;">Dwarf planets</th> <th>Pluto</th> <td style="text-align: right;">0.0146</td>
test/tables/planets.latex view
@@ -17,17 +17,18 @@ \bottomrule\noalign{} \endlastfoot \multicolumn{2}{@{}c}{%-\multirow{4}{=}{Terrestrial planets}} & Mercury & 0.330 & 4,879 & 5427 & 3.7 &-4222.6 & 57.9 & 167 & 0 & Closest to the Sun \\+\multirow{4}{*}{\centering\arraybackslash Terrestrial planets}} & Mercury &+0.330 & 4,879 & 5427 & 3.7 & 4222.6 & 57.9 & 167 & 0 & Closest to the Sun \\ & & Venus & 4.87 & 12,104 & 5243 & 8.9 & 2802.0 & 108.2 & 464 & 0 & \\ & & Earth & 5.97 & 12,756 & 5514 & 9.8 & 24.0 & 149.6 & 15 & 1 & Our world \\ & & Mars & 0.642 & 6,792 & 3933 & 3.7 & 24.7 & 227.9 & -65 & 2 & The red planet \\-\multirow{4}{=}{Jovian planets} & \multirow{2}{=}{Gas giants} & Jupiter & 1898 &-142,984 & 1326 & 23.1 & 9.9 & 778.6 & -110 & 67 & The largest planet \\+\multirow{4}{*}{\centering\arraybackslash Jovian planets} &+\multirow{2}{*}{\centering\arraybackslash Gas giants} & Jupiter & 1898 & 142,984+& 1326 & 23.1 & 9.9 & 778.6 & -110 & 67 & The largest planet \\ & & Saturn & 568 & 120,536 & 687 & 9.0 & 10.7 & 1433.5 & -140 & 62 & \\-& \multirow{2}{=}{Ice giants} & Uranus & 86.8 & 51,118 & 1271 & 8.7 & 17.2 &-2872.5 & -195 & 27 & \\+& \multirow{2}{*}{\centering\arraybackslash Ice giants} & Uranus & 86.8 & 51,118+& 1271 & 8.7 & 17.2 & 2872.5 & -195 & 27 & \\ & & Neptune & 102 & 49,528 & 1638 & 11.0 & 16.1 & 4495.1 & -200 & 14 & \\ \multicolumn{2}{@{}c}{% Dwarf planets} & Pluto & 0.0146 & 2,370 & 2095 & 0.7 & 153.3 & 5906.4 & -225 & 5
+ test/tables/planets.markdown view
@@ -0,0 +1,31 @@++------------------+---------+------------+----------+-----------+----------+---------+-----------+-------------+--------+--------------++|                  | Name    | Mass       | Diameter | Density   | Gravity  | Length  | Distance  | Mean        | Number | Notes        |+|                  |         | (10\^24kg) | (km)     | (kg/m\^3) | (m/s\^2) | of day  | from Sun  | temperature | of     |              |+|                  |         |            |          |           |          | (hours) | (10\^6km) | (C)         | moons  |              |++:=======:+:======:+=========+===========:+=========:+==========:+=========:+========:+==========:+============:+=======:+==============++| Terrestrial      | Mercury | 0.330      | 4,879    | 5427      | 3.7      | 4222.6  | 57.9      | 167         | 0      | Closest to   |+| planets          |         |            |          |           |          |         |           |             |        | the Sun      |+|                  +---------+------------+----------+-----------+----------+---------+-----------+-------------+--------+--------------++|                  | Venus   | 4.87       | 12,104   | 5243      | 8.9      | 2802.0  | 108.2     | 464         | 0      |              |+|                  +---------+------------+----------+-----------+----------+---------+-----------+-------------+--------+--------------++|                  | Earth   | 5.97       | 12,756   | 5514      | 9.8      | 24.0    | 149.6     | 15          | 1      | Our world    |+|                  +---------+------------+----------+-----------+----------+---------+-----------+-------------+--------+--------------++|                  | Mars    | 0.642      | 6,792    | 3933      | 3.7      | 24.7    | 227.9     | -65         | 2      | The red      |+|                  |         |            |          |           |          |         |           |             |        | planet       |++---------+--------+---------+------------+----------+-----------+----------+---------+-----------+-------------+--------+--------------++| Jovian  | Gas    | Jupiter | 1898       | 142,984  | 1326      | 23.1     | 9.9     | 778.6     | -110        | 67     | The largest  |+| planets | giants |         |            |          |           |          |         |           |             |        | planet       |+|         |        +---------+------------+----------+-----------+----------+---------+-----------+-------------+--------+--------------++|         |        | Saturn  | 568        | 120,536  | 687       | 9.0      | 10.7    | 1433.5    | -140        | 62     |              |+|         +--------+---------+------------+----------+-----------+----------+---------+-----------+-------------+--------+--------------++|         | Ice    | Uranus  | 86.8       | 51,118   | 1271      | 8.7      | 17.2    | 2872.5    | -195        | 27     |              |+|         | giants |         |            |          |           |          |         |           |             |        |              |+|         |        +---------+------------+----------+-----------+----------+---------+-----------+-------------+--------+--------------++|         |        | Neptune | 102        | 49,528   | 1638      | 11.0     | 16.1    | 4495.1    | -200        | 14     |              |++---------+--------+---------+------------+----------+-----------+----------+---------+-----------+-------------+--------+--------------++| Dwarf planets    | Pluto   | 0.0146     | 2,370    | 2095      | 0.7      | 153.3   | 5906.4    | -225        | 5      | Declassified |+|                  |         |            |          |           |          |         |           |             |        | as a planet  |+|                  |         |            |          |           |          |         |           |             |        | in 2006.     |++------------------+---------+------------+----------+-----------+----------+---------+-----------+-------------+--------+--------------+++: Data about the planets of our solar system.
test/tables/students.html4 view
@@ -5,49 +5,49 @@ <col width="50%" /> </colgroup> <thead>-<tr class="header">+<tr> <th align="center">Student ID</th> <th align="center">Name</th> </tr> </thead> <tbody class="souvereign-states">-<tr class="odd">+<tr> <th colspan="2" align="left">Computer Science</th> </tr> -<tr class="odd">+<tr> <td align="left">3741255</td> <td align="left">Jones, Martha</td> </tr>-<tr class="even">+<tr> <td align="left">4077830</td> <td align="left">Pierce, Benjamin</td> </tr>-<tr class="odd">+<tr> <td align="left">5151701</td> <td align="left">Kirk, James</td> </tr> </tbody> <tbody>-<tr class="odd">+<tr> <th colspan="2" align="left">Russian Literature</th> </tr> -<tr class="odd">+<tr> <td align="left">3971244</td> <td align="left">Nim, Victor</td> </tr> </tbody> <tbody>-<tr class="odd">+<tr> <th colspan="2" align="left">Astrophysics</th> </tr> -<tr class="odd">+<tr> <td align="left">4100332</td> <td align="left">Petrov, Alexandra</td> </tr>-<tr class="even">+<tr> <td align="left">4100332</td> <td align="left">Toyota, Hiroko</td> </tr>
test/tables/students.html5 view
@@ -5,49 +5,49 @@ <col style="width: 50%" /> </colgroup> <thead>-<tr class="header">+<tr> <th style="text-align: center;">Student ID</th> <th style="text-align: center;">Name</th> </tr> </thead> <tbody class="souvereign-states">-<tr class="odd">+<tr> <th colspan="2" style="text-align: left;">Computer Science</th> </tr> -<tr class="odd">+<tr> <td style="text-align: left;">3741255</td> <td style="text-align: left;">Jones, Martha</td> </tr>-<tr class="even">+<tr> <td style="text-align: left;">4077830</td> <td style="text-align: left;">Pierce, Benjamin</td> </tr>-<tr class="odd">+<tr> <td style="text-align: left;">5151701</td> <td style="text-align: left;">Kirk, James</td> </tr> </tbody> <tbody>-<tr class="odd">+<tr> <th colspan="2" style="text-align: left;">Russian Literature</th> </tr> -<tr class="odd">+<tr> <td style="text-align: left;">3971244</td> <td style="text-align: left;">Nim, Victor</td> </tr> </tbody> <tbody>-<tr class="odd">+<tr> <th colspan="2" style="text-align: left;">Astrophysics</th> </tr> -<tr class="odd">+<tr> <td style="text-align: left;">4100332</td> <td style="text-align: left;">Petrov, Alexandra</td> </tr>-<tr class="even">+<tr> <td style="text-align: left;">4100332</td> <td style="text-align: left;">Toyota, Hiroko</td> </tr>
test/tables/students.latex view
@@ -1,6 +1,6 @@ \begin{longtable}[]{@{}-  >{\raggedright\arraybackslash}p{(\columnwidth - 2\tabcolsep) * \real{0.5000}}-  >{\raggedright\arraybackslash}p{(\columnwidth - 2\tabcolsep) * \real{0.5000}}@{}}+  >{\raggedright\arraybackslash}p{(\linewidth - 2\tabcolsep) * \real{0.5000}}+  >{\raggedright\arraybackslash}p{(\linewidth - 2\tabcolsep) * \real{0.5000}}@{}} \caption{List of Students}\label{students}\tabularnewline \toprule\noalign{} \begin{minipage}[b]{\linewidth}\centering@@ -20,15 +20,15 @@ \endhead \bottomrule\noalign{} \endlastfoot-\multicolumn{2}{@{}>{\raggedright\arraybackslash}p{(\columnwidth - 2\tabcolsep) * \real{1.0000} + 2\tabcolsep}@{}}{%+\multicolumn{2}{@{}>{\raggedright\arraybackslash}p{(\linewidth - 2\tabcolsep) * \real{1.0000} + 2\tabcolsep}@{}}{% Computer Science} \\ 3741255 & Jones, Martha \\ 4077830 & Pierce, Benjamin \\ 5151701 & Kirk, James \\-\multicolumn{2}{@{}>{\raggedright\arraybackslash}p{(\columnwidth - 2\tabcolsep) * \real{1.0000} + 2\tabcolsep}@{}}{%+\multicolumn{2}{@{}>{\raggedright\arraybackslash}p{(\linewidth - 2\tabcolsep) * \real{1.0000} + 2\tabcolsep}@{}}{% Russian Literature} \\ 3971244 & Nim, Victor \\-\multicolumn{2}{@{}>{\raggedright\arraybackslash}p{(\columnwidth - 2\tabcolsep) * \real{1.0000} + 2\tabcolsep}@{}}{%+\multicolumn{2}{@{}>{\raggedright\arraybackslash}p{(\linewidth - 2\tabcolsep) * \real{1.0000} + 2\tabcolsep}@{}}{% Astrophysics} \\ 4100332 & Petrov, Alexandra \\ 4100332 & Toyota, Hiroko \\
+ test/tables/students.markdown view
@@ -0,0 +1,23 @@++-----------------------------------------+-----------------------------------------++| Student ID                              | Name                                    |++:========================================+:========================================++| Computer Science                                                                  |++-----------------------------------------+-----------------------------------------++| 3741255                                 | Jones, Martha                           |++-----------------------------------------+-----------------------------------------++| 4077830                                 | Pierce, Benjamin                        |++-----------------------------------------+-----------------------------------------++| 5151701                                 | Kirk, James                             |++-----------------------------------------+-----------------------------------------++| Russian Literature                                                                |++-----------------------------------------+-----------------------------------------++| 3971244                                 | Nim, Victor                             |++-----------------------------------------+-----------------------------------------++| Astrophysics                                                                      |++-----------------------------------------+-----------------------------------------++| 4100332                                 | Petrov, Alexandra                       |++-----------------------------------------+-----------------------------------------++| 4100332                                 | Toyota, Hiroko                          |++-----------------------------------------+-----------------------------------------+++: List of Students {#students source="mdn"}
test/tables/students.mediawiki view
@@ -1,4 +1,4 @@-{| id="students" class="wikitable" source="mdn"+{| id="students" class="wikitable" data-source="mdn" |+ List of Students |- ! style="text-align: center;"| Student ID
test/test-pandoc.hs view
@@ -1,6 +1,4 @@-{-# OPTIONS_GHC -Wall #-}--module Main where+module Main (main) where  import System.Environment (getArgs, getExecutablePath) import qualified Control.Exception as E@@ -14,6 +12,8 @@ import qualified Tests.Old import qualified Tests.Readers.Creole import qualified Tests.Readers.Docx+import qualified Tests.Readers.Pptx+import qualified Tests.Readers.Xlsx import qualified Tests.Readers.DokuWiki import qualified Tests.Readers.EPUB import qualified Tests.Readers.FB2@@ -29,6 +29,8 @@ import qualified Tests.Readers.RTF import qualified Tests.Readers.Txt2Tags import qualified Tests.Readers.Man+import qualified Tests.Readers.Mdoc+import qualified Tests.Readers.Pod import qualified Tests.Shared import qualified Tests.Writers.AsciiDoc import qualified Tests.Writers.ConTeXt@@ -50,6 +52,8 @@ import qualified Tests.Writers.AnnotatedTable import qualified Tests.Writers.TEI import qualified Tests.Writers.Markua+import qualified Tests.Writers.BBCode+import qualified Tests.XML import qualified Tests.MediaBag import Text.Pandoc.Shared (inDirectory) @@ -59,6 +63,7 @@         , testGroup "Old" (Tests.Old.tests pandocPath)         , testGroup "Shared" Tests.Shared.tests         , testGroup "MediaBag" Tests.MediaBag.tests+        , testGroup "XML" Tests.XML.tests         , testGroup "Writers"           [ testGroup "Native" Tests.Writers.Native.tests           , testGroup "ConTeXt" Tests.Writers.ConTeXt.tests@@ -80,6 +85,7 @@           , testGroup "PowerPoint" Tests.Writers.Powerpoint.tests           , testGroup "Ms" Tests.Writers.Ms.tests           , testGroup "AnnotatedTable" Tests.Writers.AnnotatedTable.tests+          , testGroup "BBCode" Tests.Writers.BBCode.tests           ]         , testGroup "Readers"           [ testGroup "LaTeX" Tests.Readers.LaTeX.tests@@ -91,14 +97,18 @@           , testGroup "RST" Tests.Readers.RST.tests           , testGroup "RTF" Tests.Readers.RTF.tests           , testGroup "Docx" Tests.Readers.Docx.tests+          , testGroup "Pptx" Tests.Readers.Pptx.tests+          , testGroup "Xlsx" Tests.Readers.Xlsx.tests           , testGroup "ODT" Tests.Readers.ODT.tests           , testGroup "Txt2Tags" Tests.Readers.Txt2Tags.tests           , testGroup "EPUB" Tests.Readers.EPUB.tests           , testGroup "Muse" Tests.Readers.Muse.tests           , testGroup "Creole" Tests.Readers.Creole.tests           , testGroup "Man" Tests.Readers.Man.tests+          , testGroup "Mdoc" Tests.Readers.Mdoc.tests           , testGroup "FB2" Tests.Readers.FB2.tests           , testGroup "DokuWiki" Tests.Readers.DokuWiki.tests+          , testGroup "Pod" Tests.Readers.Pod.tests           ]         ] 
test/twiki-reader.native view
@@ -149,6 +149,22 @@   , Para [ Str "Nother" , Space , Str "paragraph." ]   , Header       1+      ( "internal-links" , [] , [] )+      [ Str "internal" , Space , Str "links" ]+  , Para+      [ Link+          ( "" , [ "wikilink" ] , [] )+          [ Str "MySimplePage" ]+          ( "MySimplePage" , "" )+      ]+  , Para+      [ Link+          ( "" , [ "wikilink" ] , [] )+          [ Str "My23Page23" ]+          ( "My23Page23" , "" )+      ]+  , Header+      1       ( "external-links" , [] , [] )       [ Str "external" , Space , Str "links" ]   , Para
test/twiki-reader.twiki view
@@ -93,6 +93,12 @@ </blockquote> Nother paragraph. +---+ internal links++MySimplePage++My23Page23+ ---+ external links  [[http://google.com][<i>Google</i> search engine]]
test/typst-reader.native view
@@ -1,7 +1,6 @@ Pandoc   Meta { unMeta = fromList [] }-  [ Para []-  , Header+  [ Header       1       ( "" , [] , [] )       [ Str "Fibonacci" , Space , Str "sequence" ]@@ -46,7 +45,6 @@           DisplayMath           "F_{n} = \\left\\lfloor {\\frac{1}{\\sqrt{5}}\\phi^{n}} \\right\\rceil,\\quad\\phi = \\frac{1 + \\sqrt{5}}{2}"       ]-  , Para []   , Para       [ Str "The"       , Space@@ -189,34 +187,28 @@           ]           (TableFoot ( "" , [] , [] ) [])       ]-  , Para []-  , Para []-  , Para []-  , Para []-  , Para []-  , Para []   , Div       ( "" , [ "columns-flow" ] , [ ( "count" , "2" ) ] )       [ Para           [ Span               ( "" , [] , [ ( "align" , "center" ) ] )-              [ Underline-                  [ Link-                      ( "" , [] , [] )-                      [ Strong-                          [ Str "Typst"-                          , Space-                          , Str "Math"-                          , Space-                          , Str "for"-                          , Space-                          , Str "Undergrads"-                          ]+              [ Link+                  ( "" , [] , [] )+                  [ SoftBreak+                  , Strong+                      [ Str "Typst"+                      , Space+                      , Str "Math"+                      , Space+                      , Str "for"+                      , Space+                      , Str "Undergrads"                       ]-                      ( "https://github.com/johanvx/typst-undergradmath"-                      , ""-                      )+                  , SoftBreak                   ]+                  ( "https://github.com/johanvx/typst-undergradmath"+                  , ""+                  )               ]           ]       , Para@@ -265,16 +257,13 @@           , Str "at"           , Space           , Underline-              [ Underline-                  [ Link-                      ( "" , [] , [] )-                      [ Str-                          "https://gitlab.com/jim.hefferon/undergradmath"-                      ]-                      ( "https://gitlab.com/jim.hefferon/undergradmath"-                      , ""-                      )+              [ Link+                  ( "" , [] , [] )+                  [ Str "https://gitlab.com/jim.hefferon/undergradmath"                   ]+                  ( "https://gitlab.com/jim.hefferon/undergradmath"+                  , ""+                  )               ]           , Str "."           ]@@ -532,15 +521,14 @@                       AlignDefault                       (RowSpan 1)                       (ColSpan 1)-                      [ Para [] ]+                      []                   , Cell                       ( "" , [] , [] )                       AlignDefault                       (RowSpan 1)                       (ColSpan 1)                       [ CodeBlock-                          ( "" , [] , [] )-                          "-- document body here --\n  "+                          ( "" , [] , [] ) "-- document body here --"                       ]                   ]               ]@@ -1681,7 +1669,6 @@           , Code ( "" , [] , [] ) "overline(A)"           , Str ")."           ]-      , Para []       , DefinitionList           [ ( [ Str "Remark" ]             , [ [ Para@@ -1830,7 +1817,7 @@                           [ Para                               [ Span                                   ( "" , [ "box" ] , [] )-                                  [ Math InlineMath "f\\prime"+                                  [ Math InlineMath "f'"                                   , Str "\8192"                                   , Code ( "" , [] , [] ) "f'"                                   , Str ","@@ -3192,7 +3179,7 @@                           [ Para                               [ Span                                   ( "" , [ "box" ] , [] )-                                  [ Math InlineMath "\\preccurlyeq"+                                  [ Math InlineMath "\\preceq"                                   , Str "\8192"                                   , Code ( "" , [] , [] ) "prec.eq"                                   ]@@ -3208,7 +3195,7 @@                                   ( "" , [ "box" ] , [] )                                   [ Math InlineMath "\\ominus"                                   , Str "\8192"-                                  , Code ( "" , [] , [] ) "minus.cirle"+                                  , Code ( "" , [] , [] ) "minus.circle"                                   ]                               ]                           ]@@ -3220,7 +3207,7 @@                           [ Para                               [ Span                                   ( "" , [ "box" ] , [] )-                                  [ Math InlineMath "\\hslash"+                                  [ Math InlineMath "\295"                                   , Str "\8192"                                   , Code                                       ( "" , [] , [] ) "planck.reduce"@@ -3285,7 +3272,7 @@                           [ Para                               [ Span                                   ( "" , [ "box" ] , [] )-                                  [ Math InlineMath "\\succcurlyeq"+                                  [ Math InlineMath "\\succeq"                                   , Str "\8192"                                   , Code ( "" , [] , [] ) "succ.eq"                                   ]@@ -3622,12 +3609,14 @@                           [ Para                               [ Span                                   ( "" , [ "box" ] , [] )-                                  [ Math InlineMath "\\leftrightarrow"+                                  [ Math+                                      InlineMath "\\longleftrightarrow"                                   , Str "\8192"-                                  , Code ( "" , [] , [] ) "<->"+                                  , Code ( "" , [] , [] ) "<-->"                                   , Str ","                                   , Space-                                  , Code ( "" , [] , [] ) "arrow.l.r"+                                  , Code+                                      ( "" , [] , [] ) "arrow.l.r.long"                                   ]                               ]                           ]@@ -4142,7 +4131,7 @@                           (ColSpan 1)                           [ CodeBlock                               ( "" , [] , [] )-                              "lr([sum_(k = 0)^n e^(k^2)], size: #50%)\n  "+                              "lr([sum_(k = 0)^n e^(k^2)], size: #50%)"                           ]                       ]                   ]@@ -4209,7 +4198,7 @@                           (ColSpan 1)                           [ CodeBlock                               ( "" , [] , [] )-                              "lr(angle.l i, 2^(2^i) angle.r)\n  "+                              "lr(angle.l i, 2^(2^i) angle.r)"                           ]                       ]                   ]@@ -4284,8 +4273,7 @@                           AlignDefault                           (RowSpan 1)                           (ColSpan 1)-                          [ CodeBlock-                              ( "" , [] , [] ) "(1 / n^(alpha))\n  "+                          [ CodeBlock ( "" , [] , [] ) "(1 / n^(alpha))"                           ]                       ]                   , Row@@ -4307,7 +4295,7 @@                           (ColSpan 1)                           [ CodeBlock                               ( "" , [] , [] )-                              "paren.l 1 / n^(alpha) paren.r\n  "+                              "paren.l 1 / n^(alpha) paren.r"                           ]                       ]                   ]@@ -4372,7 +4360,7 @@                           (ColSpan 1)                           [ CodeBlock                               ( "" , [] , [] )-                              "lr(frac(dif f, dif x) |)_(x_0)\n  "+                              "lr(frac(dif f, dif x) |)_(x_0)"                           ]                       ]                   ]@@ -4441,7 +4429,7 @@                           (RowSpan 1)                           (ColSpan 1)                           [ CodeBlock-                              ( "" , [] , [] ) "$ mat(a, b; c, d) $\n  "+                              ( "" , [] , [] ) "$ mat(a, b; c, d) $"                           ]                       ]                   ]@@ -4454,14 +4442,12 @@           , Str "Typst,"           , Space           , Underline-              [ Underline-                  [ Link-                      ( "" , [] , [] )-                      [ Str "array" ]-                      ( "https://typst.app/docs/reference/typst/array"-                      , ""-                      )-                  ]+              [ Link+                  ( "" , [] , [] )+                  [ Str "array" ]+                  ( "https://typst.app/docs/reference/typst/array"+                  , ""+                  )               ]           , Space           , Str "is"@@ -4588,7 +4574,7 @@                           (ColSpan 1)                           [ CodeBlock                               ( "" , [] , [] )-                              "$ f_n = cases(\n    a &\"if\" n = 0,\n    r dot f_(n - 1) &\"else\"\n  ) $\n  "+                              "$ f_n = cases(\n  a &\"if\" n = 0,\n  r dot f_(n - 1) &\"else\"\n) $"                           ]                       ]                   ]@@ -4796,7 +4782,7 @@                           (RowSpan 1)                           (ColSpan 1)                           [ CodeBlock-                              ( "" , [] , [] ) "$ S = k dot lg W $\n  "+                              ( "" , [] , [] ) "$ S = k dot lg W $"                           ]                       ]                   ]@@ -4849,7 +4835,7 @@                           (ColSpan 1)                           [ CodeBlock                               ( "" , [] , [] )-                              "$ sin(x) = x - x^3 / 3! \\\n      + x^5 / 5! - dots.h.c $\n  "+                              "$ sin(x) = x - x^3 / 3! \\\n    + x^5 / 5! - dots.h.c $"                           ]                       ]                   ]@@ -4898,7 +4884,7 @@                           (ColSpan 1)                           [ CodeBlock                               ( "" , [] , [] )-                              "$ nabla dot bold(D) &= rho \\\n    nabla dot bold(B) &= 0 $\n  "+                              "$ nabla dot bold(D) &= rho \\\n  nabla dot bold(B) &= 0 $"                           ]                       ]                   ]@@ -4978,13 +4964,10 @@                           AlignDefault                           (RowSpan 1)                           (ColSpan 1)-                          [ Div-                              ( "" , [] , [] )-                              [ Para-                                  [ Math-                                      InlineMath-                                      "f:{\\mathbb{R}} \\rightarrow {\\mathbb{R}}"-                                  ]+                          [ Para+                              [ Math+                                  InlineMath+                                  "f:{\\mathbb{R}} \\rightarrow {\\mathbb{R}}"                               ]                           ]                       , Cell@@ -4992,8 +4975,7 @@                           AlignDefault                           (RowSpan 1)                           (ColSpan 1)-                          [ CodeBlock ( "" , [] , [] ) "f: RR -> RR\n  "-                          ]+                          [ CodeBlock ( "" , [] , [] ) "f: RR -> RR" ]                       ]                   , Row                       ( "" , [] , [] )@@ -5002,13 +4984,8 @@                           AlignDefault                           (RowSpan 1)                           (ColSpan 1)-                          [ Div-                              ( "" , [] , [] )-                              [ Para-                                  [ Math-                                      InlineMath-                                      "9.8\\ \\text{ m/s}^{2}"-                                  ]+                          [ Para+                              [ Math InlineMath "9.8\\ \\text{ m/s}^{2}"                               ]                           ]                       , Cell@@ -5016,18 +4993,14 @@                           AlignDefault                           (RowSpan 1)                           (ColSpan 1)-                          [ Div-                              ( "" , [] , [] )-                              [ Para-                                  [ Code-                                      ( "" , [] , [] )-                                      "\"9.8\" \"m/s\"^2"-                                  , Space-                                  , Link-                                      ( "" , [ "ref" ] , [] )-                                      [ Str "[tricky]" ]-                                      ( "#tricky" , "" )-                                  ]+                          [ Para+                              [ Code+                                  ( "" , [] , [] ) "\"9.8\" \"m/s\"^2"+                              , Space+                              , Link+                                  ( "" , [ "ref" ] , [] )+                                  [ Str "[tricky]" ]+                                  ( "#tricky" , "" )                               ]                           ]                       ]@@ -5051,7 +5024,7 @@                           (ColSpan 1)                           [ CodeBlock                               ( "" , [] , [] )-                              "lim_(h -> 0) (f(x + h) - f(x)) / h\n  "+                              "lim_(h -> 0) (f(x + h) - f(x)) / h"                           ]                       ]                   , Row@@ -5074,7 +5047,7 @@                           (ColSpan 1)                           [ CodeBlock                               ( "" , [] , [] )-                              "integral x^2 dif x = x^3 \\/ 3 + C\n  "+                              "integral x^2 dif x = x^3 \\/ 3 + C"                           ]                       ]                   , Row@@ -5097,7 +5070,7 @@                           (ColSpan 1)                           [ CodeBlock                               ( "" , [] , [] )-                              "nabla = bold(i) dif / (dif x) + bold(j) dif / (dif y) + bold(k) dif / (dif z)\n  "+                              "nabla = bold(i) dif / (dif x) + bold(j) dif / (dif y) + bold(k) dif / (dif z)"                           ]                       ]                   ]@@ -5236,13 +5209,10 @@                           AlignDefault                           (RowSpan 1)                           (ColSpan 1)-                          [ Div-                              ( "" , [] , [] )-                              [ Para-                                  [ Math-                                      InlineMath-                                      "\\sigma^{2} = \\sqrt{{\\sum(x_{i} - \\mu)}^{2}/N}"-                                  ]+                          [ Para+                              [ Math+                                  InlineMath+                                  "\\sigma^{2} = \\sqrt{{\\sum(x_{i} - \\mu)}^{2}/N}"                               ]                           ]                       , Cell@@ -5252,7 +5222,7 @@                           (ColSpan 1)                           [ CodeBlock                               ( "" , [] , [] )-                              "sigma^2 = sqrt(sum(x_i - mu)^2 \\/ N)\n  "+                              "sigma^2 = sqrt(sum(x_i - mu)^2 \\/ N)"                           ]                       ]                   , Row@@ -5262,13 +5232,10 @@                           AlignDefault                           (RowSpan 1)                           (ColSpan 1)-                          [ Div-                              ( "" , [] , [] )-                              [ Para-                                  [ Math-                                      InlineMath-                                      "E(X) = \\mu_{X} = \\sum(x_{i} - P\\left( x_{i} \\right))"-                                  ]+                          [ Para+                              [ Math+                                  InlineMath+                                  "E(X) = \\mu_{X} = \\sum(x_{i} - P\\left( x_{i} \\right))"                               ]                           ]                       , Cell@@ -5278,7 +5245,7 @@                           (ColSpan 1)                           [ CodeBlock                               ( "" , [] , [] )-                              "E(X) = mu_X = sum(x_i - P(x_i))\n  "+                              "E(X) = mu_X = sum(x_i - P(x_i))"                           ]                       ]                   ]@@ -5325,7 +5292,7 @@                       AlignDefault                       (RowSpan 1)                       (ColSpan 1)-                      [ Para [] ]+                      []                   , Cell                       ( "" , [] , [] )                       AlignDefault@@ -5333,7 +5300,7 @@                       (ColSpan 1)                       [ CodeBlock                           ( "" , [] , [] )-                          "1 / sqrt(2 sigma^2 pi)\n    e^(- (x - mu)^2 / (2 sigma^2))\n  "+                          "1 / sqrt(2 sigma^2 pi)\n  e^(- (x - mu)^2 / (2 sigma^2))"                       ]                   ]               ]@@ -5354,39 +5321,29 @@           , Str "at"           , Space           , Underline-              [ Underline-                  [ Link-                      ( "" , [] , [] )-                      [ Str "https://typst.app/docs" ]-                      ( "https://typst.app/docs" , "" )-                  ]+              [ Link+                  ( "" , [] , [] )+                  [ Str "https://typst.app/docs" ]+                  ( "https://typst.app/docs" , "" )               ]           , Str "."           ]-      , Para []-      , Div-          ( "" , [] , [] )-          [ HorizontalRule-          , Para-              [ Str "johanvx"-              , Space-              , Str "("-              , Underline-                  [ Underline-                      [ Underline-                          [ Link-                              ( "" , [] , [] )-                              [ Str "https://github.com/johanvx" ]-                              ( "https://github.com/johanvx" , "" )-                          ]-                      ]-                  ]-              , Str ")"-              , Space-              , Str "\8202\8193"-              , Space-              , Str "2023-05-22"+      , HorizontalRule+      , Para+          [ Str "johanvx"+          , Space+          , Str "("+          , Underline+              [ Link+                  ( "" , [] , [] )+                  [ Str "https://github.com/johanvx" ]+                  ( "https://github.com/johanvx" , "" )               ]+          , Str ")"+          , Space+          , Str "\8202\8193"+          , Space+          , Str "2023-05-22"           ]       ]   ]
test/undergradmath.typ view
@@ -259,7 +259,7 @@   cell($\u{224D}$, [`\u{224D}` @tricky]), cell($tilde.eq$, `tilde.eq`), cell($n!$, `n!`),   cell($equiv$, `equiv`), cell($tilde.not$, `tilde.not`), cell($diff$, `diff`),   cell($prec$, `prec`), cell($plus.circle$, `plus.circle`), cell($nabla$, `nabla`),-  cell($prec.eq$, `prec.eq`), cell($minus.circle$, `minus.cirle`), cell($planck.reduce$, `planck.reduce`),+  cell($prec.eq$, `prec.eq`), cell($minus.circle$, `minus.circle`), cell($planck.reduce$, `planck.reduce`),   cell($succ$, `succ`), cell($dot.circle$, `dot.circle`), cell($circle.stroked.tiny$, `circle.stroked.tiny`),   cell($succ.eq$, `succ.eq`), cell($times.circle$, `times.circle`), cell($star$, `star`),   cell($prop$, `prop`), cell($\u{2298}$, [`\u{2298}` @tricky]), cell($sqrt("")$, `sqrt("")`),@@ -276,7 +276,7 @@   cell($->$, [`->`, `arrow.r`]), cell($|->$, [`|->`, `arrow.r.bar`]),   cell($arrow.r.not$, `arrow.r.not`), cell($arrow.r.long.bar$, `arrow.r.long.bar`),   cell($arrow.r.long$, `arrow.r.long`), cell($<-$, [`<-`, `arrow.l`]),-  cell($=>$, [`=>`, `arrow.r.double`]), cell($<->$, [`<->`, `arrow.l.r`]),+  cell($=>$, [`=>`, `arrow.r.double`]), cell($<-->$, [`<-->`, `arrow.l.r.long`]),   cell($arrow.r.double.not$, `arrow.r.double.not`), cell($arrow.b$, `arrow.b`),   cell($arrow.r.double.long$, `arrow.r.double.long`), cell($arrow.t$, `arrow.t`),   cell($arrow.squiggly$, `arrow.squiggly`), cell($arrow.t.b$, `arrow.t.b`),
+ test/vimdoc/definition-lists.markdown view
@@ -0,0 +1,70 @@+---+vimdoc-prefix: pandoc+abstract: "A short description"+filename: "definition-lists.txt"+author: Author+title: Title+---++## Basic++Term 1+:   Definition I++Term 2+:   Definition II++Term 3+:   Definition III++## Code++<!-- Source: <https://github.com/ggandor/leap.nvim/blob/c4a215acef90749851d85ddba08bc282867b50eb/doc/leap.txt#L283-L294> -->++`leap.opts.keys.next_target`+: Jump to the next available target (use the previous search pattern if no input+  has been given). `:h leap-repeat`++`leap.opts.keys.prev_target`+: Jump to the previous target (revert `next_target`).++`leap.opts.keys.next_group`+: Shift to the next group of labeled targets.++`leap.opts.keys.prev_group`+: Shift to the previous group of labeled targets (revert `next_group`).++## Span++[Important concept]{#important-concept}+: Definition++[I am too long to fit on the same line as a reference, so reference is put above me!]{#i-am-too-long}+: Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod+  tempor incididunt ut labore et dolore magna aliqua.++## Commands++In markdown vim commands are represented as inline code starting with colon (ie.+`:MyCommand`), but writer strips the backticks++`:FnlCompileBuffer`{#:FnlCompileBuffer}++:   Compiles current active fennel buffer++`:FnlCompile[!]`{#:FnlCompile}++:   Diff compiles all indexed fennel files+    If bang! is present then forcefully compiles all `source` files++`:[range]Fnl {expr}`{#:Fnl}++:    Evaluates {expr} or range++     ```+     :'<,'>Fnl++     :Fnl (print "Hello World")++     :Fnl (values some_var)+     ```
+ test/vimdoc/definition-lists.vimdoc view
@@ -0,0 +1,71 @@+*definition-lists.txt*	A short description++                               Title by Author+++                                       Type |gO| to see the table of contents.++Basic ........................................................... |pandoc-basic|+Code ............................................................. |pandoc-code|+Span ............................................................. |pandoc-span|+Commands ..................................................... |pandoc-commands|++------------------------------------------------------------------------------+Basic                                                             *pandoc-basic*++Term 1+    Definition I+Term 2+    Definition II+Term 3+    Definition III++------------------------------------------------------------------------------+Code                                                               *pandoc-code*++`leap.opts.keys.next_target`+    Jump to the next available target (use the previous search pattern if no+    input has been given). |leap-repeat|+`leap.opts.keys.prev_target`+    Jump to the previous target (revert `next_target`).+`leap.opts.keys.next_group`+    Shift to the next group of labeled targets.+`leap.opts.keys.prev_group`+    Shift to the previous group of labeled targets (revert `next_group`).++------------------------------------------------------------------------------+Span                                                               *pandoc-span*++Important concept                                     *pandoc-important-concept*+    Definition+                                                          *pandoc-i-am-too-long*+I am too long to fit on the same line as a reference, so reference is put+above me!+    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod+    tempor incididunt ut labore et dolore magna aliqua.++------------------------------------------------------------------------------+Commands                                                       *pandoc-commands*++In markdown vim commands are represented as inline code starting with colon+(ie. `:MyCommand`), but writer strips the backticks++:FnlCompileBuffer                                            *:FnlCompileBuffer*+    Compiles current active fennel buffer++:FnlCompile[!]                                                     *:FnlCompile*+    Diff compiles all indexed fennel files If bang! is present then forcefully+    compiles all `source` files++:[range]Fnl {expr}                                                        *:Fnl*+    Evaluates {expr} or range++    >+        :'<,'>Fnl++        :Fnl (print "Hello World")++        :Fnl (values some_var)+<++ vim:tw=78:sw=4:ts=4:ft=help:norl:et:
+ test/vimdoc/headers-numbered.vimdoc view
@@ -0,0 +1,108 @@+                                       Type |gO| to see the table of contents.++1. unremarkable header 1 ............................... |unremarkable-header-1|+  1.1 unremarkable header 2 ............................ |unremarkable-header-2|+      1.1.1 unremarkable header 3 ...................... |unremarkable-header-3|+      1.1.2 unremarkable header 3 .................... |unremarkable-header-3-1|+  unremarkable header 2 .............................. |unremarkable-header-2-1|+    unremarkable header 3 ............................ |unremarkable-header-3-2|+    unremarkable header 3 ............................ |unremarkable-header-3-3|+2. bold italic underline strikethrough ............................... |short11|+  2.1 superscript2 subscript3 ........................................ |short21|+      2.1.1 smallcaps code inline math display math .................. |short31|+      2.1.2 link image ............................................... |short32|+3. Long header 1 long header 1 long header 1 long header 1 long heade... |long1|+  3.1 Long header 2 long header 2 long header 2 long header 2 long h... |long21|+      3.1.1 Long header 3 long header 3 long header 3 long header 3.... |long31|+      3.1.2 Long header 3 long header 3 long header 3 long header 3.... |long32|+  3.2 Long header 2 long header 2 long header 2 long header 2 long h... |long22|+      3.2.1 Long header 3 long header 3 long header 3 long header 3.... |long33|+      3.2.2 Long header 3 long header 3 long header 3 long header 3.... |long34|+4. ... |long-header-1-long-header-1-long-header-1-long-header-1-long-header-1-long-header-1-long-header-1|+  4.1 ... |long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2|+      4.1.1 ... |long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3|+      4.1.2 ... |long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-1|+  4.2 ... |long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-1|+      4.2.1 ... |long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-2|+      4.2.2 ... |long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-3|+++Headers with a short title and implicit ref. Last 3 headers are unnumbered.++==============================================================================+unremarkable header 1                                    *unremarkable-header-1*++------------------------------------------------------------------------------+unremarkable header 2                                    *unremarkable-header-2*++UNREMARKABLE HEADER 3                                    *unremarkable-header-3*++UNREMARKABLE HEADER 3                                  *unremarkable-header-3-1*++------------------------------------------------------------------------------+unremarkable header 2                                  *unremarkable-header-2-1*++UNREMARKABLE HEADER 3                                  *unremarkable-header-3-2*++UNREMARKABLE HEADER 3                                  *unremarkable-header-3-3*++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++Headers with various inline elements++==============================================================================+bold italic underline strikethrough                                    *short11*++------------------------------------------------------------------------------+superscript2 subscript3                                                *short21*++SMALLCAPS `code` `$inline math$` `$display math$`                      *short31*++LINK example.com                                                       *short32*++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++Headers with a long name and explicit short ref++==============================================================================+Long header 1 long header 1 long header 1 long header 1 long header 1 long header 1 long header 1 *long1*++------------------------------------------------------------------------------+Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 *long21*++LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long31*++LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long32*++------------------------------------------------------------------------------+Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 *long22*++LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long33*++LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long34*++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++Headers with a long name and implicit ref.++Since implicit ref is very lengthy, there is no way to fit it. Therefore title+is not rendered and the references exceed the columns (textwidth) limit++==============================================================================+Long header 1 long header 1 long header 1 long header 1 long header 1 long header 1 long header 1 *long-header-1-long-header-1-long-header-1-long-header-1-long-header-1-long-header-1-long-header-1*++------------------------------------------------------------------------------+Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 *long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2*++LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3*++LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-1*++------------------------------------------------------------------------------+Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 *long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-1*++LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-2*++LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-3*++ vim:tw=78:sw=4:ts=4:ft=help:norl:et:
+ test/vimdoc/headers.markdown view
@@ -0,0 +1,45 @@+Headers with a short title and implicit ref. Last 3 headers are unnumbered.++# unremarkable header 1+## unremarkable header 2+### unremarkable header 3+### unremarkable header 3+## unremarkable header 2 {.unnumbered}+### unremarkable header 3 {.unnumbered}+### unremarkable header 3 {.unnumbered}++---++Headers with various inline elements++# **bold** *italic* [underline]{.underline} ~strikethrough~ {#short11}+## superscript^2^ subscript~3~ {#short21}+### [smallcaps]{.smallcaps} `code` $inline math$ $$display math$$ {#short31}+### [link](example.com) ![image](https://duckduckgo.com/favicon.ico) {#short32}++---++Headers with a long name and explicit short ref++# Long header 1 long header 1 long header 1 long header 1 long header 1 long header 1 long header 1 {#long1}+## Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 {#long21}+### Long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 {#long31}+### Long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 {#long32}+## Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 {#long22}+### Long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 {#long33}+### Long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 {#long34}++---++Headers with a long name and implicit ref.++Since implicit ref is very lengthy, there is no way to fit it. Therefore title+is not rendered and the references exceed the columns (textwidth) limit++# Long header 1 long header 1 long header 1 long header 1 long header 1 long header 1 long header 1+## Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2+### Long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 long header 3+### Long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 long header 3+## Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2+### Long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 long header 3+### Long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 long header 3
+ test/vimdoc/headers.vimdoc view
@@ -0,0 +1,94 @@+                                       Type |gO| to see the table of contents.++unremarkable header 1 .................................. |unremarkable-header-1|+  unremarkable header 2 ................................ |unremarkable-header-2|+  unremarkable header 2 .............................. |unremarkable-header-2-1|+bold italic underline strikethrough .................................. |short11|+  superscript2 subscript3 ............................................ |short21|+Long header 1 long header 1 long header 1 long header 1 long header 1... |long1|+  Long header 2 long header 2 long header 2 long header 2 long heade... |long21|+  Long header 2 long header 2 long header 2 long header 2 long heade... |long22|+... |long-header-1-long-header-1-long-header-1-long-header-1-long-header-1-long-header-1-long-header-1|+  ... |long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2|+  ... |long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-1|+++Headers with a short title and implicit ref. Last 3 headers are unnumbered.++==============================================================================+unremarkable header 1                                    *unremarkable-header-1*++------------------------------------------------------------------------------+unremarkable header 2                                    *unremarkable-header-2*++UNREMARKABLE HEADER 3                                    *unremarkable-header-3*++UNREMARKABLE HEADER 3                                  *unremarkable-header-3-1*++------------------------------------------------------------------------------+unremarkable header 2                                  *unremarkable-header-2-1*++UNREMARKABLE HEADER 3                                  *unremarkable-header-3-2*++UNREMARKABLE HEADER 3                                  *unremarkable-header-3-3*++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++Headers with various inline elements++==============================================================================+bold italic underline strikethrough                                    *short11*++------------------------------------------------------------------------------+superscript2 subscript3                                                *short21*++SMALLCAPS `code` `$inline math$` `$display math$`                      *short31*++LINK example.com                                                       *short32*++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++Headers with a long name and explicit short ref++==============================================================================+Long header 1 long header 1 long header 1 long header 1 long header 1 long header 1 long header 1 *long1*++------------------------------------------------------------------------------+Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 *long21*++LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long31*++LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long32*++------------------------------------------------------------------------------+Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 *long22*++LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long33*++LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long34*++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++Headers with a long name and implicit ref.++Since implicit ref is very lengthy, there is no way to fit it. Therefore title+is not rendered and the references exceed the columns (textwidth) limit++==============================================================================+Long header 1 long header 1 long header 1 long header 1 long header 1 long header 1 long header 1 *long-header-1-long-header-1-long-header-1-long-header-1-long-header-1-long-header-1-long-header-1*++------------------------------------------------------------------------------+Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 *long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2*++LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3*++LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-1*++------------------------------------------------------------------------------+Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 *long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-1*++LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-2*++LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-3*++ vim:tw=78:sw=4:ts=4:ft=help:norl:et:
+ test/vimdoc/vim-online-doc.markdown view
@@ -0,0 +1,42 @@+# Online vim documentation++While vim documentation can be accessed with `:help`, it may be beneficial to+link to the websites inside readme/markdown docs. Two most common websites are:++- <https://vimhelp.org/> and+- <https://neovim.io/doc/user>++Also it is not uncommon to reference documentation as `:h <topic>`++## Links to vimhelp.org {#vimhelp-links}++For introduction to writing help files see+<https://vimhelp.org/helphelp.txt.html#help-writing>++Named link: [vimhelp link](https://vimhelp.org/helphelp.txt.html#help-writing)++## Links to neo.vimhelp.org {#neo-vimhelp-links}++For introduction to writing help files see+<https://neo.vimhelp.org/helphelp.txt.html#help-writing>++Named link: [vimhelp link](https://neo.vimhelp.org/helphelp.txt.html#help-writing)++## Links to neovim.io {#neovim-io-links}++For introduction to writing help files see+<https://neovim.io/doc/user/helphelp.html#help-writing>++Named link: [neovim.io link](https://neovim.io/doc/user/helphelp.html#help-writing)++You can also reference whole files with topic omitted:+<https://neovim.io/doc/user/vim_diff.html>++## :h-style documentation {#colon-h-docs}++For introduction to writing help files see+`:h help-writing`++Long name for `:help` is also supported: `:help help-writing`++This is malformed: `:help help-writing `, but this is not: `:help  help-writing`
+ test/vimdoc/vim-online-doc.vimdoc view
@@ -0,0 +1,53 @@+                                       Type |gO| to see the table of contents.++Online vim documentation ............................ |online-vim-documentation|+  Links to vimhelp.org ......................................... |vimhelp-links|+  Links to neo.vimhelp.org ................................. |neo-vimhelp-links|+  Links to neovim.io ......................................... |neovim-io-links|+  :h-style documentation ........................................ |colon-h-docs|++==============================================================================+Online vim documentation                              *online-vim-documentation*++While vim documentation can be accessed with `:help`, it may be beneficial to+link to the websites inside readme/markdown docs. Two most common websites+are:++- https://vimhelp.org/ and+- https://neovim.io/doc/user++Also it is not uncommon to reference documentation as |<topic>|++------------------------------------------------------------------------------+Links to vimhelp.org                                             *vimhelp-links*++For introduction to writing help files see |help-writing|++Named link: vimhelp link |help-writing|++------------------------------------------------------------------------------+Links to neo.vimhelp.org                                     *neo-vimhelp-links*++For introduction to writing help files see |help-writing|++Named link: vimhelp link |help-writing|++------------------------------------------------------------------------------+Links to neovim.io                                             *neovim-io-links*++For introduction to writing help files see |help-writing|++Named link: neovim.io link |help-writing|++You can also reference whole files with topic omitted: |vim_diff.txt|++------------------------------------------------------------------------------+:h-style documentation                                            *colon-h-docs*++For introduction to writing help files see |help-writing|++Long name for `:help` is also supported: |help-writing|++This is malformed: |help-writing|, but this is not: |help-writing|++ vim:tw=78:sw=4:ts=4:ft=help:norl:et:
test/vimwiki-reader.native view
@@ -559,13 +559,13 @@       [ Str "internal" , Space , Str "links" ]   , Para       [ Link-          ( "" , [] , [] )+          ( "" , [ "wikilink" ] , [] )           [ Str "This is a link" ]-          ( "This is a link" , "wikilink" )+          ( "This is a link" , "" )       ]   , Para       [ Link-          ( "" , [] , [] )+          ( "" , [ "wikilink" ] , [] )           [ Str "Description"           , Space           , Str "of"@@ -574,27 +574,27 @@           , Space           , Str "link"           ]-          ( "This is a link source" , "wikilink" )+          ( "This is a link source" , "" )       ]   , Para       [ Link-          ( "" , [] , [] )+          ( "" , [ "wikilink" ] , [] )           [ Str "projects/Important Project 1" ]-          ( "projects/Important Project 1" , "wikilink" )+          ( "projects/Important Project 1" , "" )       , SoftBreak       , Link-          ( "" , [] , [] )+          ( "" , [ "wikilink" ] , [] )           [ Str "../index" ]-          ( "../index" , "wikilink" )+          ( "../index" , "" )       , SoftBreak       , Link-          ( "" , [] , [] )+          ( "" , [ "wikilink" ] , [] )           [ Str "Other" , Space , Str "files" ]-          ( "a subdirectory/" , "wikilink" )+          ( "a subdirectory/" , "" )       ]   , Para       [ Link-          ( "" , [] , [] )+          ( "" , [ "wikilink" ] , [] )           [ Str "try"           , Space           , Str "me"@@ -607,11 +607,11 @@           , Space           , Str "anchors"           ]-          ( "#tag-one" , "wikilink" )+          ( "#tag-one" , "" )       ]   , Para       [ Link-          ( "" , [] , [] )+          ( "" , [ "wikilink" ] , [] )           [ Str "try"           , Space           , Str "me"@@ -624,11 +624,11 @@           , Space           , Str "anchors"           ]-          ( "#block quotes" , "wikilink" )+          ( "#block quotes" , "" )       ]   , Para       [ Link-          ( "" , [] , [] )+          ( "" , [ "wikilink" ] , [] )           [ Str "try"           , Space           , Str "me"@@ -641,19 +641,19 @@           , Space           , Str "anchors"           ]-          ( "#strong" , "wikilink" )+          ( "#strong" , "" )       ]   , Para       [ Link-          ( "" , [] , [] )+          ( "" , [ "wikilink" ] , [] )           [ Str "Tasks" , Space , Str "for" , Space , Str "tomorrow" ]-          ( "Todo List#Tomorrow" , "wikilink" )+          ( "Todo List#Tomorrow" , "" )       ]   , Para       [ Link-          ( "" , [] , [] )+          ( "" , [ "wikilink" ] , [] )           [ Str "diary:2017-05-01" ]-          ( "diary/2017-05-01" , "wikilink" )+          ( "diary/2017-05-01" , "" )       ]   , Para       [ Link
test/writer.asciidoc view
@@ -40,7 +40,7 @@ Because a hard-wrapped line in the middle of a paragraph looked like a list item. -Here’s one with a bullet. * criminey.+Here’s one with a bullet. ++*++ criminey.  There should be a hard line break + here.@@ -84,7 +84,7 @@ -- ____ -This should not be a block quote: 2 > 1.+This should not be a block quote: 2 ++>++ 1.  And a following paragraph. @@ -424,7 +424,7 @@  So is *_this_* word. -This is code: `+>+`, `+$+`, `+\+`, `+\$+`, `+<html>+`.+This is code: `++>++`, `$`, `++\++`, `++\++$`, `++<++html++>++`.  [line-through]#This is _strikeout_.# @@ -447,7 +447,7 @@  '`He said, "`I want to go.`"`' Were you alive in the 70’s? -Here is some quoted '``+code+``' and a "`http://example.com/?foo=1&bar=2[quoted+Here is some quoted '``code``' and a "`http://example.com/?foo=1&bar=2[quoted link]`".  Some dashes: one—two — three—four — five.@@ -477,11 +477,11 @@  These shouldn’t be math: -* To get the famous equation, write `+$e = mc^2$+`.+* To get the famous equation, write `$e = mc^2$`. * $22,000 is a _lot_ of money. So is $34,000. (It worked if "`lot`" is emphasized.) * Shoes ($20) and socks ($5).-* Escaped `+$+`: $73 _this should be emphasized_ 23$.+* Escaped `$`: $73 _this should be emphasized_ 23$.  Here’s a LaTeX table: @@ -503,39 +503,39 @@  This & that. -4 < 5.+4 ++<++ 5. -6 > 5.+6 ++>++ 5. -Backslash: \+Backslash: ++\++ -Backtick: `+Backtick: ++`++ -Asterisk: *+Asterisk: ++*++ -Underscore: _+Underscore: ++_++ -Left brace: \{+Left brace: ++{++  Right brace: } -Left bracket: [+Left bracket: ++[++ -Right bracket: ]+Right bracket: ++]++  Left paren: (  Right paren: ) -Greater-than: >+Greater-than: ++>++ -Hash: #+Hash: ++#++  Period: .  Bang: ! -Plus: ++Plus: {plus}  Minus: - @@ -557,7 +557,7 @@  link:/url/[URL and title] -link:/url/with_underscore[with_underscore]+link:/url/with_underscore[with++_++underscore]  mailto:nobody@nowhere.net[Email link] @@ -567,7 +567,7 @@  Foo link:/url/[bar]. -With link:/url/[embedded [brackets]].+With link:/url/[embedded ++[++brackets++]++].  link:/url/[b] by itself should be a link. @@ -577,7 +577,7 @@  Indented link:/url[thrice]. -This should [not][] be a link.+This should ++[++not++][]++ be a link.  .... [not]: /url@@ -611,7 +611,7 @@ Blockquoted: http://example.com/ ____ -Auto-links should not occur here: `+<http://example.com/>+`+Auto-links should not occur here: `++<++http://example.com/++>++`  .... or here: <http://example.com/>@@ -635,10 +635,10 @@ Here is a footnote reference,footnote:[Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document.] and another.[multiblock footnote omitted] This should _not_ be a footnote-reference, because it contains a space.[^my note] Here is an inline+reference, because it contains a space.++[++^my note++]++ Here is an inline note.footnote:[This is _easier_ to type. Inline notes may contain-http://google.com[links] and `+]+` verbatim characters, as well as [bracketed-text].]+http://google.com[links] and `++]++` verbatim characters, as well as+++[++bracketed text++]++.]  ____ Notes can go in quotes.footnote:[In quote.]
test/writer.asciidoc_legacy view
@@ -39,7 +39,7 @@ Because a hard-wrapped line in the middle of a paragraph looked like a list item. -Here’s one with a bullet. * criminey.+Here’s one with a bullet. ++*++ criminey.  There should be a hard line break + here.@@ -83,7 +83,7 @@ -- ____ -This should not be a block quote: 2 > 1.+This should not be a block quote: 2 ++>++ 1.  And a following paragraph. @@ -502,39 +502,39 @@  This & that. -4 < 5.+4 ++<++ 5. -6 > 5.+6 ++>++ 5. -Backslash: \+Backslash: ++\++ -Backtick: `+Backtick: ++`++ -Asterisk: *+Asterisk: ++*++ -Underscore: _+Underscore: ++_++ -Left brace: \{+Left brace: ++{++  Right brace: } -Left bracket: [+Left bracket: ++[++ -Right bracket: ]+Right bracket: ++]++  Left paren: (  Right paren: ) -Greater-than: >+Greater-than: ++>++ -Hash: #+Hash: ++#++  Period: .  Bang: ! -Plus: ++Plus: {plus}  Minus: - @@ -556,7 +556,7 @@  link:/url/[URL and title] -link:/url/with_underscore[with_underscore]+link:/url/with_underscore[with++_++underscore]  mailto:nobody@nowhere.net[Email link] @@ -566,7 +566,7 @@  Foo link:/url/[bar]. -With link:/url/[embedded [brackets]].+With link:/url/[embedded ++[++brackets++]++].  link:/url/[b] by itself should be a link. @@ -576,7 +576,7 @@  Indented link:/url[thrice]. -This should [not][] be a link.+This should ++[++not++][]++ be a link.  .... [not]: /url@@ -634,10 +634,10 @@ Here is a footnote reference,footnote:[Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document.] and another.[multiblock footnote omitted] This should _not_ be a footnote-reference, because it contains a space.[^my note] Here is an inline+reference, because it contains a space.++[++^my note++]++ Here is an inline note.footnote:[This is _easier_ to type. Inline notes may contain-http://google.com[links] and `]` verbatim characters, as well as [bracketed-text].]+http://google.com[links] and `]` verbatim characters, as well as ++[++bracketed+text++]++.]  ____ Notes can go in quotes.footnote:[In quote.]
+ test/writer.bbcode view
@@ -0,0 +1,729 @@+This is a set of tests for pandoc. Most of them are adapted from John Gruber's markdown test suite.++* * *++[u][b]Headers[/b][/u]++[b]Level 2 with an [url=/url]embedded link[/url][/b]++[u]Level 3 with [i]emphasis[/i][/u]++Level 4++Level 5++[u][b]Level 1[/b][/u]++[b]Level 2 with [i]emphasis[/i][/b]++[u]Level 3[/u]++with no blank line++[b]Level 2[/b]++with no blank line++* * *++[u][b]Paragraphs[/b][/u]++Here's a regular paragraph.++In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item. Because a hard-wrapped line in the middle of a paragraph looked like a list item.++Here's one with a bullet. * criminey.++There should be a hard line break+here.++* * *++[u][b]Block Quotes[/b][/u]++E-mail style:++[quote]+This is a block quote. It is pretty short.+[/quote]++[quote]+Code in a block quote:++[code]sub status {+    print "working";+}+[/code]++A list:++[list=1]+[*]item one+[*]item two+[/list]++Nested block quotes:++[quote]+nested+[/quote]++[quote]+nested+[/quote]+[/quote]++This should not be a block quote: 2 > 1.++And a following paragraph.++* * *++[u][b]Code Blocks[/b][/u]++Code:++[code]---- (should be four hyphens)++sub status {+    print "working";+}++this code block is indented by one tab+[/code]++And:++[code]    this code block is indented by two tabs++These should not be escaped:  \$ \\ \> \[ \{+[/code]++* * *++[u][b]Lists[/b][/u]++[b]Unordered[/b]++Asterisks tight:++[list]+[*]asterisk 1+[*]asterisk 2+[*]asterisk 3+[/list]++Asterisks loose:++[list]+[*]asterisk 1+[*]asterisk 2+[*]asterisk 3+[/list]++Pluses tight:++[list]+[*]Plus 1+[*]Plus 2+[*]Plus 3+[/list]++Pluses loose:++[list]+[*]Plus 1+[*]Plus 2+[*]Plus 3+[/list]++Minuses tight:++[list]+[*]Minus 1+[*]Minus 2+[*]Minus 3+[/list]++Minuses loose:++[list]+[*]Minus 1+[*]Minus 2+[*]Minus 3+[/list]++[b]Ordered[/b]++Tight:++[list=1]+[*]First+[*]Second+[*]Third+[/list]++and:++[list=1]+[*]One+[*]Two+[*]Three+[/list]++Loose using tabs:++[list=1]+[*]First+[*]Second+[*]Third+[/list]++and using spaces:++[list=1]+[*]One+[*]Two+[*]Three+[/list]++Multiple paragraphs:++[list=1]+[*]Item 1, graf one.++Item 1. graf two. The quick brown fox jumped over the lazy dog's back.+[*]Item 2.+[*]Item 3.+[/list]++[b]Nested[/b]++[list]+[*]Tab++[list]+[*]Tab++[list]+[*]Tab+[/list]+[/list]+[/list]++Here's another:++[list=1]+[*]First+[*]Second:++[list]+[*]Fee+[*]Fie+[*]Foe+[/list]+[*]Third+[/list]++Same thing but with paragraphs:++[list=1]+[*]First+[*]Second:++[list]+[*]Fee+[*]Fie+[*]Foe+[/list]+[*]Third+[/list]++[b]Tabs and spaces[/b]++[list]+[*]this is a list item indented with tabs+[*]this is a list item indented with spaces++[list]+[*]this is an example list item indented with tabs+[*]this is an example list item indented with spaces+[/list]+[/list]++[b]Fancy list markers[/b]++[list=1]+[*]begins with 2+[*]and now 3++with a continuation++[list=i]+[*]sublist with roman numerals, starting with 4+[*]more items++[list=A]+[*]a subsublist+[*]a subsublist+[/list]+[/list]+[/list]++Nesting:++[list=A]+[*]Upper Alpha++[list=I]+[*]Upper Roman.++[list=1]+[*]Decimal start with 6++[list=a]+[*]Lower alpha with paren+[/list]+[/list]+[/list]+[/list]++Autonumbering:++[list=1]+[*]Autonumber.+[*]More.++[list=1]+[*]Nested.+[/list]+[/list]++Should not be a list item:++M.A. 2007++B. Williams++* * *++[u][b]Definition Lists[/b][/u]++Tight using spaces:++apple+[list]+[*]red fruit+[/list]+orange+[list]+[*]orange fruit+[/list]+banana+[list]+[*]yellow fruit+[/list]++Tight using tabs:++apple+[list]+[*]red fruit+[/list]+orange+[list]+[*]orange fruit+[/list]+banana+[list]+[*]yellow fruit+[/list]++Loose:++apple+[list]+[*]red fruit+[/list]+orange+[list]+[*]orange fruit+[/list]+banana+[list]+[*]yellow fruit+[/list]++Multiple blocks with italics:++[i]apple[/i]+[list]+[*]red fruit++contains seeds, crisp, pleasant to taste+[/list]+[i]orange[/i]+[list]+[*]orange fruit++[code]{ orange code block }+[/code]++[quote]+orange block quote+[/quote]+[/list]++Multiple definitions, tight:++apple+[list]+[*]red fruit+[*]computer+[/list]+orange+[list]+[*]orange fruit+[*]bank+[/list]++Multiple definitions, loose:++apple+[list]+[*]red fruit+[*]computer+[/list]+orange+[list]+[*]orange fruit+[*]bank+[/list]++Blank line after term, indented marker, alternate markers:++apple+[list]+[*]red fruit+[*]computer+[/list]+orange+[list]+[*]orange fruit++[list=1]+[*]sublist+[*]sublist+[/list]+[/list]++[u][b]HTML Blocks[/b][/u]++Simple block on one line:++foo++And nested without indentation:++foo++bar++Interpreted markdown in a table:++This is [i]emphasized[/i]++And this is [b]strong[/b]++Here's a simple block:++foo++This should be a code block, though:++[code]<div>+    foo+</div>+[/code]++As should this:++[code]<div>foo</div>+[/code]++Now, nested:++foo++This should just be an HTML comment:++Multiline:++Code block:++[code]<!-- Comment -->+[/code]++Just plain comment, with trailing spaces on the line:++Code:++[code]<hr />+[/code]++Hr's:++* * *++[u][b]Inline Markup[/b][/u]++This is [i]emphasized[/i], and so [i]is this[/i].++This is [b]strong[/b], and so [b]is this[/b].++An [i][url=/url]emphasized link[/url][/i].++[b][i]This is strong and em.[/i][/b]++So is [b][i]this[/i][/b] word.++[b][i]This is strong and em.[/i][/b]++So is [b][i]this[/i][/b] word.++This is code: >, $, \, \$, <html>.++[s]This is [i]strikeout[/i].[/s]++Superscripts: abcd a[i]hello[/i] ahello there.++Subscripts: H2O, H23O, Hmany of themO.++These should not be superscripts or subscripts, because of the unescaped spaces: a^b c^d, a~b c~d.++* * *++[u][b]Smart quotes, ellipses, dashes[/b][/u]++"Hello," said the spider. "'Shelob' is my name."++'A', 'B', and 'C' are letters.++'Oak,' 'elm,' and 'beech' are names of trees. So is 'pine.'++'He said, "I want to go."' Were you alive in the 70's?++Here is some quoted 'code' and a "[url=http://example.com/?foo=1&bar=2]quoted link[/url]".++Some dashes: one---two --- three---four --- five.++Dashes between numbers: 5--7, 255--66, 1987--1999.++Ellipses...and...and....++* * *++[u][b]LaTeX[/b][/u]++[list]+[*]+[*]$2+2=4$+[*]$x \in y$+[*]$\alpha \wedge \omega$+[*]$223$+[*]$p$-Tree+[*]Here's some display math: [code=latex]$$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$+[/code]+[*]Here's one that has a line break in it: $\alpha + \omega \times x^2$.+[/list]++These shouldn't be math:++[list]+[*]To get the famous equation, write $e = mc^2$.+[*]$22,000 is a [i]lot[/i] of money. So is $34,000. (It worked if "lot" is emphasized.)+[*]Shoes ($20) and socks ($5).+[*]Escaped $: $73 [i]this should be emphasized[/i] 23$.+[/list]++Here's a LaTeX table:++* * *++[u][b]Special Characters[/b][/u]++Here is some unicode:++[list]+[*]I hat: Î+[*]o umlaut: ö+[*]section: §+[*]set membership: ∈+[*]copyright: ©+[/list]++AT&T has an ampersand in their name.++AT&T is another way to write it.++This & that.++4 < 5.++6 > 5.++Backslash: \++Backtick: `++Asterisk: *++Underscore: _++Left brace: {++Right brace: }++Left bracket: [++Right bracket: ]++Left paren: (++Right paren: )++Greater-than: >++Hash: #++Period: .++Bang: !++Plus: +++Minus: -++* * *++[u][b]Links[/b][/u]++[b]Explicit[/b]++Just a [url=/url/]URL[/url].++[url=/url/]URL and title[/url].++[url=/url/]URL and title[/url].++[url=/url/]URL and title[/url].++[url=/url/]URL and title[/url]++[url=/url/]URL and title[/url]++[url=/url/with_underscore]with_underscore[/url]++[email=nobody@nowhere.net]Email link[/email]++[url]Empty[/url].++[b]Reference[/b]++Foo [url=/url/]bar[/url].++With [url=/url/]embedded [brackets][/url].++[url=/url/]b[/url] by itself should be a link.++Indented [url=/url]once[/url].++Indented [url=/url]twice[/url].++Indented [url=/url]thrice[/url].++This should [not][] be a link.++[code][not]: /url+[/code]++Foo [url=/url/]bar[/url].++Foo [url=/url/]biz[/url].++[b]With ampersands[/b]++Here's a [url=http://example.com/?foo=1&bar=2]link with an ampersand in the URL[/url].++Here's a link with an amersand in the link text: [url=http://att.com/]AT&T[/url].++Here's an [url=/script?foo=1&bar=2]inline link[/url].++Here's an [url=/script?foo=1&bar=2]inline link in pointy braces[/url].++[b]Autolinks[/b]++With an ampersand: [url]http://example.com/?foo=1&bar=2[/url]++[list]+[*]In a list?+[*][url]http://example.com/[/url]+[*]It should.+[/list]++An e-mail address: [email]nobody@nowhere.net[/email]++[quote]+Blockquoted: [url]http://example.com/[/url]+[/quote]++Auto-links should not occur here: <http://example.com/>++[code]or here: <http://example.com/>+[/code]++* * *++[u][b]Images[/b][/u]++From "Voyage dans la Lune" by Georges Melies (1902):++[img alt="lalune" title="Voyage dans la Lune"]lalune.jpg[/img]+lalune++Here is a movie [img alt="movie"]movie.jpg[/img] icon.++* * *++[u][b]Footnotes[/b][/u]++Here is a footnote reference,(1) and another.(2) This should [i]not[/i] be a footnote reference, because it contains a space.[^my note] Here is an inline note.(3)++[quote]+Notes can go in quotes.(4)+[/quote]++[list=1]+[*]And in list items.(5)+[/list]++This paragraph should not be part of the note, as it is not indented.++* * *++(1) Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document.++(2) Here's the long note. This one contains multiple blocks.++Subsequent blocks are indented to show that they belong to the footnote (as with list items).++[code]  { <code> }+[/code]++If you want, you can indent every line, but you can also be lazy and just indent the first line of each block.++(3) This is [i]easier[/i] to type. Inline notes may contain [url=http://google.com]links[/url] and ] verbatim characters, as well as [bracketed text].++(4) In quote.++(5) In list.
test/writer.context view
@@ -13,7 +13,6 @@ \setupinteractionscreen[option={bookmark,title}]  \setuppagenumbering[location={footer,middle}]-\setupbackend[export=yes] \setupstructure[state=start,method=auto]  % use microtypography
test/writer.djot view
@@ -533,7 +533,7 @@ {#latex} # LaTeX -- +- - $`2+2=4` - $`x \in y` - $`\alpha \wedge \omega`
test/writer.docbook4 view
@@ -512,8 +512,8 @@     </sect2>     <sect2 id="fancy-list-markers">       <title>Fancy list markers</title>-      <orderedlist numeration="arabic">-        <listitem override="2">+      <orderedlist numeration="arabic" startingnumber="2">+        <listitem>           <para>             begins with 2           </para>@@ -525,8 +525,8 @@           <para>             with a continuation           </para>-          <orderedlist numeration="lowerroman" spacing="compact">-            <listitem override="4">+          <orderedlist numeration="lowerroman" spacing="compact" startingnumber="4">+            <listitem>               <para>                 sublist with roman numerals, starting with 4               </para>@@ -564,13 +564,13 @@               <para>                 Upper Roman.               </para>-              <orderedlist numeration="arabic" spacing="compact">-                <listitem override="6">+              <orderedlist numeration="arabic" spacing="compact" startingnumber="6">+                <listitem>                   <para>                     Decimal start with 6                   </para>-                  <orderedlist numeration="loweralpha" spacing="compact">-                    <listitem override="3">+                  <orderedlist numeration="loweralpha" spacing="compact" startingnumber="3">+                    <listitem>                       <para>                         Lower alpha with paren                       </para>
test/writer.docbook5 view
@@ -514,8 +514,8 @@     </section>     <section xml:id="fancy-list-markers">       <title>Fancy list markers</title>-      <orderedlist numeration="arabic">-        <listitem override="2">+      <orderedlist numeration="arabic" startingnumber="2">+        <listitem>           <para>             begins with 2           </para>@@ -527,8 +527,8 @@           <para>             with a continuation           </para>-          <orderedlist numeration="lowerroman" spacing="compact">-            <listitem override="4">+          <orderedlist numeration="lowerroman" spacing="compact" startingnumber="4">+            <listitem>               <para>                 sublist with roman numerals, starting with 4               </para>@@ -566,13 +566,13 @@               <para>                 Upper Roman.               </para>-              <orderedlist numeration="arabic" spacing="compact">-                <listitem override="6">+              <orderedlist numeration="arabic" spacing="compact" startingnumber="6">+                <listitem>                   <para>                     Decimal start with 6                   </para>-                  <orderedlist numeration="loweralpha" spacing="compact">-                    <listitem override="3">+                  <orderedlist numeration="loweralpha" spacing="compact" startingnumber="3">+                    <listitem>                       <para>                         Lower alpha with paren                       </para>
test/writer.dokuwiki view
@@ -48,26 +48,25 @@  > This is a block quote. It is pretty short. -<HTML><blockquote>-Code in a block quote:+> Code in a block quote: -<code>+> <code> sub status {     print "working"; } </code> -A list:+> A list: -  - item one-  - item two+>   - item one+>   - item two -Nested block quotes:+> Nested block quotes: -> nested+>> nested -> nested-</blockquote></HTML>+>> nested+ This should not be a block quote: 2 > 1.  And a following paragraph.@@ -168,11 +167,12 @@  Multiple paragraphs: -<HTML><ol style="list-style-type: decimal;"></HTML>-<HTML><li></HTML><HTML><p></HTML>Item 1, graf one.<HTML></p></HTML>-<HTML><p></HTML>Item 1. graf two. The quick brown fox jumped over the lazy dog’s back.<HTML></p></HTML><HTML></li></HTML>-<HTML><li></HTML><HTML><p></HTML>Item 2.<HTML></p></HTML><HTML></li></HTML>-<HTML><li></HTML><HTML><p></HTML>Item 3.<HTML></p></HTML><HTML></li></HTML><HTML></ol></HTML>+  - <WRAP>+Item 1, graf one.+Item 1. graf two. The quick brown fox jumped over the lazy dog’s back.+</WRAP>+  - Item 2.+  - Item 3.  ===== Nested ===== @@ -207,32 +207,28 @@  ===== Fancy list markers ===== -<HTML><ol start="2" style="list-style-type: decimal;"></HTML>-<HTML><li></HTML><HTML><p></HTML>begins with 2<HTML></p></HTML><HTML></li></HTML>-<HTML><li></HTML><HTML><p></HTML>and now 3<HTML></p></HTML>-<HTML><p></HTML>with a continuation<HTML></p></HTML>-<HTML><ol start="4" style="list-style-type: lower-roman;"></HTML>-<HTML><li></HTML>sublist with roman numerals, starting with 4<HTML></li></HTML>-<HTML><li></HTML>more items-<HTML><ol style="list-style-type: upper-alpha;"></HTML>-<HTML><li></HTML>a subsublist<HTML></li></HTML>-<HTML><li></HTML>a subsublist<HTML></li></HTML><HTML></ol></HTML>-<HTML></li></HTML><HTML></ol></HTML>-<HTML></li></HTML><HTML></ol></HTML>+  - begins with 2+  - <WRAP>+and now 3+with a continuation+    - sublist with roman numerals, starting with 4+    - more items+      - a subsublist+      - a subsublist+</WRAP>  Nesting: -<HTML><ol style="list-style-type: upper-alpha;"></HTML>-<HTML><li></HTML>Upper Alpha-<HTML><ol style="list-style-type: upper-roman;"></HTML>-<HTML><li></HTML>Upper Roman.-<HTML><ol start="6" style="list-style-type: decimal;"></HTML>-<HTML><li></HTML>Decimal start with 6-<HTML><ol start="3" style="list-style-type: lower-alpha;"></HTML>-<HTML><li></HTML>Lower alpha with paren<HTML></li></HTML><HTML></ol></HTML>-<HTML></li></HTML><HTML></ol></HTML>-<HTML></li></HTML><HTML></ol></HTML>-<HTML></li></HTML><HTML></ol></HTML>+  - <WRAP>+Upper Alpha+    - <WRAP>+Upper Roman.+      - <WRAP>+Decimal start with 6+        - Lower alpha with paren+</WRAP>+</WRAP>+</WRAP>  Autonumbering: @@ -271,32 +267,32 @@  Multiple blocks with italics: -<HTML><dl></HTML>-<HTML><dt></HTML>//apple//<HTML></dt></HTML>-<HTML><dd></HTML><HTML><p></HTML>red fruit<HTML></p></HTML>-<HTML><p></HTML>contains seeds, crisp, pleasant to taste<HTML></p></HTML><HTML></dd></HTML>-<HTML><dt></HTML>//orange//<HTML></dt></HTML>-<HTML><dd></HTML><HTML><p></HTML>orange fruit<HTML></p></HTML>+  * **//apple//** <WRAP>+red fruit+contains seeds, crisp, pleasant to taste+</WRAP>+  * **//orange//** <WRAP>+orange fruit <code> { orange code block } </code> -> <HTML><p></HTML>orange block quote<HTML></p></HTML>-<HTML></dd></HTML><HTML></dl></HTML>+> orange block quote+</WRAP>  Multiple definitions, tight: -  * **apple** red fruitcomputer-  * **orange** orange fruitbank+  * **apple** red fruit; computer+  * **orange** orange fruit; bank  Multiple definitions, loose: -  * **apple** red fruitcomputer-  * **orange** orange fruitbank+  * **apple** red fruit; computer+  * **orange** orange fruit; bank  Blank line after term, indented marker, alternate markers: -  * **apple** red fruitcomputer+  * **apple** red fruit; computer   * **orange** orange fruit     - sublist     - sublist@@ -318,23 +314,11 @@  Interpreted markdown in a table: -<HTML>-<table>-<tr>-<td>-</HTML>+ This is //emphasized//-<HTML>-</td>-<td>-</HTML>+ And this is **strong**-<HTML>-</td>-</tr>-</table>-<script type="text/javascript">document.write('This *should not* be interpreted as markdown');</script>-</HTML>+ Here’s a simple block:  foo@@ -362,20 +346,10 @@  This should just be an HTML comment: -<HTML>-<!-- Comment -->-</HTML>+ Multiline: -<HTML>-<!---Blah-Blah--->-<!---    This is another comment.--->-</HTML>+ Code block:  <code>@@ -384,9 +358,7 @@  Just plain comment, with trailing spaces on the line: -<HTML>-<!-- foo -->-</HTML>+ Code:  <code>@@ -395,18 +367,8 @@  Hr’s: -<HTML>-<hr>-<hr />-<hr />-<hr>-<hr />-<hr />-<hr class="foo" id="bar" />-<hr class="foo" id="bar" />-<hr class="foo" id="bar">-</HTML> + ----  ====== Inline Markup ======@@ -644,7 +606,7 @@ ))  > Notes can go in quotes.((In quote.-> ))+))    - And in list items.((In list.)) 
test/writer.html4 view
@@ -3,12 +3,15 @@ <head>   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />   <meta http-equiv="Content-Style-Type" content="text/css" />-  <meta name="generator" content="pandoc" />+  <meta name="generator" content="pandoc " />   <meta name="author" content="John MacFarlane" />   <meta name="author" content="Anonymous" />   <meta name="date" content="2006-07-17" />   <title>Pandoc Test Suite</title>   <style type="text/css">+    /* Default styles provided by pandoc.+    ** See https://pandoc.org/MANUAL.html#variables-for-html for config info.+    */     html {       color: #1a1a1a;       background-color: #fdfdfd;@@ -91,6 +94,7 @@       color: #606060;     }     code {+      white-space: pre-wrap;       font-family: Menlo, Monaco, Consolas, 'Lucida Console', monospace;       font-size: 85%;       margin: 0;@@ -110,8 +114,8 @@      overflow: visible;     }     hr {-      background-color: #1a1a1a;       border: none;+      border-top: 1px solid #1a1a1a;       height: 1px;       margin: 1em 0;     }@@ -154,10 +158,13 @@     #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;}+    div.columns{display: flex; gap: 1.5em;}+    div.column{flex: auto;}+    @media screen {+    div.columns{gap: min(4vw, 1.5em);}+    div.column{overflow-x: auto;}+    }     div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}     /* The extra [class] is a hack that increases specificity enough to        override a similar rule in reveal.js */
test/writer.html5 view
@@ -1,14 +1,17 @@ <!DOCTYPE html>-<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">+<html xmlns="http://www.w3.org/1999/xhtml"> <head>   <meta charset="utf-8" />-  <meta name="generator" content="pandoc" />+  <meta name="generator" content="pandoc " />   <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />   <meta name="author" content="John MacFarlane" />   <meta name="author" content="Anonymous" />   <meta name="dcterms.date" content="2006-07-17" />   <title>Pandoc Test Suite</title>   <style>+    /* Default styles provided by pandoc.+    ** See https://pandoc.org/MANUAL.html#variables-for-html for config info.+    */     html {       color: #1a1a1a;       background-color: #fdfdfd;@@ -91,6 +94,7 @@       color: #606060;     }     code {+      white-space: pre-wrap;       font-family: Menlo, Monaco, Consolas, 'Lucida Console', monospace;       font-size: 85%;       margin: 0;@@ -110,8 +114,8 @@      overflow: visible;     }     hr {-      background-color: #1a1a1a;       border: none;+      border-top: 1px solid #1a1a1a;       height: 1px;       margin: 1em 0;     }@@ -154,10 +158,13 @@     #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;}+    div.columns{display: flex; gap: 1.5em;}+    div.column{flex: auto;}+    @media screen {+    div.columns{gap: min(4vw, 1.5em);}+    div.column{overflow-x: auto;}+    }     div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}     /* The extra [class] is a hack that increases specificity enough to        override a similar rule in reveal.js */
test/writer.jats_archiving view
@@ -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>@@ -687,7 +669,7 @@     <list-item>       <p>Here’s some display math: <disp-formula><alternatives>       <tex-math><![CDATA[\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}]]></tex-math>-      <mml:math display="block" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mfrac><mml:mi>d</mml:mi><mml:mrow><mml:mi>d</mml:mi><mml:mi>x</mml:mi></mml:mrow></mml:mfrac><mml:mi>f</mml:mi><mml:mrow><mml:mo stretchy="true" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="true" form="postfix">)</mml:mo></mml:mrow><mml:mo>=</mml:mo><mml:munder><mml:mo>lim</mml:mo><mml:mrow><mml:mi>h</mml:mi><mml:mo>→</mml:mo><mml:mn>0</mml:mn></mml:mrow></mml:munder><mml:mfrac><mml:mrow><mml:mi>f</mml:mi><mml:mrow><mml:mo stretchy="true" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo>+</mml:mo><mml:mi>h</mml:mi><mml:mo stretchy="true" form="postfix">)</mml:mo></mml:mrow><mml:mo>−</mml:mo><mml:mi>f</mml:mi><mml:mrow><mml:mo stretchy="true" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="true" form="postfix">)</mml:mo></mml:mrow></mml:mrow><mml:mi>h</mml:mi></mml:mfrac></mml:mrow></mml:math></alternatives></disp-formula></p>+      <mml:math display="block" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mfrac><mml:mi>d</mml:mi><mml:mrow><mml:mi>d</mml:mi><mml:mi>x</mml:mi></mml:mrow></mml:mfrac><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo><mml:mo>=</mml:mo><mml:munder><mml:mi mathvariant="normal">lim</mml:mi><mml:mrow><mml:mi>h</mml:mi><mml:mo>→</mml:mo><mml:mn>0</mml:mn></mml:mrow></mml:munder><mml:mfrac><mml:mrow><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo>+</mml:mo><mml:mi>h</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo><mml:mo>−</mml:mo><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo></mml:mrow><mml:mi>h</mml:mi></mml:mfrac></mml:mrow></mml:math></alternatives></disp-formula></p>     </list-item>     <list-item>       <p>Here’s one that has a line break in it: <inline-formula><alternatives>
test/writer.jats_articleauthoring view
@@ -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>@@ -673,7 +655,7 @@     </list-item>     <list-item>       <p>Here’s some display math:-      <disp-formula><mml:math display="block" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mfrac><mml:mi>d</mml:mi><mml:mrow><mml:mi>d</mml:mi><mml:mi>x</mml:mi></mml:mrow></mml:mfrac><mml:mi>f</mml:mi><mml:mrow><mml:mo stretchy="true" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="true" form="postfix">)</mml:mo></mml:mrow><mml:mo>=</mml:mo><mml:munder><mml:mo>lim</mml:mo><mml:mrow><mml:mi>h</mml:mi><mml:mo>→</mml:mo><mml:mn>0</mml:mn></mml:mrow></mml:munder><mml:mfrac><mml:mrow><mml:mi>f</mml:mi><mml:mrow><mml:mo stretchy="true" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo>+</mml:mo><mml:mi>h</mml:mi><mml:mo stretchy="true" form="postfix">)</mml:mo></mml:mrow><mml:mo>−</mml:mo><mml:mi>f</mml:mi><mml:mrow><mml:mo stretchy="true" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="true" form="postfix">)</mml:mo></mml:mrow></mml:mrow><mml:mi>h</mml:mi></mml:mfrac></mml:mrow></mml:math></disp-formula></p>+      <disp-formula><mml:math display="block" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mfrac><mml:mi>d</mml:mi><mml:mrow><mml:mi>d</mml:mi><mml:mi>x</mml:mi></mml:mrow></mml:mfrac><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo><mml:mo>=</mml:mo><mml:munder><mml:mi mathvariant="normal">lim</mml:mi><mml:mrow><mml:mi>h</mml:mi><mml:mo>→</mml:mo><mml:mn>0</mml:mn></mml:mrow></mml:munder><mml:mfrac><mml:mrow><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo>+</mml:mo><mml:mi>h</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo><mml:mo>−</mml:mo><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo></mml:mrow><mml:mi>h</mml:mi></mml:mfrac></mml:mrow></mml:math></disp-formula></p>     </list-item>     <list-item>       <p>Here’s one that has a line break in it:
test/writer.jats_publishing view
@@ -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>@@ -687,7 +669,7 @@     <list-item>       <p>Here’s some display math: <disp-formula><alternatives>       <tex-math><![CDATA[\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}]]></tex-math>-      <mml:math display="block" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mfrac><mml:mi>d</mml:mi><mml:mrow><mml:mi>d</mml:mi><mml:mi>x</mml:mi></mml:mrow></mml:mfrac><mml:mi>f</mml:mi><mml:mrow><mml:mo stretchy="true" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="true" form="postfix">)</mml:mo></mml:mrow><mml:mo>=</mml:mo><mml:munder><mml:mo>lim</mml:mo><mml:mrow><mml:mi>h</mml:mi><mml:mo>→</mml:mo><mml:mn>0</mml:mn></mml:mrow></mml:munder><mml:mfrac><mml:mrow><mml:mi>f</mml:mi><mml:mrow><mml:mo stretchy="true" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo>+</mml:mo><mml:mi>h</mml:mi><mml:mo stretchy="true" form="postfix">)</mml:mo></mml:mrow><mml:mo>−</mml:mo><mml:mi>f</mml:mi><mml:mrow><mml:mo stretchy="true" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="true" form="postfix">)</mml:mo></mml:mrow></mml:mrow><mml:mi>h</mml:mi></mml:mfrac></mml:mrow></mml:math></alternatives></disp-formula></p>+      <mml:math display="block" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mfrac><mml:mi>d</mml:mi><mml:mrow><mml:mi>d</mml:mi><mml:mi>x</mml:mi></mml:mrow></mml:mfrac><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo><mml:mo>=</mml:mo><mml:munder><mml:mi mathvariant="normal">lim</mml:mi><mml:mrow><mml:mi>h</mml:mi><mml:mo>→</mml:mo><mml:mn>0</mml:mn></mml:mrow></mml:munder><mml:mfrac><mml:mrow><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo>+</mml:mo><mml:mi>h</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo><mml:mo>−</mml:mo><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo></mml:mrow><mml:mi>h</mml:mi></mml:mfrac></mml:mrow></mml:math></alternatives></disp-formula></p>     </list-item>     <list-item>       <p>Here’s one that has a line break in it: <inline-formula><alternatives>
test/writer.latex view
@@ -1,10 +1,11 @@ % Options for packages loaded elsewhere \PassOptionsToPackage{unicode}{hyperref} \PassOptionsToPackage{hyphens}{url}-% \documentclass[ ]{article}+\usepackage{xcolor} \usepackage{amsmath,amssymb}+\setcounter{secnumdepth}{-\maxdimen} % remove section numbering \usepackage{iftex} \ifPDFTeX   \usepackage[T1]{fontenc}@@ -36,18 +37,19 @@   \KOMAoptions{parskip=half}} \makeatother \usepackage{fancyvrb}-\usepackage{xcolor} \usepackage{graphicx} \makeatletter-\def\maxwidth{\ifdim\Gin@nat@width>\linewidth\linewidth\else\Gin@nat@width\fi}-\def\maxheight{\ifdim\Gin@nat@height>\textheight\textheight\else\Gin@nat@height\fi}-\makeatother-% Scale images if necessary, so that they will not overflow the page-% margins by default, and it is still possible to overwrite the defaults-% using explicit options in \includegraphics[width, height, ...]{}-\setkeys{Gin}{width=\maxwidth,height=\maxheight,keepaspectratio}+\newsavebox\pandoc@box+\newcommand*\pandocbounded[1]{% scales image to fit in text height/width+  \sbox\pandoc@box{#1}%+  \Gscale@div\@tempa{\textheight}{\dimexpr\ht\pandoc@box+\dp\pandoc@box\relax}%+  \Gscale@div\@tempb{\linewidth}{\wd\pandoc@box}%+  \ifdim\@tempb\p@<\@tempa\p@\let\@tempa\@tempb\fi% select the smaller of both+  \ifdim\@tempa\p@<\p@\scalebox{\@tempa}{\usebox\pandoc@box}%+  \else\usebox{\pandoc@box}%+  \fi%+} % Set default figure placement to htbp-\makeatletter \def\fps@figure{htbp} \makeatother \ifLuaTeX@@ -59,14 +61,14 @@ \setlength{\emergencystretch}{3em} % prevent overfull lines \providecommand{\tightlist}{%   \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}-\setcounter{secnumdepth}{-\maxdimen} % remove section numbering-\ifLuaTeX-  \usepackage{selnolig}  % disable illegal ligatures-\fi \usepackage{bookmark} \IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available \urlstyle{same} \VerbatimFootnotes % allow verbatim text in footnotes+% fallback for those not using the hyperref driver hyperxmp:+\makeatletter+\@ifundefined{xmpquote}{\newcommand{\xmpquote}[1]{#1}}{}+\makeatother \hypersetup{   pdftitle={Pandoc Test Suite},   pdfauthor={John MacFarlane; Anonymous},@@ -925,11 +927,12 @@  \begin{figure} \centering-\includegraphics{lalune.jpg}+\pandocbounded{\includegraphics[keepaspectratio,alt={lalune}]{lalune.jpg}} \caption{lalune} \end{figure} -Here is a movie \includegraphics{movie.jpg} icon.+Here is a movie+\pandocbounded{\includegraphics[keepaspectratio,alt={movie}]{movie.jpg}} icon.  \begin{center}\rule{0.5\linewidth}{0.5pt}\end{center} 
test/writer.man view
@@ -1,7 +1,7 @@-.TH "Pandoc Test Suite" "" "July 17, 2006" "" ""+.TH "Pandoc Test Suite" "" "July 17, 2006" "" .PP This is a set of tests for pandoc.-Most of them are adapted from John Gruber\[cq]s markdown test suite.+Most of them are adapted from John Gruber\(cqs markdown test suite. .PP    *   *   *   *   * .SH Headers@@ -18,7 +18,7 @@ .PP    *   *   *   *   * .SH Paragraphs-Here\[cq]s a regular paragraph.+Here\(cqs a regular paragraph. .PP In Markdown 1.0.0 and earlier. Version 8.@@ -26,7 +26,7 @@ Because a hard\-wrapped line in the middle of a paragraph looked like a list item. .PP-Here\[cq]s one with a bullet.+Here\(cqs one with a bullet. * criminey. .PP There should be a hard line break@@ -49,7 +49,7 @@ .IP .EX sub status {-    print \[dq]working\[dq];+    print \(dqworking\(dq; } .EE .PP@@ -82,7 +82,7 @@ \-\-\-\- (should be four hyphens)  sub status {-    print \[dq]working\[dq];+    print \(dqworking\(dq; }  this code block is indented by one tab@@ -93,58 +93,58 @@ .EX     this code block is indented by two tabs -These should not be escaped:  \[rs]$ \[rs]\[rs] \[rs]> \[rs][ \[rs]{+These should not be escaped:  \(rs$ \(rs\(rs \(rs> \(rs[ \(rs{ .EE .PP    *   *   *   *   * .SH Lists .SS Unordered Asterisks tight:-.IP \[bu] 2+.IP \(bu 2 asterisk 1-.IP \[bu] 2+.IP \(bu 2 asterisk 2-.IP \[bu] 2+.IP \(bu 2 asterisk 3 .PP Asterisks loose:-.IP \[bu] 2+.IP \(bu 2 asterisk 1-.IP \[bu] 2+.IP \(bu 2 asterisk 2-.IP \[bu] 2+.IP \(bu 2 asterisk 3 .PP Pluses tight:-.IP \[bu] 2+.IP \(bu 2 Plus 1-.IP \[bu] 2+.IP \(bu 2 Plus 2-.IP \[bu] 2+.IP \(bu 2 Plus 3 .PP Pluses loose:-.IP \[bu] 2+.IP \(bu 2 Plus 1-.IP \[bu] 2+.IP \(bu 2 Plus 2-.IP \[bu] 2+.IP \(bu 2 Plus 3 .PP Minuses tight:-.IP \[bu] 2+.IP \(bu 2 Minus 1-.IP \[bu] 2+.IP \(bu 2 Minus 2-.IP \[bu] 2+.IP \(bu 2 Minus 3 .PP Minuses loose:-.IP \[bu] 2+.IP \(bu 2 Minus 1-.IP \[bu] 2+.IP \(bu 2 Minus 2-.IP \[bu] 2+.IP \(bu 2 Minus 3 .SS Ordered Tight:@@ -186,35 +186,35 @@ .PP Item 1. graf two.-The quick brown fox jumped over the lazy dog\[cq]s back.+The quick brown fox jumped over the lazy dog\(cqs back. .RE .IP "2." 3 Item 2. .IP "3." 3 Item 3. .SS Nested-.IP \[bu] 2+.IP \(bu 2 Tab .RS 2-.IP \[bu] 2+.IP \(bu 2 Tab .RS 2-.IP \[bu] 2+.IP \(bu 2 Tab .RE .RE .PP-Here\[cq]s another:+Here\(cqs another: .IP "1." 3 First .IP "2." 3 Second: .RS 4-.IP \[bu] 2+.IP \(bu 2 Fee-.IP \[bu] 2+.IP \(bu 2 Fie-.IP \[bu] 2+.IP \(bu 2 Foe .RE .IP "3." 3@@ -226,24 +226,24 @@ .IP "2." 3 Second: .RS 4-.IP \[bu] 2+.IP \(bu 2 Fee-.IP \[bu] 2+.IP \(bu 2 Fie-.IP \[bu] 2+.IP \(bu 2 Foe .RE .IP "3." 3 Third .SS Tabs and spaces-.IP \[bu] 2+.IP \(bu 2 this is a list item indented with tabs-.IP \[bu] 2+.IP \(bu 2 this is a list item indented with spaces .RS 2-.IP \[bu] 2+.IP \(bu 2 this is an example list item indented with tabs-.IP \[bu] 2+.IP \(bu 2 this is an example list item indented with spaces .RE .SS Fancy list markers@@ -359,27 +359,40 @@ .TP apple red fruit+.RS computer+.RE .TP orange orange fruit+.RS bank+.RE .PP Multiple definitions, loose: .TP apple red fruit+.RS+.PP computer+.RE .TP orange orange fruit+.RS+.PP bank+.RE .PP Blank line after term, indented marker, alternate markers: .TP apple red fruit+.RS+.PP computer+.RE .TP orange orange fruit@@ -402,7 +415,7 @@ This is \f[I]emphasized\f[R] And this is \f[B]strong\f[R] .PP-Here\[cq]s a simple block:+Here\(cqs a simple block: .PP foo .PP@@ -441,7 +454,7 @@ <hr /> .EE .PP-Hr\[cq]s:+Hr\(cqs: .PP    *   *   *   *   * .SH Inline Markup@@ -459,7 +472,7 @@ .PP So is \f[B]\f[BI]this\f[B]\f[R] word. .PP-This is code: \f[CR]>\f[R], \f[CR]$\f[R], \f[CR]\[rs]\f[R], \f[CR]\[rs]$\f[R],+This is code: \f[CR]>\f[R], \f[CR]$\f[R], \f[CR]\(rs\f[R], \f[CR]\(rs$\f[R], \f[CR]<html>\f[R]. .PP [STRIKEOUT:This is \f[I]strikeout\f[R].]@@ -469,80 +482,80 @@ Subscripts: H~2~O, H~23~O, H~many\ of\ them~O. .PP These should not be superscripts or subscripts, because of the unescaped spaces:-a\[ha]b c\[ha]d, a\[ti]b c\[ti]d.+a\(hab c\(had, a\(tib c\(tid. .PP    *   *   *   *   * .SH Smart quotes, ellipses, dashes-\[lq]Hello,\[rq] said the spider.-\[lq]`Shelob' is my name.\[rq]+\(lqHello,\(rq said the spider.+\(lq`Shelob' is my name.\(rq .PP `A', `B', and `C' are letters. .PP `Oak,' `elm,' and `beech' are names of trees. So is `pine.' .PP-`He said, \[lq]I want to go.\[rq]' Were you alive in the 70\[cq]s?+`He said, \(lqI want to go.\(rq' Were you alive in the 70\(cqs? .PP-Here is some quoted `\f[CR]code\f[R]' and a \[lq]\c+Here is some quoted `\f[CR]code\f[R]' and a \(lq\c .UR http://example.com/?foo=1&bar=2 quoted link .UE \c-\[rq].+\(rq. .PP-Some dashes: one\[em]two \[em] three\[em]four \[em] five.+Some dashes: one\(emtwo \(em three\(emfour \(em five. .PP-Dashes between numbers: 5\[en]7, 255\[en]66, 1987\[en]1999.+Dashes between numbers: 5\(en7, 255\(en66, 1987\(en1999. .PP Ellipses\&...and\&...and\&.... .PP    *   *   *   *   * .SH LaTeX-.IP \[bu] 2-.IP \[bu] 2+.IP \(bu 2+.IP \(bu 2 2 + 2 = 4-.IP \[bu] 2+.IP \(bu 2 \f[I]x\f[R] ∈ \f[I]y\f[R]-.IP \[bu] 2+.IP \(bu 2 \f[I]α\f[R] ∧ \f[I]ω\f[R]-.IP \[bu] 2+.IP \(bu 2 223-.IP \[bu] 2+.IP \(bu 2 \f[I]p\f[R]\-Tree-.IP \[bu] 2-Here\[cq]s some display math:+.IP \(bu 2+Here\(cqs some display math: .RS-$$\[rs]frac{d}{dx}f(x)=\[rs]lim_{h\[rs]to 0}\[rs]frac{f(x+h)\-f(x)}{h}$$+$$\(rsfrac{d}{dx}f(x)=\(rslim_{h\(rsto 0}\(rsfrac{f(x+h)\-f(x)}{h}$$ .RE-.IP \[bu] 2-Here\[cq]s one that has a line break in it:+.IP \(bu 2+Here\(cqs one that has a line break in it: \f[I]α\f[R] + \f[I]ω\f[R] × \f[I]x\f[R]^2^. .PP-These shouldn\[cq]t be math:-.IP \[bu] 2-To get the famous equation, write \f[CR]$e = mc\[ha]2$\f[R].-.IP \[bu] 2+These shouldn\(cqt be math:+.IP \(bu 2+To get the famous equation, write \f[CR]$e = mc\(ha2$\f[R].+.IP \(bu 2 $22,000 is a \f[I]lot\f[R] of money. So is $34,000.-(It worked if \[lq]lot\[rq] is emphasized.)-.IP \[bu] 2+(It worked if \(lqlot\(rq is emphasized.)+.IP \(bu 2 Shoes ($20) and socks ($5).-.IP \[bu] 2+.IP \(bu 2 Escaped \f[CR]$\f[R]: $73 \f[I]this should be emphasized\f[R] 23$. .PP-Here\[cq]s a LaTeX table:+Here\(cqs a LaTeX table: .PP    *   *   *   *   * .SH Special Characters Here is some unicode:-.IP \[bu] 2+.IP \(bu 2 I hat: Î-.IP \[bu] 2+.IP \(bu 2 o umlaut: ö-.IP \[bu] 2+.IP \(bu 2 section: §-.IP \[bu] 2+.IP \(bu 2 set membership: ∈-.IP \[bu] 2+.IP \(bu 2 copyright: © .PP AT&T has an ampersand in their name.@@ -555,9 +568,9 @@ .PP 6 > 5. .PP-Backslash: \[rs]+Backslash: \(rs .PP-Backtick: \[ga]+Backtick: \(ga .PP Asterisk: * .PP@@ -633,32 +646,32 @@ .PP Foo biz. .SS With ampersands-Here\[cq]s a \c+Here\(cqs a \c .UR http://example.com/?foo=1&bar=2 link with an ampersand in the URL .UE \c \&. .PP-Here\[cq]s a link with an amersand in the link text: \c+Here\(cqs a link with an amersand in the link text: \c .UR http://att.com/ AT&T .UE \c \&. .PP-Here\[cq]s an inline link.+Here\(cqs an inline link. .PP-Here\[cq]s an inline link in pointy braces.+Here\(cqs an inline link in pointy braces. .SS Autolinks With an ampersand: \c .UR http://example.com/?foo=1&bar=2 .UE \c-.IP \[bu] 2+.IP \(bu 2 In a list?-.IP \[bu] 2+.IP \(bu 2 \c .UR http://example.com/ .UE \c-.IP \[bu] 2+.IP \(bu 2 It should. .PP An e\-mail address: \c@@ -679,7 +692,7 @@ .PP    *   *   *   *   * .SH Images-From \[lq]Voyage dans la Lune\[rq] by Georges Melies (1902):+From \(lqVoyage dans la Lune\(rq by Georges Melies (1902): [IMAGE: lalune] lalune .PP@@ -688,7 +701,7 @@    *   *   *   *   * .SH Footnotes Here is a footnote reference,[1] and another.[2] This should \f[I]not\f[R] be a-footnote reference, because it contains a space.[\[ha]my note] Here is an inline+footnote reference, because it contains a space.[\(hamy note] Here is an inline note.[3] .RS .PP@@ -706,7 +719,7 @@ It need not be placed at the end of the document. .SS [2] .PP-Here\[cq]s the long note.+Here\(cqs the long note. This one contains multiple blocks. .PP Subsequent blocks are indented to show that they belong to the footnote (as with
test/writer.markdown view
@@ -105,45 +105,45 @@  Asterisks tight: --   asterisk 1--   asterisk 2--   asterisk 3+- asterisk 1+- asterisk 2+- asterisk 3  Asterisks loose: --   asterisk 1+- asterisk 1 --   asterisk 2+- asterisk 2 --   asterisk 3+- asterisk 3  Pluses tight: --   Plus 1--   Plus 2--   Plus 3+- Plus 1+- Plus 2+- Plus 3  Pluses loose: --   Plus 1+- Plus 1 --   Plus 2+- Plus 2 --   Plus 3+- Plus 3  Minuses tight: --   Minus 1--   Minus 2--   Minus 3+- Minus 1+- Minus 2+- Minus 3  Minuses loose: --   Minus 1+- Minus 1 --   Minus 2+- Minus 2 --   Minus 3+- Minus 3  ## Ordered @@ -187,17 +187,17 @@  ## Nested --   Tab-    -   Tab-        -   Tab+- Tab+  - Tab+    - Tab  Here's another:  1.  First 2.  Second:-    -   Fee-    -   Fie-    -   Foe+    - Fee+    - Fie+    - Foe 3.  Third  Same thing but with paragraphs:@@ -206,21 +206,21 @@  2.  Second: -    -   Fee-    -   Fie-    -   Foe+    - Fee+    - Fie+    - Foe  3.  Third  ## Tabs and spaces --   this is a list item indented with tabs+- this is a list item indented with tabs --   this is a list item indented with spaces+- this is a list item indented with spaces -    -   this is an example list item indented with tabs+  - this is an example list item indented with tabs -    -   this is an example list item indented with spaces+  - this is an example list item indented with spaces  ## Fancy list markers @@ -261,164 +261,135 @@ Tight using spaces:  apple-:   red fruit+: red fruit  orange-:   orange fruit+: orange fruit  banana-:   yellow fruit+: yellow fruit  Tight using tabs:  apple-:   red fruit+: red fruit  orange-:   orange fruit+: orange fruit  banana-:   yellow fruit+: yellow fruit  Loose:  apple -:   red fruit+: red fruit  orange -:   orange fruit+: orange fruit  banana -:   yellow fruit+: yellow fruit  Multiple blocks with italics:  *apple* -:   red fruit+: red fruit -    contains seeds, crisp, pleasant to taste+  contains seeds, crisp, pleasant to taste  *orange* -:   orange fruit+: orange fruit -        { orange code block }+      { orange code block } -    > orange block quote+  > orange block quote  Multiple definitions, tight:  apple-:   red fruit-:   computer+: red fruit+: computer  orange-:   orange fruit-:   bank+: orange fruit+: bank  Multiple definitions, loose:  apple -:   red fruit+: red fruit -:   computer+: computer  orange -:   orange fruit+: orange fruit -:   bank+: bank  Blank line after term, indented marker, alternate markers:  apple -:   red fruit+: red fruit -:   computer+: computer  orange -:   orange fruit+: orange fruit -    1.  sublist-    2.  sublist+  1.  sublist+  2.  sublist  # HTML Blocks  Simple block on one line: -<div>-+::: {} foo--</div>+:::  And nested without indentation: -<div>--<div>--<div>-+:::::: {}+:::: {}+::: {} foo--</div>--</div>--<div>+:::+:::: +::: {} bar--</div>--</div>+:::+::::::  Interpreted markdown in a table: -```{=html} <table>-```-```{=html} <tr>-```-```{=html} <td>-``` This is *emphasized*-```{=html} </td>-```-```{=html} <td>-``` And this is **strong**-```{=html} </td>-```-```{=html} </tr>-```-```{=html} </table>-```-```{=html} <script type="text/javascript">document.write('This *should not* be interpreted as markdown');</script>-```-Here's a simple block: -<div>+Here's a simple block: +::: {} foo--</div>+:::  This should be a code block, though: @@ -432,80 +403,51 @@  Now, nested: -<div>--<div>--<div>-+::::: {}+:::: {}+::: {} foo--</div>--</div>--</div>+:::+::::+:::::  This should just be an HTML comment: -```{=html} <!-- Comment -->-```+ Multiline: -```{=html} <!-- Blah Blah -->-```-```{=html} <!--     This is another comment. -->-```+ Code block:      <!-- Comment -->  Just plain comment, with trailing spaces on the line: -```{=html} <!-- foo -->-```+ Code:      <hr />  Hr's: -```{=html} <hr>-```-```{=html} <hr />-```-```{=html} <hr />-```-```{=html} <hr>-```-```{=html} <hr />-```-```{=html} <hr />-```-```{=html} <hr class="foo" id="bar" />-```-```{=html} <hr class="foo" id="bar" />-```-```{=html} <hr class="foo" id="bar">-```  -------------------------------------------------------------------------------- @@ -561,33 +503,31 @@  # LaTeX --   `\cite[22-23]{smith.1899}`{=tex}--   $2+2=4$--   $x \in y$--   $\alpha \wedge \omega$--   $223$--   $p$-Tree--   Here's some display math:-    $$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$--   Here's one that has a line break in it: $\alpha + \omega \times x^2$.+- `\cite[22-23]{smith.1899}`{=tex}+- $2+2=4$+- $x \in y$+- $\alpha \wedge \omega$+- $223$+- $p$-Tree+- Here's some display math:+  $$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$+- Here's one that has a line break in it: $\alpha + \omega \times x^2$.  These shouldn't be math: --   To get the famous equation, write `$e = mc^2$`.--   \$22,000 is a *lot* of money. So is \$34,000. (It worked if "lot" is-    emphasized.)--   Shoes (\$20) and socks (\$5).--   Escaped `$`: \$73 *this should be emphasized* 23\$.+- To get the famous equation, write `$e = mc^2$`.+- \$22,000 is a *lot* of money. So is \$34,000. (It worked if "lot" is+  emphasized.)+- Shoes (\$20) and socks (\$5).+- Escaped `$`: \$73 *this should be emphasized* 23\$.  Here's a LaTeX table: -```{=tex} \begin{tabular}{|l|l|}\hline Animal & Number \\ \hline Dog    & 2      \\ Cat    & 1      \\ \hline \end{tabular}-```  -------------------------------------------------------------------------------- @@ -595,11 +535,11 @@  Here is some unicode: --   I hat: Î--   o umlaut: ö--   section: §--   set membership: ∈--   copyright: ©+- I hat: Î+- o umlaut: ö+- section: §+- set membership: ∈+- copyright: ©  AT&T has an ampersand in their name. @@ -703,9 +643,9 @@  With an ampersand: <http://example.com/?foo=1&bar=2> --   In a list?--   <http://example.com/>--   It should.+- In a list?+- <http://example.com/>+- It should.  An e-mail address: <nobody@nowhere.net> 
test/writer.markua view
@@ -317,17 +317,17 @@  : red fruit -    contains seeds, crisp, pleasant to taste+  contains seeds, crisp, pleasant to taste  *orange*  : orange fruit -    ```-    { orange code block }-    ```+  ```+  { orange code block }+  ``` -    > orange block quote+  > orange block quote  Multiple definitions, tight: @@ -365,8 +365,8 @@  : orange fruit -    1. sublist-    2. sublist+  1. sublist+  2. sublist  {id: html-blocks} # HTML Blocks
test/writer.mediawiki view
@@ -1,6 +1,5 @@ This is a set of tests for pandoc. Most of them are adapted from John Gruber’s markdown test suite. - -----  <span id="headers"></span>@@ -34,7 +33,6 @@  with no blank line - -----  <span id="paragraphs"></span>@@ -49,7 +47,6 @@ There should be a hard line break<br /> here. - -----  <span id="block-quotes"></span>@@ -74,12 +71,12 @@ <blockquote>nested </blockquote> <blockquote>nested-</blockquote></blockquote>+</blockquote>+</blockquote> This should not be a block quote: 2 &gt; 1.  And a following paragraph. - -----  <span id="code-blocks"></span>@@ -224,9 +221,7 @@ <li>more items <ol style="list-style-type: upper-alpha;"> <li>a subsublist</li>-<li>a subsublist</li></ol>-</li></ol>-</li></ol>+<li>a subsublist</li></ol></li></ol></li></ol>  Nesting: @@ -237,10 +232,7 @@ <ol start="6" style="list-style-type: decimal;"> <li>Decimal start with 6 <ol start="3" style="list-style-type: lower-alpha;">-<li>Lower alpha with paren</li></ol>-</li></ol>-</li></ol>-</li></ol>+<li>Lower alpha with paren</li></ol></li></ol></li></ol></li></ol>  Autonumbering: @@ -254,7 +246,6 @@  B. Williams - -----  <span id="definition-lists"></span>@@ -296,7 +287,8 @@ <dt>''orange''</dt> <dd><p>orange fruit</p> <pre>{ orange code block }</pre>-<blockquote><p>orange block quote</p></blockquote></dd></dl>+<blockquote><p>orange block quote</p>+</blockquote></dd></dl>  Multiple definitions, tight: @@ -332,31 +324,26 @@ Simple block on one line:  <div>- foo- </div>+ And nested without indentation:  <div>- <div>- <div>- foo - </div>  </div>-<div> +<div> bar- </div>  </div>+ Interpreted markdown in a table:  <table>@@ -373,11 +360,10 @@ Here’s a simple block:  <div>- foo - </div>+ This should be a code block, though:  <pre>&lt;div&gt;@@ -389,18 +375,15 @@ Now, nested:  <div>- <div>- <div>- foo- </div>  </div>  </div>+ This should just be an HTML comment:  <!-- Comment -->@@ -463,7 +446,6 @@  These should not be superscripts or subscripts, because of the unescaped spaces: a^b c^d, a~b c~d. - -----  <span id="smart-quotes-ellipses-dashes"></span>@@ -485,13 +467,12 @@  Ellipses…and…and…. - -----  <span id="latex"></span> = LaTeX = -* +* * <math display="inline">2+2=4</math> * <math display="inline">x \in y</math> * <math display="inline">\alpha \wedge \omega</math>@@ -509,8 +490,6 @@  Here’s a LaTeX table: -- -----  <span id="special-characters"></span>@@ -566,7 +545,6 @@  Minus: - - -----  <span id="links"></span>@@ -651,12 +629,10 @@ From “Voyage dans la Lune” by Georges Melies (1902):  <div class="figure">- [[File:lalune.jpg|lalune]]- </div>-Here is a movie [[File:movie.jpg|movie]] icon. +Here is a movie [[File:movie.jpg|movie]] icon.  ----- 
test/writer.ms view
@@ -27,7 +27,7 @@ .\" line height .nr VS 12p .\" font family: A, BM, H, HN, N, P, T, ZCM-.fam P+.fam T .\" paragraph indent .nr PI 0m .\" interparagraph space@@ -38,10 +38,6 @@ .nr FPS (\n[PS] - 2000) .\" color used for strikeout .defcolor strikecolor rgb 0.7 0.7 0.7-.\" color for links (rgb)-.ds PDFHREF.COLOUR   0.35 0.00 0.60-.\" border for links (default none)-.ds PDFHREF.BORDER   0 0 0 .\" point size difference between heading levels .nr PSINCR 1p .\" heading level above which point size no longer changes@@ -52,6 +48,14 @@ .\" page numbers in footer, centered .ds CH .ds CF %+.hy+.EQ+delim @@+.EN+.\" color for links (rgb)+.ds PDFHREF.COLOUR   0.35 0.00 0.60+.\" border for links (default none)+.ds PDFHREF.BORDER   0 0 0 .\" pdf outline fold level .nr PDFOUTLINE.FOLDLEVEL 3 .\" start out in outline view@@ -60,10 +64,6 @@ .\" PDF metadata .pdfinfo /Title "Pandoc Test Suite" .pdfinfo /Author "John MacFarlane; Anonymous"-.hy-.EQ-delim @@-.EN .TL Pandoc Test Suite .AU@@ -78,7 +78,7 @@ .1C .LP This is a set of tests for pandoc.-Most of them are adapted from John Gruber\[cq]s markdown test suite.+Most of them are adapted from John Gruber\(cqs markdown test suite. .HLINE .SH 1 Headers@@ -129,15 +129,15 @@ .pdfhref O 1 "Paragraphs" .pdfhref M "paragraphs" .LP-Here\[cq]s a regular paragraph.+Here\(cqs a regular paragraph. .PP In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item.-Because a hard\-wrapped line in the middle of a paragraph looked like a list+Because a hard-wrapped line in the middle of a paragraph looked like a list item. .PP-Here\[cq]s one with a bullet.+Here\(cqs one with a bullet. * criminey. .PP There should be a hard line break@@ -149,7 +149,7 @@ .pdfhref O 1 "Block Quotes" .pdfhref M "block-quotes" .LP-E\-mail style:+E-mail style: .QS .LP This is a block quote.@@ -162,7 +162,7 @@ .nf \f[C] sub status {-    print \[dq]working\[dq];+    print \(dqworking\(dq; } \f[] .fi@@ -197,10 +197,10 @@ .IP .nf \f[C]-\-\-\-\- (should be four hyphens)+---- (should be four hyphens)  sub status {-    print \[dq]working\[dq];+    print \(dqworking\(dq; }  this code block is indented by one tab@@ -213,7 +213,7 @@ \f[C]     this code block is indented by two tabs -These should not be escaped:  \[rs]$ \[rs]\[rs] \[rs]> \[rs][ \[rs]{+These should not be escaped:  \(rs$ \(rs\(rs \(rs> \(rs[ \(rs{ \f[] .fi .HLINE@@ -227,51 +227,51 @@ .pdfhref M "unordered" .LP Asterisks tight:-.IP \[bu] 3+.IP \(bu 3 asterisk 1-.IP \[bu] 3+.IP \(bu 3 asterisk 2-.IP \[bu] 3+.IP \(bu 3 asterisk 3 .LP Asterisks loose:-.IP \[bu] 3+.IP \(bu 3 asterisk 1-.IP \[bu] 3+.IP \(bu 3 asterisk 2-.IP \[bu] 3+.IP \(bu 3 asterisk 3 .LP Pluses tight:-.IP \[bu] 3+.IP \(bu 3 Plus 1-.IP \[bu] 3+.IP \(bu 3 Plus 2-.IP \[bu] 3+.IP \(bu 3 Plus 3 .LP Pluses loose:-.IP \[bu] 3+.IP \(bu 3 Plus 1-.IP \[bu] 3+.IP \(bu 3 Plus 2-.IP \[bu] 3+.IP \(bu 3 Plus 3 .LP Minuses tight:-.IP \[bu] 3+.IP \(bu 3 Minus 1-.IP \[bu] 3+.IP \(bu 3 Minus 2-.IP \[bu] 3+.IP \(bu 3 Minus 3 .LP Minuses loose:-.IP \[bu] 3+.IP \(bu 3 Minus 1-.IP \[bu] 3+.IP \(bu 3 Minus 2-.IP \[bu] 3+.IP \(bu 3 Minus 3 .SH 2 Ordered@@ -317,7 +317,7 @@ .PP Item 1. graf two.-The quick brown fox jumped over the lazy dog\[cq]s back.+The quick brown fox jumped over the lazy dog\(cqs back. .RE .IP " 2." 4 Item 2.@@ -327,28 +327,28 @@ Nested .pdfhref O 2 "Nested" .pdfhref M "nested"-.IP \[bu] 3+.IP \(bu 3 Tab .RS 3-.IP \[bu] 3+.IP \(bu 3 Tab .RS 3-.IP \[bu] 3+.IP \(bu 3 Tab .RE .RE .LP-Here\[cq]s another:+Here\(cqs another: .IP " 1." 4 First .IP " 2." 4 Second: .RS 4-.IP \[bu] 3+.IP \(bu 3 Fee-.IP \[bu] 3+.IP \(bu 3 Fie-.IP \[bu] 3+.IP \(bu 3 Foe .RE .IP " 3." 4@@ -360,11 +360,11 @@ .IP " 2." 4 Second: .RS 4-.IP \[bu] 3+.IP \(bu 3 Fee-.IP \[bu] 3+.IP \(bu 3 Fie-.IP \[bu] 3+.IP \(bu 3 Foe .RE .IP " 3." 4@@ -373,14 +373,14 @@ Tabs and spaces .pdfhref O 2 "Tabs and spaces" .pdfhref M "tabs-and-spaces"-.IP \[bu] 3+.IP \(bu 3 this is a list item indented with tabs-.IP \[bu] 3+.IP \(bu 3 this is a list item indented with spaces .RS 3-.IP \[bu] 3+.IP \(bu 3 this is an example list item indented with tabs-.IP \[bu] 3+.IP \(bu 3 this is an example list item indented with spaces .RE .SH 2@@ -572,7 +572,7 @@ This is \f[I]emphasized\f[R] And this is \f[B]strong\f[R] .PP-Here\[cq]s a simple block:+Here\(cqs a simple block: .LP foo .LP@@ -605,7 +605,7 @@ .IP .nf \f[C]-<!\-\- Comment \-\->+<!-- Comment --> \f[] .fi .LP@@ -619,7 +619,7 @@ \f[] .fi .LP-Hr\[cq]s:+Hr\(cqs: .HLINE .SH 1 Inline Markup@@ -643,7 +643,7 @@ .PP So is \f[B]\f[BI]this\f[B]\f[R] word. .PP-This is code: \f[CR]>\f[R], \f[CR]$\f[R], \f[CR]\[rs]\f[R], \f[CR]\[rs]$\f[R],+This is code: \f[CR]>\f[R], \f[CR]$\f[R], \f[CR]\(rs\f[R], \f[CR]\(rs$\f[R], \f[CR]<html>\f[R]. .PP \m[strikecolor]This is \f[I]strikeout\f[R].\m[]@@ -653,31 +653,31 @@ Subscripts: H\*<2\*>O, H\*<23\*>O, H\*<many\ of\ them\*>O. .PP These should not be superscripts or subscripts, because of the unescaped spaces:-a\[ha]b c\[ha]d, a\[ti]b c\[ti]d.+a\(hab c\(had, a\(tib c\(tid. .HLINE .SH 1 Smart quotes, ellipses, dashes .pdfhref O 1 "Smart quotes, ellipses, dashes" .pdfhref M "smart-quotes-ellipses-dashes" .LP-\[lq]Hello,\[rq] said the spider.-\[lq]`Shelob' is my name.\[rq]+\(lqHello,\(rq said the spider.+\(lq`Shelob' is my name.\(rq .PP `A', `B', and `C' are letters. .PP `Oak,' `elm,' and `beech' are names of trees. So is `pine.' .PP-`He said, \[lq]I want to go.\[rq]' Were you alive in the 70\[cq]s?+`He said, \(lqI want to go.\(rq' Were you alive in the 70\(cqs? .PP-Here is some quoted `\f[CR]code\f[R]' and a \[lq]\c+Here is some quoted `\f[CR]code\f[R]' and a \(lq\c .pdfhref W -D "http://example.com/?foo=1&bar=2" -A "\c" \  -- "quoted link"-\&\[rq].+\&\(rq. .PP-Some dashes: one\[em]two \[em] three\[em]four \[em] five.+Some dashes: one\(emtwo \(em three\(emfour \(em five. .PP-Dashes between numbers: 5\[en]7, 255\[en]66, 1987\[en]1999.+Dashes between numbers: 5\(en7, 255\(en66, 1987\(en1999. .PP Ellipses\&...and\&...and\&.... .HLINE@@ -685,38 +685,38 @@ LaTeX .pdfhref O 1 "LaTeX" .pdfhref M "latex"-.IP \[bu] 3-.IP \[bu] 3+.IP \(bu 3+.IP \(bu 3 @2 + 2 = 4@-.IP \[bu] 3+.IP \(bu 3 @x \[u2208] y@-.IP \[bu] 3+.IP \(bu 3 @alpha \[u2227] omega@-.IP \[bu] 3+.IP \(bu 3 @223@-.IP \[bu] 3-@p@\-Tree-.IP \[bu] 3-Here\[cq]s some display math:+.IP \(bu 3+@p@-Tree+.IP \(bu 3+Here\(cqs some display math: .EQ-d over {d x} f left ( x right ) = lim from {h -> 0} {f left ( x + h right ) - f left ( x right )} over h+d over {d x} f ( x ) = lim from {h -> 0} {f ( x + h ) - f ( x )} over h .EN-.IP \[bu] 3-Here\[cq]s one that has a line break in it: @alpha + omega times x sup 2@.+.IP \(bu 3+Here\(cqs one that has a line break in it: @alpha + omega times x sup 2@. .LP-These shouldn\[cq]t be math:-.IP \[bu] 3-To get the famous equation, write \f[CR]$e = mc\[ha]2$\f[R].-.IP \[bu] 3+These shouldn\(cqt be math:+.IP \(bu 3+To get the famous equation, write \f[CR]$e = mc\(ha2$\f[R].+.IP \(bu 3 $22,000 is a \f[I]lot\f[R] of money. So is $34,000.-(It worked if \[lq]lot\[rq] is emphasized.)-.IP \[bu] 3+(It worked if \(lqlot\(rq is emphasized.)+.IP \(bu 3 Shoes ($20) and socks ($5).-.IP \[bu] 3+.IP \(bu 3 Escaped \f[CR]$\f[R]: $73 \f[I]this should be emphasized\f[R] 23$. .LP-Here\[cq]s a LaTeX table:+Here\(cqs a LaTeX table: .HLINE .SH 1 Special Characters@@ -724,15 +724,15 @@ .pdfhref M "special-characters" .LP Here is some unicode:-.IP \[bu] 3+.IP \(bu 3 I hat: Î-.IP \[bu] 3+.IP \(bu 3 o umlaut: ö-.IP \[bu] 3+.IP \(bu 3 section: §-.IP \[bu] 3+.IP \(bu 3 set membership: ∈-.IP \[bu] 3+.IP \(bu 3 copyright: © .LP AT&T has an ampersand in their name.@@ -745,9 +745,9 @@ .PP 6 > 5. .PP-Backslash: \[rs]+Backslash: \(rs .PP-Backtick: \[ga]+Backtick: \(ga .PP Asterisk: * .PP@@ -765,7 +765,7 @@ .PP Right paren: ) .PP-Greater\-than: >+Greater-than: > .PP Hash: # .PP@@ -775,7 +775,7 @@ .PP Plus: + .PP-Minus: \-+Minus: - .HLINE .SH 1 Links@@ -887,22 +887,22 @@ .pdfhref O 2 "With ampersands" .pdfhref M "with-ampersands" .LP-Here\[cq]s a \c+Here\(cqs a \c .pdfhref W -D "http://example.com/?foo=1&bar=2" -A "\c" \  -- "link with an ampersand in the URL" \&. .PP-Here\[cq]s a link with an amersand in the link text: \c+Here\(cqs a link with an amersand in the link text: \c .pdfhref W -D "http://att.com/" -A "\c" \  -- "AT&T" \&. .PP-Here\[cq]s an \c+Here\(cqs an \c .pdfhref W -D "/script?foo=1&bar=2" -A "\c" \  -- "inline link" \&. .PP-Here\[cq]s an \c+Here\(cqs an \c .pdfhref W -D "/script?foo=1&bar=2" -A "\c" \  -- "inline link in pointy braces" \&.@@ -915,19 +915,19 @@ .pdfhref W -D "http://example.com/?foo=1&bar=2" -A "\c" \  -- "http://example.com/?foo=1&bar=2" \&-.IP \[bu] 3+.IP \(bu 3 In a list?-.IP \[bu] 3+.IP \(bu 3 \c .pdfhref W -D "http://example.com/" -A "\c" \  -- "http://example.com/" \&-.IP \[bu] 3+.IP \(bu 3 It should. .LP-An e\-mail address: \c+An e-mail address: \c .pdfhref W -D "mailto:nobody%40nowhere.net" -A "\c" \- -- "nobody\[at]nowhere.net"+ -- "nobody\(atnowhere.net" \& .QS .LP@@ -937,7 +937,7 @@ \& .QE .LP-Auto\-links should not occur here: \f[CR]<http://example.com/>\f[R]+Auto-links should not occur here: \f[CR]<http://example.com/>\f[R] .IP .nf \f[C]@@ -950,7 +950,7 @@ .pdfhref O 1 "Images" .pdfhref M "images" .LP-From \[lq]Voyage dans la Lune\[rq] by Georges Melies (1902):+From \(lqVoyage dans la Lune\(rq by Georges Melies (1902): \" .IMAGE "lalune.jpg" .ce 1 lalune@@ -973,7 +973,7 @@ .FE and another.\** .FS-Here\[cq]s the long note.+Here\(cqs the long note. This one contains multiple blocks. .PP Subsequent blocks are indented to show that they belong to the footnote (as with@@ -989,7 +989,7 @@ the first line of each block. .FE This should \f[I]not\f[R] be a footnote reference, because it contains a-space.[\[ha]my note] Here is an inline note.\**+space.[\(hamy note] Here is an inline note.\** .FS This is \f[I]easier\f[R] to type. Inline notes may contain \c
test/writer.opendocument view
@@ -4,1908 +4,958 @@     <style:font-face style:name="Courier New" style:font-family-generic="modern" style:font-pitch="fixed" svg:font-family="'Courier New'" />   </office:font-face-decls>   <office:automatic-styles>-    <text:list-style style:name="L1">-      <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />-        </style:list-level-properties>-      </text:list-level-style-number>-    </text:list-style>-    <text:list-style style:name="L2">-      <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-    </text:list-style>-    <text:list-style style:name="L3">-      <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-    </text:list-style>-    <text:list-style style:name="L4">-      <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-    </text:list-style>-    <text:list-style style:name="L5">-      <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-    </text:list-style>-    <text:list-style style:name="L6">-      <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-    </text:list-style>-    <text:list-style style:name="L7">-      <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-    </text:list-style>-    <text:list-style style:name="L8">-      <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />-        </style:list-level-properties>-      </text:list-level-style-number>-    </text:list-style>-    <text:list-style style:name="L9">-      <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />-        </style:list-level-properties>-      </text:list-level-style-number>-    </text:list-style>-    <text:list-style style:name="L10">-      <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />-        </style:list-level-properties>-      </text:list-level-style-number>-    </text:list-style>-    <text:list-style style:name="L11">-      <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />-        </style:list-level-properties>-      </text:list-level-style-number>-    </text:list-style>-    <text:list-style style:name="L12">-      <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />-        </style:list-level-properties>-      </text:list-level-style-number>-    </text:list-style>-    <text:list-style style:name="L13">-      <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-    </text:list-style>-    <text:list-style style:name="L14">-      <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-    </text:list-style>-    <text:list-style style:name="L15">-      <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-    </text:list-style>-    <text:list-style style:name="L16">-      <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />-        </style:list-level-properties>-      </text:list-level-style-number>-    </text:list-style>-    <text:list-style style:name="L17">-      <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-    </text:list-style>-    <text:list-style style:name="L18">-      <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />-        </style:list-level-properties>-      </text:list-level-style-number>-    </text:list-style>-    <text:list-style style:name="L19">-      <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-    </text:list-style>-    <text:list-style style:name="L20">-      <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-    </text:list-style>-    <text:list-style style:name="L21">-      <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-    </text:list-style>-    <text:list-style style:name="L22">-      <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="2" style:num-prefix="(" style:num-suffix=")">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />-        </style:list-level-properties>-      </text:list-level-style-number>-      <text:list-level-style-number text:level="2" text:style-name="Numbering_20_Symbols" style:num-format="i" text:start-value="4" style:num-suffix=".">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />-        </style:list-level-properties>-      </text:list-level-style-number>-      <text:list-level-style-number text:level="3" text:style-name="Numbering_20_Symbols" style:num-format="A" text:start-value="1" style:num-prefix="(" style:num-suffix=")">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />-        </style:list-level-properties>-      </text:list-level-style-number>-    </text:list-style>-    <text:list-style style:name="L23">-      <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="A" text:start-value="1" style:num-suffix=".">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />-        </style:list-level-properties>-      </text:list-level-style-number>-      <text:list-level-style-number text:level="2" text:style-name="Numbering_20_Symbols" style:num-format="I" text:start-value="1" style:num-suffix=".">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />-        </style:list-level-properties>-      </text:list-level-style-number>-      <text:list-level-style-number text:level="3" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="6" style:num-prefix="(" style:num-suffix=")">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />-        </style:list-level-properties>-      </text:list-level-style-number>-      <text:list-level-style-number text:level="4" text:style-name="Numbering_20_Symbols" style:num-format="a" text:start-value="3" style:num-suffix=")">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />-        </style:list-level-properties>-      </text:list-level-style-number>-    </text:list-style>-    <text:list-style style:name="L24">-      <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />-        </style:list-level-properties>-      </text:list-level-style-number>-      <text:list-level-style-number text:level="2" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />-        </style:list-level-properties>-      </text:list-level-style-number>-    </text:list-style>-    <text:list-style style:name="L25">-      <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />-        </style:list-level-properties>-      </text:list-level-style-number>-    </text:list-style>-    <text:list-style style:name="L26">-      <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-    </text:list-style>-    <text:list-style style:name="L27">-      <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-    </text:list-style>-    <text:list-style style:name="L28">-      <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-    </text:list-style>-    <text:list-style style:name="L29">-      <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-      <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />-        </style:list-level-properties>-      </text:list-level-style-bullet>-    </text:list-style>-    <text:list-style style:name="L30">-      <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">-        <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">-          <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />-        </style:list-level-properties>-      </text:list-level-style-number>-    </text:list-style>-    <style:style style:name="T1" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style>-    <style:style style:name="T2" style:family="text"><style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold" /></style:style>-    <style:style style:name="T3" style:family="text"><style:text-properties fo:font-style="italic" fo:font-weight="bold" style:font-style-asian="italic" style:font-style-complex="italic" style:font-weight-asian="bold" style:font-weight-complex="bold" /></style:style>-    <style:style style:name="T4" style:family="text"><style:text-properties style:text-line-through-style="solid" /></style:style>-    <style:style style:name="T5" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" style:text-line-through-style="solid" /></style:style>-    <style:style style:name="T6" style:family="text"><style:text-properties style:text-position="super 58%" /></style:style>-    <style:style style:name="T7" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" style:text-position="super 58%" /></style:style>-    <style:style style:name="T8" style:family="text"><style:text-properties style:text-position="sub 58%" /></style:style>-    <style:style style:name="fr2" style:family="graphic" style:parent-style-name="Formula"><style:graphic-properties style:vertical-pos="middle" style:vertical-rel="text" style:horizontal-pos="center" style:horizontal-rel="paragraph-content" style:wrap="none" /></style:style>-    <style:style style:name="fr1" style:family="graphic" style:parent-style-name="Formula"><style:graphic-properties style:vertical-pos="middle" style:vertical-rel="text" /></style:style>-    <style:style style:name="P1" style:family="paragraph" style:parent-style-name="Quotations">-      <style:paragraph-properties fo:margin-left="0.5in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" />-    </style:style>-    <style:style style:name="P2" style:family="paragraph" style:parent-style-name="Quotations">-      <style:paragraph-properties fo:margin-left="0.5in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" />-    </style:style>-    <style:style style:name="P3" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">-      <style:paragraph-properties fo:margin-left="0.5in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" />-    </style:style>-    <style:style style:name="P4" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">-      <style:paragraph-properties fo:margin-left="0.5in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" />-    </style:style>-    <style:style style:name="P5" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">-      <style:paragraph-properties fo:margin-left="0.5in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" />-    </style:style>-    <style:style style:name="P6" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1">-      <style:paragraph-properties fo:margin-left="0.5in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" fo:margin-top="0in" fo:margin-bottom="0in" />-    </style:style>-    <style:style style:name="P7" style:family="paragraph" style:parent-style-name="Quotations">-      <style:paragraph-properties fo:margin-left="1.0in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" />-    </style:style>-    <style:style style:name="P8" style:family="paragraph" style:parent-style-name="Quotations">-      <style:paragraph-properties fo:margin-left="1.0in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" />-    </style:style>-    <style:style style:name="P9" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">-    </style:style>-    <style:style style:name="P10" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">-    </style:style>-    <style:style style:name="P11" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">-    </style:style>-    <style:style style:name="P12" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">-    </style:style>-    <style:style style:name="P13" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">-    </style:style>-    <style:style style:name="P14" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">-    </style:style>-    <style:style style:name="P15" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">-    </style:style>-    <style:style style:name="P16" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">-    </style:style>-    <style:style style:name="P17" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">-    </style:style>-    <style:style style:name="P18" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">-    </style:style>-    <style:style style:name="P19" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L2">-      <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />-    </style:style>-    <style:style style:name="P20" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L3">-    </style:style>-    <style:style style:name="P21" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L4">-      <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />-    </style:style>-    <style:style style:name="P22" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L5">-    </style:style>-    <style:style style:name="P23" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L6">-      <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />-    </style:style>-    <style:style style:name="P24" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L7">-    </style:style>-    <style:style style:name="P25" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L8">-      <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />-    </style:style>-    <style:style style:name="P26" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L9">-      <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />-    </style:style>-    <style:style style:name="P27" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L10">-    </style:style>-    <style:style style:name="P28" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L11">-    </style:style>-    <style:style style:name="P29" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L12">-    </style:style>-    <style:style style:name="P30" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L13">-      <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />-    </style:style>-    <style:style style:name="P31" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L14">-      <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />-    </style:style>-    <style:style style:name="P32" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L15">-      <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />-    </style:style>-    <style:style style:name="P33" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L16">-      <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />-    </style:style>-    <style:style style:name="P34" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L17">-      <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />-    </style:style>-    <style:style style:name="P35" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L18">-    </style:style>-    <style:style style:name="P36" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L19">-      <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />-    </style:style>-    <style:style style:name="P37" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L20">-    </style:style>-    <style:style style:name="P38" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L21">-    </style:style>-    <style:style style:name="P39" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L22">-    </style:style>-    <style:style style:name="P40" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L23">-      <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />-    </style:style>-    <style:style style:name="P41" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L24">-      <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />-    </style:style>-    <style:style style:name="P42" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">-      <style:paragraph-properties fo:margin-left="0.5in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" />-    </style:style>-    <style:style style:name="P43" style:family="paragraph" style:parent-style-name="Quotations">-      <style:paragraph-properties fo:margin-left="0.5in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" />-    </style:style>-    <style:style style:name="P44" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L25">-      <style:paragraph-properties fo:margin-left="0.5in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" fo:margin-top="0in" fo:margin-bottom="0in" />-    </style:style>-    <style:style style:name="P45" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">-    </style:style>-    <style:style style:name="P46" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">-    </style:style>-    <style:style style:name="P47" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">-    </style:style>-    <style:style style:name="P48" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">-    </style:style>-    <style:style style:name="P49" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">-    </style:style>-    <style:style style:name="P50" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">-    </style:style>-    <style:style style:name="P51" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L26">-      <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />-    </style:style>-    <style:style style:name="P52" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L27">-      <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />-    </style:style>-    <style:style style:name="P53" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L28">-      <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />-    </style:style>-    <style:style style:name="P54" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">-    </style:style>-    <style:style style:name="P55" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L29">-      <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />-    </style:style>-    <style:style style:name="P56" style:family="paragraph" style:parent-style-name="Quotations">-      <style:paragraph-properties fo:margin-left="0.5in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" />-    </style:style>-    <style:style style:name="P57" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">-    </style:style>-    <style:style style:name="P58" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">-    </style:style>-    <style:style style:name="P59" style:family="paragraph" style:parent-style-name="Quotations">-      <style:paragraph-properties fo:margin-left="0.5in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" />-    </style:style>-    <style:style style:name="P60" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L30">-      <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />-    </style:style>-  </office:automatic-styles>-<office:body>-<office:text>-<text:p text:style-name="Title">Pandoc Test Suite</text:p>-<text:p text:style-name="Author">John MacFarlane</text:p>-<text:p text:style-name="Author">Anonymous</text:p>-<text:p text:style-name="Date">July 17, 2006</text:p>-<text:p text:style-name="Text_20_body">This is a set of tests for pandoc. Most-of them are adapted from John Gruber’s markdown test suite.</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="headers" />Headers<text:bookmark-end text:name="headers" /></text:h>-<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="level-2-with-an-embedded-link" />Level-2 with an-<text:a xlink:type="simple" xlink:href="/url" office:name=""><text:span text:style-name="Definition">embedded-link</text:span></text:a><text:bookmark-end text:name="level-2-with-an-embedded-link" /></text:h>-<text:h text:style-name="Heading_20_3" text:outline-level="3"><text:bookmark-start text:name="level-3-with-emphasis" />Level-3 with-<text:span text:style-name="T1">emphasis</text:span><text:bookmark-end text:name="level-3-with-emphasis" /></text:h>-<text:h text:style-name="Heading_20_4" text:outline-level="4"><text:bookmark-start text:name="level-4" />Level-4<text:bookmark-end text:name="level-4" /></text:h>-<text:h text:style-name="Heading_20_5" text:outline-level="5"><text:bookmark-start text:name="level-5" />Level-5<text:bookmark-end text:name="level-5" /></text:h>-<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="level-1" />Level-1<text:bookmark-end text:name="level-1" /></text:h>-<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="level-2-with-emphasis" />Level-2 with-<text:span text:style-name="T1">emphasis</text:span><text:bookmark-end text:name="level-2-with-emphasis" /></text:h>-<text:h text:style-name="Heading_20_3" text:outline-level="3"><text:bookmark-start text:name="level-3" />Level-3<text:bookmark-end text:name="level-3" /></text:h>-<text:p text:style-name="First_20_paragraph">with no blank line</text:p>-<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="level-2" />Level-2<text:bookmark-end text:name="level-2" /></text:h>-<text:p text:style-name="First_20_paragraph">with no blank line</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="paragraphs" />Paragraphs<text:bookmark-end text:name="paragraphs" /></text:h>-<text:p text:style-name="First_20_paragraph">Here’s a regular-paragraph.</text:p>-<text:p text:style-name="Text_20_body">In Markdown 1.0.0 and earlier. Version 8.-This line turns into a list item. Because a hard-wrapped line in the middle of a-paragraph looked like a list item.</text:p>-<text:p text:style-name="Text_20_body">Here’s one with a bullet. *-criminey.</text:p>-<text:p text:style-name="Text_20_body">There should be a hard line-break<text:line-break />here.</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="block-quotes" />Block-Quotes<text:bookmark-end text:name="block-quotes" /></text:h>-<text:p text:style-name="First_20_paragraph">E-mail style:</text:p>-<text:p text:style-name="P1">This is a block quote. It is pretty short.</text:p>-<text:p text:style-name="P2">Code in a block quote:</text:p>-<text:p text:style-name="P3">sub status {</text:p>-<text:p text:style-name="P4"><text:s text:c="4" />print &quot;working&quot;;</text:p>-<text:p text:style-name="P5">}</text:p>-<text:p text:style-name="P2">A list:</text:p>-<text:list text:style-name="L1">-  <text:list-item>-    <text:p text:style-name="P6">item one</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P6">item two</text:p>-  </text:list-item>-</text:list>-<text:p text:style-name="P2">Nested block quotes:</text:p>-<text:p text:style-name="P7">nested</text:p>-<text:p text:style-name="P8">nested</text:p>-<text:p text:style-name="First_20_paragraph">This should not be a block quote: 2-&gt; 1.</text:p>-<text:p text:style-name="Text_20_body">And a following paragraph.</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="code-blocks" />Code-Blocks<text:bookmark-end text:name="code-blocks" /></text:h>-<text:p text:style-name="First_20_paragraph">Code:</text:p>-<text:p text:style-name="P9">---- (should be four hyphens)</text:p>-<text:p text:style-name="P10"></text:p>-<text:p text:style-name="P11">sub status {</text:p>-<text:p text:style-name="P12"><text:s text:c="4" />print &quot;working&quot;;</text:p>-<text:p text:style-name="P13">}</text:p>-<text:p text:style-name="P14"></text:p>-<text:p text:style-name="P15">this code block is indented by one tab</text:p>-<text:p text:style-name="First_20_paragraph">And:</text:p>-<text:p text:style-name="P16"><text:s text:c="4" />this code block is indented by two tabs</text:p>-<text:p text:style-name="P17"></text:p>-<text:p text:style-name="P18">These should not be escaped: <text:s text:c="1" />\$ \\ \&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="lists" />Lists<text:bookmark-end text:name="lists" /></text:h>-<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="unordered" />Unordered<text:bookmark-end text:name="unordered" /></text:h>-<text:p text:style-name="First_20_paragraph">Asterisks tight:</text:p>-<text:list text:style-name="L2">-  <text:list-item>-    <text:p text:style-name="P19">asterisk 1</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P19">asterisk 2</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P19">asterisk 3</text:p>-  </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">Asterisks loose:</text:p>-<text:list text:style-name="L3">-  <text:list-item>-    <text:p text:style-name="P20">asterisk 1</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P20">asterisk 2</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P20">asterisk 3</text:p>-  </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">Pluses tight:</text:p>-<text:list text:style-name="L4">-  <text:list-item>-    <text:p text:style-name="P21">Plus 1</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P21">Plus 2</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P21">Plus 3</text:p>-  </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">Pluses loose:</text:p>-<text:list text:style-name="L5">-  <text:list-item>-    <text:p text:style-name="P22">Plus 1</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P22">Plus 2</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P22">Plus 3</text:p>-  </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">Minuses tight:</text:p>-<text:list text:style-name="L6">-  <text:list-item>-    <text:p text:style-name="P23">Minus 1</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P23">Minus 2</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P23">Minus 3</text:p>-  </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">Minuses loose:</text:p>-<text:list text:style-name="L7">-  <text:list-item>-    <text:p text:style-name="P24">Minus 1</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P24">Minus 2</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P24">Minus 3</text:p>-  </text:list-item>-</text:list>-<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="ordered" />Ordered<text:bookmark-end text:name="ordered" /></text:h>-<text:p text:style-name="First_20_paragraph">Tight:</text:p>-<text:list text:style-name="L8">-  <text:list-item>-    <text:p text:style-name="P25">First</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P25">Second</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P25">Third</text:p>-  </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">and:</text:p>-<text:list text:style-name="L9">-  <text:list-item>-    <text:p text:style-name="P26">One</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P26">Two</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P26">Three</text:p>-  </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">Loose using tabs:</text:p>-<text:list text:style-name="L10">-  <text:list-item>-    <text:p text:style-name="P27">First</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P27">Second</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P27">Third</text:p>-  </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">and using spaces:</text:p>-<text:list text:style-name="L11">-  <text:list-item>-    <text:p text:style-name="P28">One</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P28">Two</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P28">Three</text:p>-  </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">Multiple paragraphs:</text:p>-<text:list text:style-name="L12">-  <text:list-item>-    <text:p text:style-name="P29">Item 1, graf one.</text:p>-    <text:p text:style-name="P29">Item 1. graf two. The quick brown fox jumped-    over the lazy dog’s back.</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P29">Item 2.</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P29">Item 3.</text:p>-  </text:list-item>-</text:list>-<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="nested" />Nested<text:bookmark-end text:name="nested" /></text:h>-<text:list text:style-name="L13">-  <text:list-item>-    <text:p text:style-name="P30">Tab</text:p><text:list text:style-name="L14">-      <text:list-item>-        <text:p text:style-name="P31">Tab</text:p><text:list text:style-name="L15">-          <text:list-item>-            <text:p text:style-name="P32">Tab</text:p>-          </text:list-item>-        </text:list>-      </text:list-item>-    </text:list>-  </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">Here’s another:</text:p>-<text:list text:style-name="L16">-  <text:list-item>-    <text:p text:style-name="P33">First</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P33">Second:</text:p>-    <text:list text:style-name="L17">-      <text:list-item>-        <text:p text:style-name="P34">Fee</text:p>-      </text:list-item>-      <text:list-item>-        <text:p text:style-name="P34">Fie</text:p>-      </text:list-item>-      <text:list-item>-        <text:p text:style-name="P34">Foe</text:p>-      </text:list-item>-    </text:list>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P33">Third</text:p>-  </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">Same thing but with-paragraphs:</text:p>-<text:list text:style-name="L18">-  <text:list-item>-    <text:p text:style-name="P35">First</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P35">Second:</text:p>-    <text:list text:style-name="L19">-      <text:list-item>-        <text:p text:style-name="P36">Fee</text:p>-      </text:list-item>-      <text:list-item>-        <text:p text:style-name="P36">Fie</text:p>-      </text:list-item>-      <text:list-item>-        <text:p text:style-name="P36">Foe</text:p>-      </text:list-item>-    </text:list>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P35">Third</text:p>-  </text:list-item>-</text:list>-<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="tabs-and-spaces" />Tabs-and spaces<text:bookmark-end text:name="tabs-and-spaces" /></text:h>-<text:list text:style-name="L20">-  <text:list-item>-    <text:p text:style-name="P37">this is a list item indented with-    tabs</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P37">this is a list item indented with-    spaces</text:p><text:list text:style-name="L21">-      <text:list-item>-        <text:p text:style-name="P38">this is an example list item indented with-        tabs</text:p>-      </text:list-item>-      <text:list-item>-        <text:p text:style-name="P38">this is an example list item indented with-        spaces</text:p>-      </text:list-item>-    </text:list>-  </text:list-item>-</text:list>-<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="fancy-list-markers" />Fancy-list markers<text:bookmark-end text:name="fancy-list-markers" /></text:h>-<text:list text:style-name="L22">-  <text:list-item>-    <text:p text:style-name="P39">begins with 2</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P39">and now 3</text:p>-    <text:p text:style-name="P39">with a continuation</text:p>-    <text:list>-      <text:list-item>-        <text:p text:style-name="P39">sublist with roman numerals, starting with-        4</text:p>-      </text:list-item>-      <text:list-item>-        <text:p text:style-name="P39">more items</text:p>-        <text:list>-          <text:list-item>-            <text:p text:style-name="P39">a subsublist</text:p>-          </text:list-item>-          <text:list-item>-            <text:p text:style-name="P39">a subsublist</text:p>-          </text:list-item>-        </text:list>-      </text:list-item>-    </text:list>-  </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">Nesting:</text:p>-<text:list text:style-name="L23">-  <text:list-item>-    <text:p text:style-name="P40">Upper Alpha</text:p>-    <text:list>-      <text:list-item>-        <text:p text:style-name="P40">Upper Roman.</text:p>-        <text:list>-          <text:list-item>-            <text:p text:style-name="P40">Decimal start with 6</text:p>-            <text:list>-              <text:list-item>-                <text:p text:style-name="P40">Lower alpha with paren</text:p>-              </text:list-item>-            </text:list>-          </text:list-item>-        </text:list>-      </text:list-item>-    </text:list>-  </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">Autonumbering:</text:p>-<text:list text:style-name="L24">-  <text:list-item>-    <text:p text:style-name="P41">Autonumber.</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P41">More.</text:p>-    <text:list>-      <text:list-item>-        <text:p text:style-name="P41">Nested.</text:p>-      </text:list-item>-    </text:list>-  </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">Should not be a list item:</text:p>-<text:p text:style-name="Text_20_body">M.A. 2007</text:p>-<text:p text:style-name="Text_20_body">B. Williams</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="definition-lists" />Definition-Lists<text:bookmark-end text:name="definition-lists" /></text:h>-<text:p text:style-name="First_20_paragraph">Tight using spaces:</text:p>-<text:p text:style-name="Definition_20_Term_20_Tight">apple</text:p>-<text:p text:style-name="Definition_20_Definition_20_Tight">red fruit</text:p>-<text:p text:style-name="Definition_20_Term_20_Tight">orange</text:p>-<text:p text:style-name="Definition_20_Definition_20_Tight">orange-fruit</text:p>-<text:p text:style-name="Definition_20_Term_20_Tight">banana</text:p>-<text:p text:style-name="Definition_20_Definition_20_Tight">yellow-fruit</text:p>-<text:p text:style-name="First_20_paragraph">Tight using tabs:</text:p>-<text:p text:style-name="Definition_20_Term_20_Tight">apple</text:p>-<text:p text:style-name="Definition_20_Definition_20_Tight">red fruit</text:p>-<text:p text:style-name="Definition_20_Term_20_Tight">orange</text:p>-<text:p text:style-name="Definition_20_Definition_20_Tight">orange-fruit</text:p>-<text:p text:style-name="Definition_20_Term_20_Tight">banana</text:p>-<text:p text:style-name="Definition_20_Definition_20_Tight">yellow-fruit</text:p>-<text:p text:style-name="First_20_paragraph">Loose:</text:p>-<text:p text:style-name="Definition_20_Term">apple</text:p>-<text:p text:style-name="Definition_20_Definition">red fruit</text:p>-<text:p text:style-name="Definition_20_Term">orange</text:p>-<text:p text:style-name="Definition_20_Definition">orange fruit</text:p>-<text:p text:style-name="Definition_20_Term">banana</text:p>-<text:p text:style-name="Definition_20_Definition">yellow fruit</text:p>-<text:p text:style-name="First_20_paragraph">Multiple blocks with-italics:</text:p>-<text:p text:style-name="Definition_20_Term"><text:span text:style-name="T1">apple</text:span></text:p>-<text:p text:style-name="Definition_20_Definition">red-fruit</text:p><text:p text:style-name="Definition_20_Definition">contains seeds,-crisp, pleasant to taste</text:p>-<text:p text:style-name="Definition_20_Term"><text:span text:style-name="T1">orange</text:span></text:p>-<text:p text:style-name="Definition_20_Definition">orange-fruit</text:p><text:p text:style-name="P42">{ orange code block }</text:p><text:p text:style-name="P43">orange-block quote</text:p>-<text:p text:style-name="First_20_paragraph">Multiple definitions,-tight:</text:p>-<text:p text:style-name="Definition_20_Term_20_Tight">apple</text:p>-<text:p text:style-name="Definition_20_Definition_20_Tight">red fruit</text:p>-<text:p text:style-name="Definition_20_Definition_20_Tight">computer</text:p>-<text:p text:style-name="Definition_20_Term_20_Tight">orange</text:p>-<text:p text:style-name="Definition_20_Definition_20_Tight">orange-fruit</text:p>-<text:p text:style-name="Definition_20_Definition_20_Tight">bank</text:p>-<text:p text:style-name="First_20_paragraph">Multiple definitions,-loose:</text:p>-<text:p text:style-name="Definition_20_Term">apple</text:p>-<text:p text:style-name="Definition_20_Definition">red fruit</text:p>-<text:p text:style-name="Definition_20_Definition">computer</text:p>-<text:p text:style-name="Definition_20_Term">orange</text:p>-<text:p text:style-name="Definition_20_Definition">orange fruit</text:p>-<text:p text:style-name="Definition_20_Definition">bank</text:p>-<text:p text:style-name="First_20_paragraph">Blank line after term, indented-marker, alternate markers:</text:p>-<text:p text:style-name="Definition_20_Term">apple</text:p>-<text:p text:style-name="Definition_20_Definition">red fruit</text:p>-<text:p text:style-name="Definition_20_Definition">computer</text:p>-<text:p text:style-name="Definition_20_Term">orange</text:p>-<text:p text:style-name="Definition_20_Definition">orange-fruit</text:p><text:list text:style-name="L25">-  <text:list-item>-    <text:p text:style-name="P44">sublist</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P44">sublist</text:p>-  </text:list-item>-</text:list>-<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="html-blocks" />HTML-Blocks<text:bookmark-end text:name="html-blocks" /></text:h>-<text:p text:style-name="First_20_paragraph">Simple block on one line:</text:p>-<text:p text:style-name="Text_20_body">foo</text:p>-<text:p text:style-name="Text_20_body">And nested without indentation:</text:p>-<text:p text:style-name="Text_20_body">foo</text:p>-<text:p text:style-name="Text_20_body">bar</text:p>-<text:p text:style-name="Text_20_body">Interpreted markdown in a table:</text:p>-<text:p text:style-name="Text_20_body">This is-<text:span text:style-name="T1">emphasized</text:span></text:p>-<text:p text:style-name="Text_20_body">And this is-<text:span text:style-name="T2">strong</text:span></text:p>-<text:p text:style-name="Text_20_body">Here’s a simple block:</text:p>-<text:p text:style-name="Text_20_body">foo</text:p>-<text:p text:style-name="Text_20_body">This should be a code block,-though:</text:p>-<text:p text:style-name="P45">&lt;div&gt;</text:p>-<text:p text:style-name="P46"><text:s text:c="4" />foo</text:p>-<text:p text:style-name="P47">&lt;/div&gt;</text:p>-<text:p text:style-name="First_20_paragraph">As should this:</text:p>-<text:p text:style-name="P48">&lt;div&gt;foo&lt;/div&gt;</text:p>-<text:p text:style-name="First_20_paragraph">Now, nested:</text:p>-<text:p text:style-name="Text_20_body">foo</text:p>-<text:p text:style-name="Text_20_body">This should just be an HTML-comment:</text:p>-<text:p text:style-name="Text_20_body">Multiline:</text:p>-<text:p text:style-name="Text_20_body">Code block:</text:p>-<text:p text:style-name="P49">&lt;!-- Comment --&gt;</text:p>-<text:p text:style-name="First_20_paragraph">Just plain comment, with trailing-spaces on the line:</text:p>-<text:p text:style-name="Text_20_body">Code:</text:p>-<text:p text:style-name="P50">&lt;hr /&gt;</text:p>-<text:p text:style-name="First_20_paragraph">Hr’s:</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="inline-markup" />Inline-Markup<text:bookmark-end text:name="inline-markup" /></text:h>-<text:p text:style-name="First_20_paragraph">This is-<text:span text:style-name="T1">emphasized</text:span>, and so-<text:span text:style-name="T1">is this</text:span>.</text:p>-<text:p text:style-name="Text_20_body">This is-<text:span text:style-name="T2">strong</text:span>, and so-<text:span text:style-name="T2">is this</text:span>.</text:p>-<text:p text:style-name="Text_20_body">An-<text:a xlink:type="simple" xlink:href="/url" office:name=""><text:span text:style-name="Definition"><text:span text:style-name="T1">emphasized-link</text:span></text:span></text:a>.</text:p>-<text:p text:style-name="Text_20_body"><text:span text:style-name="T3">This is-strong and em.</text:span></text:p>-<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"><text:span text:style-name="T3">This is-strong and em.</text:span></text:p>-<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: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:-a<text:span text:style-name="T6">bc</text:span>d-a<text:span text:style-name="T7">hello</text:span>-a<text:span text:style-name="T6">hello there</text:span>.</text:p>-<text:p text:style-name="Text_20_body">Subscripts:-H<text:span text:style-name="T8">2</text:span>O,-H<text:span text:style-name="T8">23</text:span>O,-H<text:span text:style-name="T8">many of them</text:span>O.</text:p>-<text:p text:style-name="Text_20_body">These should not be superscripts or-subscripts, because of the unescaped spaces: a^b c^d, a~b c~d.</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="smart-quotes-ellipses-dashes" />Smart-quotes, ellipses,-dashes<text:bookmark-end text:name="smart-quotes-ellipses-dashes" /></text:h>-<text:p text:style-name="First_20_paragraph">“Hello,” said the spider. “‘Shelob’-is my name.”</text:p>-<text:p text:style-name="Text_20_body">‘A’, ‘B’, and ‘C’ are letters.</text:p>-<text:p text:style-name="Text_20_body">‘Oak,’ ‘elm,’ and ‘beech’ are names of-trees. So is ‘pine.’</text:p>-<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: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 —-five.</text:p>-<text:p text:style-name="Text_20_body">Dashes between numbers: 5–7, 255–66,-1987–1999.</text:p>-<text:p text:style-name="Text_20_body">Ellipses…and…and….</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="latex" />LaTeX<text:bookmark-end text:name="latex" /></text:h>-<text:list text:style-name="L26">-  <text:list-item>-    <text:p text:style-name="P51"></text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P51">2 + 2 = 4</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P51"><text:span text:style-name="T1">x</text:span> ∈ <text:span text:style-name="T1">y</text:span></text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P51"><text:span text:style-name="T1">α</text:span> ∧ <text:span text:style-name="T1">ω</text:span></text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P51">223</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P51"><text:span text:style-name="T1">p</text:span>-Tree</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P51">Here’s some display math:-    $$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P51">Here’s one that has a line break in it:-    <text:span text:style-name="T1">α</text:span> + <text:span text:style-name="T1">ω</text:span> × <text:span text:style-name="T1">x</text:span><text:span text:style-name="T6">2</text:span>.</text:p>-  </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">These shouldn’t be math:</text:p>-<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:list-item>-  <text:list-item>-    <text:p text:style-name="P52">$22,000 is a-    <text:span text:style-name="T1">lot</text:span> of money. So is $34,000. (It-    worked if “lot” is emphasized.)</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P52">Shoes ($20) and socks ($5).</text:p>-  </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="T1">this should be emphasized</text:span>-    23$.</text:p>-  </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">Here’s a LaTeX table:</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="special-characters" />Special-Characters<text:bookmark-end text:name="special-characters" /></text:h>-<text:p text:style-name="First_20_paragraph">Here is some unicode:</text:p>-<text:list text:style-name="L28">-  <text:list-item>-    <text:p text:style-name="P53">I hat: Î</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P53">o umlaut: ö</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P53">section: §</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P53">set membership: ∈</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P53">copyright: ©</text:p>-  </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">AT&amp;T has an ampersand in their-name.</text:p>-<text:p text:style-name="Text_20_body">AT&amp;T is another way to write-it.</text:p>-<text:p text:style-name="Text_20_body">This &amp; that.</text:p>-<text:p text:style-name="Text_20_body">4 &lt; 5.</text:p>-<text:p text:style-name="Text_20_body">6 &gt; 5.</text:p>-<text:p text:style-name="Text_20_body">Backslash: \</text:p>-<text:p text:style-name="Text_20_body">Backtick: `</text:p>-<text:p text:style-name="Text_20_body">Asterisk: *</text:p>-<text:p text:style-name="Text_20_body">Underscore: _</text:p>-<text:p text:style-name="Text_20_body">Left brace: {</text:p>-<text:p text:style-name="Text_20_body">Right brace: }</text:p>-<text:p text:style-name="Text_20_body">Left bracket: [</text:p>-<text:p text:style-name="Text_20_body">Right bracket: ]</text:p>-<text:p text:style-name="Text_20_body">Left paren: (</text:p>-<text:p text:style-name="Text_20_body">Right paren: )</text:p>-<text:p text:style-name="Text_20_body">Greater-than: &gt;</text:p>-<text:p text:style-name="Text_20_body">Hash: #</text:p>-<text:p text:style-name="Text_20_body">Period: .</text:p>-<text:p text:style-name="Text_20_body">Bang: !</text:p>-<text:p text:style-name="Text_20_body">Plus: +</text:p>-<text:p text:style-name="Text_20_body">Minus: -</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="links" />Links<text:bookmark-end text:name="links" /></text:h>-<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="explicit" />Explicit<text:bookmark-end text:name="explicit" /></text:h>-<text:p text:style-name="First_20_paragraph">Just a-<text:a xlink:type="simple" xlink:href="/url/" office:name=""><text:span text:style-name="Definition">URL</text:span></text:a>.</text:p>-<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="/url/" office:name="title"><text:span text:style-name="Definition">URL-and title</text:span></text:a>.</text:p>-<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="/url/" office:name="title preceded by two spaces"><text:span text:style-name="Definition">URL-and title</text:span></text:a>.</text:p>-<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="/url/" office:name="title preceded by a tab"><text:span text:style-name="Definition">URL-and title</text:span></text:a>.</text:p>-<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="/url/" office:name="title with &quot;quotes&quot; in it"><text:span text:style-name="Definition">URL-and title</text:span></text:a></text:p>-<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="/url/" office:name="title with single quotes"><text:span text:style-name="Definition">URL-and title</text:span></text:a></text:p>-<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="/url/with_underscore" office:name=""><text:span text:style-name="Definition">with_underscore</text:span></text:a></text:p>-<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="mailto:nobody@nowhere.net" office:name=""><text:span text:style-name="Definition">Email-link</text:span></text:a></text:p>-<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="" office:name=""><text:span text:style-name="Definition">Empty</text:span></text:a>.</text:p>-<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="reference" />Reference<text:bookmark-end text:name="reference" /></text:h>-<text:p text:style-name="First_20_paragraph">Foo-<text:a xlink:type="simple" xlink:href="/url/" office:name=""><text:span text:style-name="Definition">bar</text:span></text:a>.</text:p>-<text:p text:style-name="Text_20_body">With-<text:a xlink:type="simple" xlink:href="/url/" office:name=""><text:span text:style-name="Definition">embedded-[brackets]</text:span></text:a>.</text:p>-<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="/url/" office:name=""><text:span text:style-name="Definition">b</text:span></text:a>-by itself should be a link.</text:p>-<text:p text:style-name="Text_20_body">Indented-<text:a xlink:type="simple" xlink:href="/url" office:name=""><text:span text:style-name="Definition">once</text:span></text:a>.</text:p>-<text:p text:style-name="Text_20_body">Indented-<text:a xlink:type="simple" xlink:href="/url" office:name=""><text:span text:style-name="Definition">twice</text:span></text:a>.</text:p>-<text:p text:style-name="Text_20_body">Indented-<text:a xlink:type="simple" xlink:href="/url" office:name=""><text:span text:style-name="Definition">thrice</text:span></text:a>.</text:p>-<text:p text:style-name="Text_20_body">This should [not][] be a link.</text:p>-<text:p text:style-name="P54">[not]: /url</text:p>-<text:p text:style-name="First_20_paragraph">Foo-<text:a xlink:type="simple" xlink:href="/url/" office:name="Title with &quot;quotes&quot; inside"><text:span text:style-name="Definition">bar</text:span></text:a>.</text:p>-<text:p text:style-name="Text_20_body">Foo-<text:a xlink:type="simple" xlink:href="/url/" office:name="Title with &quot;quote&quot; inside"><text:span text:style-name="Definition">biz</text:span></text:a>.</text:p>-<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="with-ampersands" />With-ampersands<text:bookmark-end text:name="with-ampersands" /></text:h>-<text:p text:style-name="First_20_paragraph">Here’s a-<text:a xlink:type="simple" xlink:href="http://example.com/?foo=1&amp;bar=2" office:name=""><text:span text:style-name="Definition">link-with an ampersand in the URL</text:span></text:a>.</text:p>-<text:p text:style-name="Text_20_body">Here’s a link with an amersand in the-link text:-<text:a xlink:type="simple" xlink:href="http://att.com/" office:name="AT&amp;T"><text:span text:style-name="Definition">AT&amp;T</text:span></text:a>.</text:p>-<text:p text:style-name="Text_20_body">Here’s an-<text:a xlink:type="simple" xlink:href="/script?foo=1&amp;bar=2" office:name=""><text:span text:style-name="Definition">inline-link</text:span></text:a>.</text:p>-<text:p text:style-name="Text_20_body">Here’s an-<text:a xlink:type="simple" xlink:href="/script?foo=1&amp;bar=2" office:name=""><text:span text:style-name="Definition">inline-link in pointy braces</text:span></text:a>.</text:p>-<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="autolinks" />Autolinks<text:bookmark-end text:name="autolinks" /></text:h>-<text:p text:style-name="First_20_paragraph">With an ampersand:-<text:a xlink:type="simple" xlink:href="http://example.com/?foo=1&amp;bar=2" office:name=""><text:span text:style-name="Definition">http://example.com/?foo=1&amp;bar=2</text:span></text:a></text:p>-<text:list text:style-name="L29">-  <text:list-item>-    <text:p text:style-name="P55">In a list?</text:p>-  </text:list-item>-  <text:list-item>-    <text:p text:style-name="P55"><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:list-item>-  <text:list-item>-    <text:p text:style-name="P55">It should.</text:p>-  </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">An e-mail address:-<text:a xlink:type="simple" xlink:href="mailto:nobody@nowhere.net" office:name=""><text:span text:style-name="Definition">nobody@nowhere.net</text:span></text:a></text:p>-<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: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>-<text:p text:style-name="First_20_paragraph">From “Voyage dans la Lune” by-Georges Melies (1902):</text:p>-<text:p text:style-name="FigureWithCaption"><draw:frame draw:name="img1"><draw:image xlink:href="lalune.jpg" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad" /></draw:frame></text:p>-<text:p text:style-name="FigureCaption">lalune</text:p>-<text:p text:style-name="Text_20_body">Here is a movie-<draw:frame draw:name="img2"><draw:image xlink:href="movie.jpg" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad" /></draw:frame>-icon.</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="footnotes" />Footnotes<text:bookmark-end text:name="footnotes" /></text:h>-<text:p text:style-name="First_20_paragraph">Here is a footnote-reference,<text:note text:id="ftn0" text:note-class="footnote"><text:note-citation>1</text:note-citation><text:note-body><text:p text:style-name="Footnote">Here-is the footnote. It can go anywhere after the footnote reference. It need not be-placed at the end of the document.</text:p></text:note-body></text:note> and-another.<text:note text:id="ftn1" text:note-class="footnote"><text:note-citation>2</text:note-citation><text:note-body><text:p text:style-name="Footnote">Here’s-the long note. This one contains multiple-blocks.</text:p><text:p text:style-name="Footnote">Subsequent blocks are-indented to show that they belong to the footnote (as with list-items).</text:p><text:p text:style-name="P58"><text:s text:c="2" />{ &lt;code&gt; }</text:p><text:p text:style-name="Footnote">If-you want, you can indent every line, but you can also be lazy and just indent-the first line of each block.</text:p></text:note-body></text:note> This should-<text:span text:style-name="T1">not</text:span> be a footnote reference, because-it contains a space.[^my note] Here is an inline-note.<text:note text:id="ftn2" text:note-class="footnote"><text:note-citation>3</text:note-citation><text:note-body><text:p text:style-name="Footnote">This-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>-<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>-<text:list text:style-name="L30">-  <text:list-item>-    <text:p text:style-name="P60">And in list+    <style:style style:name="T1" style:family="text"><style:text-properties fo:font-style="italic" fo:font-weight="bold" style:font-style-asian="italic" style:font-style-complex="italic" style:font-weight-asian="bold" style:font-weight-complex="bold" /></style:style>+    <style:style style:name="T2" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" style:text-line-through-style="solid" /></style:style>+    <style:style style:name="T3" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" style:text-position="super 58%" /></style:style>+    <style:style style:name="fr2" style:family="graphic" style:parent-style-name="Formula"><style:graphic-properties style:vertical-pos="middle" style:vertical-rel="text" style:horizontal-pos="center" style:horizontal-rel="paragraph-content" style:wrap="none" /></style:style>+    <style:style style:name="fr1" style:family="graphic" style:parent-style-name="Formula"><style:graphic-properties style:vertical-pos="middle" style:vertical-rel="text" /></style:style>+    <style:style style:name="P1" style:family="paragraph" style:parent-style-name="Quotations">+      <style:paragraph-properties fo:margin-left="0.5in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" />+    </style:style>+    <style:style style:name="P2" style:family="paragraph" style:parent-style-name="Quotations">+      <style:paragraph-properties fo:margin-left="0.5in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" />+    </style:style>+    <style:style style:name="P3" style:family="paragraph" style:parent-style-name="Quotations">+      <style:paragraph-properties fo:margin-left="0.5in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" />+    </style:style>+    <text:list-style style:name="Pandoc_5f_Numbering_5f_1">+      <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" style:num-prefix="(" style:num-suffix=")">+        <style:list-level-properties text:space-before="0.0000in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="2" text:style-name="Numbering_20_Symbols" style:num-format="1" style:num-prefix="(" style:num-suffix=")">+        <style:list-level-properties text:space-before="0.1972in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="3" text:style-name="Numbering_20_Symbols" style:num-format="1" style:num-prefix="(" style:num-suffix=")">+        <style:list-level-properties text:space-before="0.3944in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="4" text:style-name="Numbering_20_Symbols" style:num-format="1" style:num-prefix="(" style:num-suffix=")">+        <style:list-level-properties text:space-before="0.5916in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="5" text:style-name="Numbering_20_Symbols" style:num-format="1" style:num-prefix="(" style:num-suffix=")">+        <style:list-level-properties text:space-before="0.7888in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="6" text:style-name="Numbering_20_Symbols" style:num-format="1" style:num-prefix="(" style:num-suffix=")">+        <style:list-level-properties text:space-before="0.9860in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="7" text:style-name="Numbering_20_Symbols" style:num-format="1" style:num-prefix="(" style:num-suffix=")">+        <style:list-level-properties text:space-before="1.1832in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="8" text:style-name="Numbering_20_Symbols" style:num-format="1" style:num-prefix="(" style:num-suffix=")">+        <style:list-level-properties text:space-before="1.3804in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="9" text:style-name="Numbering_20_Symbols" style:num-format="1" style:num-prefix="(" style:num-suffix=")">+        <style:list-level-properties text:space-before="1.5776in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="10" text:style-name="Numbering_20_Symbols" style:num-format="1" style:num-prefix="(" style:num-suffix=")">+        <style:list-level-properties text:space-before="1.7748in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+    </text:list-style>+    <text:list-style style:name="Pandoc_5f_Numbering_5f_2">+      <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="i" style:num-suffix=".">+        <style:list-level-properties text:space-before="0.0000in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="2" text:style-name="Numbering_20_Symbols" style:num-format="i" style:num-suffix=".">+        <style:list-level-properties text:space-before="0.1972in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="3" text:style-name="Numbering_20_Symbols" style:num-format="i" style:num-suffix=".">+        <style:list-level-properties text:space-before="0.3944in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="4" text:style-name="Numbering_20_Symbols" style:num-format="i" style:num-suffix=".">+        <style:list-level-properties text:space-before="0.5916in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="5" text:style-name="Numbering_20_Symbols" style:num-format="i" style:num-suffix=".">+        <style:list-level-properties text:space-before="0.7888in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="6" text:style-name="Numbering_20_Symbols" style:num-format="i" style:num-suffix=".">+        <style:list-level-properties text:space-before="0.9860in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="7" text:style-name="Numbering_20_Symbols" style:num-format="i" style:num-suffix=".">+        <style:list-level-properties text:space-before="1.1832in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="8" text:style-name="Numbering_20_Symbols" style:num-format="i" style:num-suffix=".">+        <style:list-level-properties text:space-before="1.3804in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="9" text:style-name="Numbering_20_Symbols" style:num-format="i" style:num-suffix=".">+        <style:list-level-properties text:space-before="1.5776in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="10" text:style-name="Numbering_20_Symbols" style:num-format="i" style:num-suffix=".">+        <style:list-level-properties text:space-before="1.7748in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+    </text:list-style>+    <text:list-style style:name="Pandoc_5f_Numbering_5f_5">+      <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="I" style:num-suffix=".">+        <style:list-level-properties text:space-before="0.0000in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="2" text:style-name="Numbering_20_Symbols" style:num-format="I" style:num-suffix=".">+        <style:list-level-properties text:space-before="0.1972in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="3" text:style-name="Numbering_20_Symbols" style:num-format="I" style:num-suffix=".">+        <style:list-level-properties text:space-before="0.3944in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="4" text:style-name="Numbering_20_Symbols" style:num-format="I" style:num-suffix=".">+        <style:list-level-properties text:space-before="0.5916in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="5" text:style-name="Numbering_20_Symbols" style:num-format="I" style:num-suffix=".">+        <style:list-level-properties text:space-before="0.7888in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="6" text:style-name="Numbering_20_Symbols" style:num-format="I" style:num-suffix=".">+        <style:list-level-properties text:space-before="0.9860in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="7" text:style-name="Numbering_20_Symbols" style:num-format="I" style:num-suffix=".">+        <style:list-level-properties text:space-before="1.1832in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="8" text:style-name="Numbering_20_Symbols" style:num-format="I" style:num-suffix=".">+        <style:list-level-properties text:space-before="1.3804in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="9" text:style-name="Numbering_20_Symbols" style:num-format="I" style:num-suffix=".">+        <style:list-level-properties text:space-before="1.5776in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="10" text:style-name="Numbering_20_Symbols" style:num-format="I" style:num-suffix=".">+        <style:list-level-properties text:space-before="1.7748in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+    </text:list-style>+    <text:list-style style:name="Pandoc_5f_Numbering_5f_6">+      <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="a" style:num-suffix=")">+        <style:list-level-properties text:space-before="0.0000in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="2" text:style-name="Numbering_20_Symbols" style:num-format="a" style:num-suffix=")">+        <style:list-level-properties text:space-before="0.1972in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="3" text:style-name="Numbering_20_Symbols" style:num-format="a" style:num-suffix=")">+        <style:list-level-properties text:space-before="0.3944in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="4" text:style-name="Numbering_20_Symbols" style:num-format="a" style:num-suffix=")">+        <style:list-level-properties text:space-before="0.5916in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="5" text:style-name="Numbering_20_Symbols" style:num-format="a" style:num-suffix=")">+        <style:list-level-properties text:space-before="0.7888in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="6" text:style-name="Numbering_20_Symbols" style:num-format="a" style:num-suffix=")">+        <style:list-level-properties text:space-before="0.9860in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="7" text:style-name="Numbering_20_Symbols" style:num-format="a" style:num-suffix=")">+        <style:list-level-properties text:space-before="1.1832in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="8" text:style-name="Numbering_20_Symbols" style:num-format="a" style:num-suffix=")">+        <style:list-level-properties text:space-before="1.3804in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="9" text:style-name="Numbering_20_Symbols" style:num-format="a" style:num-suffix=")">+        <style:list-level-properties text:space-before="1.5776in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="10" text:style-name="Numbering_20_Symbols" style:num-format="a" style:num-suffix=")">+        <style:list-level-properties text:space-before="1.7748in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+    </text:list-style>+    <text:list-style style:name="Pandoc_5f_Numbering_5f_4">+      <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-suffix=".">+        <style:list-level-properties text:space-before="0.0000in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="2" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-suffix=".">+        <style:list-level-properties text:space-before="0.1972in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="3" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-suffix=".">+        <style:list-level-properties text:space-before="0.3944in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="4" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-suffix=".">+        <style:list-level-properties text:space-before="0.5916in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="5" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-suffix=".">+        <style:list-level-properties text:space-before="0.7888in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="6" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-suffix=".">+        <style:list-level-properties text:space-before="0.9860in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="7" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-suffix=".">+        <style:list-level-properties text:space-before="1.1832in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="8" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-suffix=".">+        <style:list-level-properties text:space-before="1.3804in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="9" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-suffix=".">+        <style:list-level-properties text:space-before="1.5776in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="10" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-suffix=".">+        <style:list-level-properties text:space-before="1.7748in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+    </text:list-style>+    <text:list-style style:name="Pandoc_5f_Numbering_5f_3">+      <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-prefix="(" style:num-suffix=")">+        <style:list-level-properties text:space-before="0.0000in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="2" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-prefix="(" style:num-suffix=")">+        <style:list-level-properties text:space-before="0.1972in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="3" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-prefix="(" style:num-suffix=")">+        <style:list-level-properties text:space-before="0.3944in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="4" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-prefix="(" style:num-suffix=")">+        <style:list-level-properties text:space-before="0.5916in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="5" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-prefix="(" style:num-suffix=")">+        <style:list-level-properties text:space-before="0.7888in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="6" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-prefix="(" style:num-suffix=")">+        <style:list-level-properties text:space-before="0.9860in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="7" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-prefix="(" style:num-suffix=")">+        <style:list-level-properties text:space-before="1.1832in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="8" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-prefix="(" style:num-suffix=")">+        <style:list-level-properties text:space-before="1.3804in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="9" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-prefix="(" style:num-suffix=")">+        <style:list-level-properties text:space-before="1.5776in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+      <text:list-level-style-number text:level="10" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-prefix="(" style:num-suffix=")">+        <style:list-level-properties text:space-before="1.7748in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+      </text:list-level-style-number>+    </text:list-style>+  </office:automatic-styles>+<office:body>+<office:text>+<text:p text:style-name="Title">Pandoc Test Suite</text:p>+<text:p text:style-name="Author">John MacFarlane</text:p>+<text:p text:style-name="Author">Anonymous</text:p>+<text:p text:style-name="Date">July 17, 2006</text:p>+<text:p text:style-name="Text_20_body">This is a set of tests for pandoc. Most+of them are adapted from John Gruber’s markdown test suite.</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="headers" />Headers<text:bookmark-end text:name="headers" /></text:h>+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="level-2-with-an-embedded-link" />Level+2 with an+<text:a xlink:type="simple" xlink:href="/url" office:name=""><text:span text:style-name="Definition">embedded+link</text:span></text:a><text:bookmark-end text:name="level-2-with-an-embedded-link" /></text:h>+<text:h text:style-name="Heading_20_3" text:outline-level="3"><text:bookmark-start text:name="level-3-with-emphasis" />Level+3 with+<text:span text:style-name="Emphasis">emphasis</text:span><text:bookmark-end text:name="level-3-with-emphasis" /></text:h>+<text:h text:style-name="Heading_20_4" text:outline-level="4"><text:bookmark-start text:name="level-4" />Level+4<text:bookmark-end text:name="level-4" /></text:h>+<text:h text:style-name="Heading_20_5" text:outline-level="5"><text:bookmark-start text:name="level-5" />Level+5<text:bookmark-end text:name="level-5" /></text:h>+<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="level-1" />Level+1<text:bookmark-end text:name="level-1" /></text:h>+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="level-2-with-emphasis" />Level+2 with+<text:span text:style-name="Emphasis">emphasis</text:span><text:bookmark-end text:name="level-2-with-emphasis" /></text:h>+<text:h text:style-name="Heading_20_3" text:outline-level="3"><text:bookmark-start text:name="level-3" />Level+3<text:bookmark-end text:name="level-3" /></text:h>+<text:p text:style-name="First_20_paragraph">with no blank line</text:p>+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="level-2" />Level+2<text:bookmark-end text:name="level-2" /></text:h>+<text:p text:style-name="First_20_paragraph">with no blank line</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="paragraphs" />Paragraphs<text:bookmark-end text:name="paragraphs" /></text:h>+<text:p text:style-name="First_20_paragraph">Here’s a regular+paragraph.</text:p>+<text:p text:style-name="Text_20_body">In Markdown 1.0.0 and earlier. Version 8.+This line turns into a list item. Because a hard-wrapped line in the middle of a+paragraph looked like a list item.</text:p>+<text:p text:style-name="Text_20_body">Here’s one with a bullet. *+criminey.</text:p>+<text:p text:style-name="Text_20_body">There should be a hard line+break<text:line-break />here.</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="block-quotes" />Block+Quotes<text:bookmark-end text:name="block-quotes" /></text:h>+<text:p text:style-name="First_20_paragraph">E-mail style:</text:p>+<text:p text:style-name="Quotations">This is a block quote. It is pretty+short.</text:p>+<text:p text:style-name="Quotations">Code in a block quote:</text:p>+<text:p text:style-name="Preformatted_20_Text">sub status {</text:p>+<text:p text:style-name="Preformatted_20_Text"><text:s text:c="4" />print &quot;working&quot;;</text:p>+<text:p text:style-name="Preformatted_20_Text">}</text:p>+<text:p text:style-name="Quotations">A list:</text:p>+<text:list text:style-name="Numbering_20_1">+  <text:list-item>+    <text:p text:style-name="List_20_Number_20_Tight">item one</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Number_20_Tight">item two</text:p>+  </text:list-item>+</text:list>+<text:p text:style-name="Quotations">Nested block quotes:</text:p>+<text:p text:style-name="P1">nested</text:p>+<text:p text:style-name="P2">nested</text:p>+<text:p text:style-name="First_20_paragraph">This should not be a block quote: 2+&gt; 1.</text:p>+<text:p text:style-name="Text_20_body">And a following paragraph.</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="code-blocks" />Code+Blocks<text:bookmark-end text:name="code-blocks" /></text:h>+<text:p text:style-name="First_20_paragraph">Code:</text:p>+<text:p text:style-name="Preformatted_20_Text">---- (should be four hyphens)</text:p>+<text:p text:style-name="Preformatted_20_Text"></text:p>+<text:p text:style-name="Preformatted_20_Text">sub status {</text:p>+<text:p text:style-name="Preformatted_20_Text"><text:s text:c="4" />print &quot;working&quot;;</text:p>+<text:p text:style-name="Preformatted_20_Text">}</text:p>+<text:p text:style-name="Preformatted_20_Text"></text:p>+<text:p text:style-name="Preformatted_20_Text">this code block is indented by one tab</text:p>+<text:p text:style-name="First_20_paragraph">And:</text:p>+<text:p text:style-name="Preformatted_20_Text"><text:s text:c="4" />this code block is indented by two tabs</text:p>+<text:p text:style-name="Preformatted_20_Text"></text:p>+<text:p text:style-name="Preformatted_20_Text">These should not be escaped: <text:s text:c="1" />\$ \\ \&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="lists" />Lists<text:bookmark-end text:name="lists" /></text:h>+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="unordered" />Unordered<text:bookmark-end text:name="unordered" /></text:h>+<text:p text:style-name="First_20_paragraph">Asterisks tight:</text:p>+<text:list text:style-name="List_20_1">+  <text:list-item>+    <text:p text:style-name="List_20_Bullet_20_Tight">asterisk 1</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Bullet_20_Tight">asterisk 2</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Bullet_20_Tight">asterisk 3</text:p>+  </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">Asterisks loose:</text:p>+<text:list text:style-name="List_20_1">+  <text:list-item>+    <text:p text:style-name="List_20_Bullet">asterisk 1</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Bullet">asterisk 2</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Bullet">asterisk 3</text:p>+  </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">Pluses tight:</text:p>+<text:list text:style-name="List_20_1">+  <text:list-item>+    <text:p text:style-name="List_20_Bullet_20_Tight">Plus 1</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Bullet_20_Tight">Plus 2</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Bullet_20_Tight">Plus 3</text:p>+  </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">Pluses loose:</text:p>+<text:list text:style-name="List_20_1">+  <text:list-item>+    <text:p text:style-name="List_20_Bullet">Plus 1</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Bullet">Plus 2</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Bullet">Plus 3</text:p>+  </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">Minuses tight:</text:p>+<text:list text:style-name="List_20_1">+  <text:list-item>+    <text:p text:style-name="List_20_Bullet_20_Tight">Minus 1</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Bullet_20_Tight">Minus 2</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Bullet_20_Tight">Minus 3</text:p>+  </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">Minuses loose:</text:p>+<text:list text:style-name="List_20_1">+  <text:list-item>+    <text:p text:style-name="List_20_Bullet">Minus 1</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Bullet">Minus 2</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Bullet">Minus 3</text:p>+  </text:list-item>+</text:list>+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="ordered" />Ordered<text:bookmark-end text:name="ordered" /></text:h>+<text:p text:style-name="First_20_paragraph">Tight:</text:p>+<text:list text:style-name="Numbering_20_1">+  <text:list-item>+    <text:p text:style-name="List_20_Number_20_Tight">First</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Number_20_Tight">Second</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Number_20_Tight">Third</text:p>+  </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">and:</text:p>+<text:list text:style-name="Numbering_20_1">+  <text:list-item>+    <text:p text:style-name="List_20_Number_20_Tight">One</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Number_20_Tight">Two</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Number_20_Tight">Three</text:p>+  </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">Loose using tabs:</text:p>+<text:list text:style-name="Numbering_20_1">+  <text:list-item>+    <text:p text:style-name="List_20_Number">First</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Number">Second</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Number">Third</text:p>+  </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">and using spaces:</text:p>+<text:list text:style-name="Numbering_20_1">+  <text:list-item>+    <text:p text:style-name="List_20_Number">One</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Number">Two</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Number">Three</text:p>+  </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">Multiple paragraphs:</text:p>+<text:list text:style-name="Numbering_20_1">+  <text:list-item>+    <text:p text:style-name="List_20_Number">Item 1, graf one.</text:p>+    <text:p text:style-name="List_20_Number">Item 1. graf two. The quick brown+    fox jumped over the lazy dog’s back.</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Number">Item 2.</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Number">Item 3.</text:p>+  </text:list-item>+</text:list>+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="nested" />Nested<text:bookmark-end text:name="nested" /></text:h>+<text:list text:style-name="List_20_1">+  <text:list-item>+    <text:p text:style-name="List_20_Bullet_20_Tight">Tab</text:p><text:list text:style-name="List_20_1">+      <text:list-item>+        <text:p text:style-name="List_20_Bullet_20_Tight">Tab</text:p><text:list text:style-name="List_20_1">+          <text:list-item>+            <text:p text:style-name="List_20_Bullet_20_Tight">Tab</text:p>+          </text:list-item>+        </text:list>+      </text:list-item>+    </text:list>+  </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">Here’s another:</text:p>+<text:list text:style-name="Numbering_20_1">+  <text:list-item>+    <text:p text:style-name="List_20_Number_20_Tight">First</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Number_20_Tight">Second:</text:p>+    <text:list text:style-name="List_20_1">+      <text:list-item>+        <text:p text:style-name="List_20_Bullet_20_Tight">Fee</text:p>+      </text:list-item>+      <text:list-item>+        <text:p text:style-name="List_20_Bullet_20_Tight">Fie</text:p>+      </text:list-item>+      <text:list-item>+        <text:p text:style-name="List_20_Bullet_20_Tight">Foe</text:p>+      </text:list-item>+    </text:list>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Number_20_Tight">Third</text:p>+  </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">Same thing but with+paragraphs:</text:p>+<text:list text:style-name="Numbering_20_1">+  <text:list-item>+    <text:p text:style-name="List_20_Number">First</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Number">Second:</text:p>+    <text:list text:style-name="List_20_1">+      <text:list-item>+        <text:p text:style-name="List_20_Bullet_20_Tight">Fee</text:p>+      </text:list-item>+      <text:list-item>+        <text:p text:style-name="List_20_Bullet_20_Tight">Fie</text:p>+      </text:list-item>+      <text:list-item>+        <text:p text:style-name="List_20_Bullet_20_Tight">Foe</text:p>+      </text:list-item>+    </text:list>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Number">Third</text:p>+  </text:list-item>+</text:list>+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="tabs-and-spaces" />Tabs+and spaces<text:bookmark-end text:name="tabs-and-spaces" /></text:h>+<text:list text:style-name="List_20_1">+  <text:list-item>+    <text:p text:style-name="List_20_Bullet">this is a list item indented with+    tabs</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Bullet">this is a list item indented with+    spaces</text:p><text:list text:style-name="List_20_1">+      <text:list-item>+        <text:p text:style-name="List_20_Bullet">this is an example list item+        indented with tabs</text:p>+      </text:list-item>+      <text:list-item>+        <text:p text:style-name="List_20_Bullet">this is an example list item+        indented with spaces</text:p>+      </text:list-item>+    </text:list>+  </text:list-item>+</text:list>+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="fancy-list-markers" />Fancy+list markers<text:bookmark-end text:name="fancy-list-markers" /></text:h>+<text:list text:style-name="Pandoc_5f_Numbering_5f_1" text:start-value="2">+  <text:list-item>+    <text:p text:style-name="List_20_Number">begins with 2</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Number">and now 3</text:p>+    <text:p text:style-name="List_20_Number">with a continuation</text:p>+    <text:list text:style-name="Pandoc_5f_Numbering_5f_2" text:start-value="4">+      <text:list-item>+        <text:p text:style-name="List_20_Number_20_Tight">sublist with roman+        numerals, starting with 4</text:p>+      </text:list-item>+      <text:list-item>+        <text:p text:style-name="List_20_Number_20_Tight">more items</text:p>+        <text:list text:style-name="Pandoc_5f_Numbering_5f_3">+          <text:list-item>+            <text:p text:style-name="List_20_Number_20_Tight">a+            subsublist</text:p>+          </text:list-item>+          <text:list-item>+            <text:p text:style-name="List_20_Number_20_Tight">a+            subsublist</text:p>+          </text:list-item>+        </text:list>+      </text:list-item>+    </text:list>+  </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">Nesting:</text:p>+<text:list text:style-name="Pandoc_5f_Numbering_5f_4">+  <text:list-item>+    <text:p text:style-name="List_20_Number_20_Tight">Upper Alpha</text:p>+    <text:list text:style-name="Pandoc_5f_Numbering_5f_5">+      <text:list-item>+        <text:p text:style-name="List_20_Number_20_Tight">Upper Roman.</text:p>+        <text:list text:style-name="Pandoc_5f_Numbering_5f_1" text:start-value="6">+          <text:list-item>+            <text:p text:style-name="List_20_Number_20_Tight">Decimal start with+            6</text:p>+            <text:list text:style-name="Pandoc_5f_Numbering_5f_6" text:start-value="3">+              <text:list-item>+                <text:p text:style-name="List_20_Number_20_Tight">Lower alpha+                with paren</text:p>+              </text:list-item>+            </text:list>+          </text:list-item>+        </text:list>+      </text:list-item>+    </text:list>+  </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">Autonumbering:</text:p>+<text:list text:style-name="Numbering_20_1">+  <text:list-item>+    <text:p text:style-name="List_20_Number_20_Tight">Autonumber.</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Number_20_Tight">More.</text:p>+    <text:list text:style-name="Numbering_20_1">+      <text:list-item>+        <text:p text:style-name="List_20_Number_20_Tight">Nested.</text:p>+      </text:list-item>+    </text:list>+  </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">Should not be a list item:</text:p>+<text:p text:style-name="Text_20_body">M.A. 2007</text:p>+<text:p text:style-name="Text_20_body">B. Williams</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="definition-lists" />Definition+Lists<text:bookmark-end text:name="definition-lists" /></text:h>+<text:p text:style-name="First_20_paragraph">Tight using spaces:</text:p>+<text:p text:style-name="Definition_20_Term_20_Tight">apple</text:p>+<text:p text:style-name="Definition_20_Definition_20_Tight">red fruit</text:p>+<text:p text:style-name="Definition_20_Term_20_Tight">orange</text:p>+<text:p text:style-name="Definition_20_Definition_20_Tight">orange+fruit</text:p>+<text:p text:style-name="Definition_20_Term_20_Tight">banana</text:p>+<text:p text:style-name="Definition_20_Definition_20_Tight">yellow+fruit</text:p>+<text:p text:style-name="First_20_paragraph">Tight using tabs:</text:p>+<text:p text:style-name="Definition_20_Term_20_Tight">apple</text:p>+<text:p text:style-name="Definition_20_Definition_20_Tight">red fruit</text:p>+<text:p text:style-name="Definition_20_Term_20_Tight">orange</text:p>+<text:p text:style-name="Definition_20_Definition_20_Tight">orange+fruit</text:p>+<text:p text:style-name="Definition_20_Term_20_Tight">banana</text:p>+<text:p text:style-name="Definition_20_Definition_20_Tight">yellow+fruit</text:p>+<text:p text:style-name="First_20_paragraph">Loose:</text:p>+<text:p text:style-name="Definition_20_Term">apple</text:p>+<text:p text:style-name="Definition_20_Definition">red fruit</text:p>+<text:p text:style-name="Definition_20_Term">orange</text:p>+<text:p text:style-name="Definition_20_Definition">orange fruit</text:p>+<text:p text:style-name="Definition_20_Term">banana</text:p>+<text:p text:style-name="Definition_20_Definition">yellow fruit</text:p>+<text:p text:style-name="First_20_paragraph">Multiple blocks with+italics:</text:p>+<text:p text:style-name="Definition_20_Term"><text:span text:style-name="Emphasis">apple</text:span></text:p>+<text:p text:style-name="Definition_20_Definition">red+fruit</text:p><text:p text:style-name="Definition_20_Definition">contains seeds,+crisp, pleasant to taste</text:p>+<text:p text:style-name="Definition_20_Term"><text:span text:style-name="Emphasis">orange</text:span></text:p>+<text:p text:style-name="Definition_20_Definition">orange+fruit</text:p><text:p text:style-name="Preformatted_20_Text">{ orange code block }</text:p><text:p text:style-name="P3">orange+block quote</text:p>+<text:p text:style-name="First_20_paragraph">Multiple definitions,+tight:</text:p>+<text:p text:style-name="Definition_20_Term_20_Tight">apple</text:p>+<text:p text:style-name="Definition_20_Definition_20_Tight">red fruit</text:p>+<text:p text:style-name="Definition_20_Definition_20_Tight">computer</text:p>+<text:p text:style-name="Definition_20_Term_20_Tight">orange</text:p>+<text:p text:style-name="Definition_20_Definition_20_Tight">orange+fruit</text:p>+<text:p text:style-name="Definition_20_Definition_20_Tight">bank</text:p>+<text:p text:style-name="First_20_paragraph">Multiple definitions,+loose:</text:p>+<text:p text:style-name="Definition_20_Term">apple</text:p>+<text:p text:style-name="Definition_20_Definition">red fruit</text:p>+<text:p text:style-name="Definition_20_Definition">computer</text:p>+<text:p text:style-name="Definition_20_Term">orange</text:p>+<text:p text:style-name="Definition_20_Definition">orange fruit</text:p>+<text:p text:style-name="Definition_20_Definition">bank</text:p>+<text:p text:style-name="First_20_paragraph">Blank line after term, indented+marker, alternate markers:</text:p>+<text:p text:style-name="Definition_20_Term">apple</text:p>+<text:p text:style-name="Definition_20_Definition">red fruit</text:p>+<text:p text:style-name="Definition_20_Definition">computer</text:p>+<text:p text:style-name="Definition_20_Term">orange</text:p>+<text:p text:style-name="Definition_20_Definition">orange+fruit</text:p><text:list text:style-name="Numbering_20_1">+  <text:list-item>+    <text:p text:style-name="List_20_Number_20_Tight">sublist</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Number_20_Tight">sublist</text:p>+  </text:list-item>+</text:list>+<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="html-blocks" />HTML+Blocks<text:bookmark-end text:name="html-blocks" /></text:h>+<text:p text:style-name="First_20_paragraph">Simple block on one line:</text:p>+<text:p text:style-name="Text_20_body">foo</text:p>+<text:p text:style-name="Text_20_body">And nested without indentation:</text:p>+<text:p text:style-name="Text_20_body">foo</text:p>+<text:p text:style-name="Text_20_body">bar</text:p>+<text:p text:style-name="Text_20_body">Interpreted markdown in a table:</text:p>+<text:p text:style-name="Text_20_body">This is+<text:span text:style-name="Emphasis">emphasized</text:span></text:p>+<text:p text:style-name="Text_20_body">And this is+<text:span text:style-name="Strong_20_Emphasis">strong</text:span></text:p>+<text:p text:style-name="Text_20_body">Here’s a simple block:</text:p>+<text:p text:style-name="Text_20_body">foo</text:p>+<text:p text:style-name="Text_20_body">This should be a code block,+though:</text:p>+<text:p text:style-name="Preformatted_20_Text">&lt;div&gt;</text:p>+<text:p text:style-name="Preformatted_20_Text"><text:s text:c="4" />foo</text:p>+<text:p text:style-name="Preformatted_20_Text">&lt;/div&gt;</text:p>+<text:p text:style-name="First_20_paragraph">As should this:</text:p>+<text:p text:style-name="Preformatted_20_Text">&lt;div&gt;foo&lt;/div&gt;</text:p>+<text:p text:style-name="First_20_paragraph">Now, nested:</text:p>+<text:p text:style-name="Text_20_body">foo</text:p>+<text:p text:style-name="Text_20_body">This should just be an HTML+comment:</text:p>+<text:p text:style-name="Text_20_body">Multiline:</text:p>+<text:p text:style-name="Text_20_body">Code block:</text:p>+<text:p text:style-name="Preformatted_20_Text">&lt;!-- Comment --&gt;</text:p>+<text:p text:style-name="First_20_paragraph">Just plain comment, with trailing+spaces on the line:</text:p>+<text:p text:style-name="Text_20_body">Code:</text:p>+<text:p text:style-name="Preformatted_20_Text">&lt;hr /&gt;</text:p>+<text:p text:style-name="First_20_paragraph">Hr’s:</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="inline-markup" />Inline+Markup<text:bookmark-end text:name="inline-markup" /></text:h>+<text:p text:style-name="First_20_paragraph">This is+<text:span text:style-name="Emphasis">emphasized</text:span>, and so+<text:span text:style-name="Emphasis">is this</text:span>.</text:p>+<text:p text:style-name="Text_20_body">This is+<text:span text:style-name="Strong_20_Emphasis">strong</text:span>, and so+<text:span text:style-name="Strong_20_Emphasis">is this</text:span>.</text:p>+<text:p text:style-name="Text_20_body">An+<text:a xlink:type="simple" xlink:href="/url" office:name=""><text:span text:style-name="Definition"><text:span text:style-name="Emphasis">emphasized+link</text:span></text:span></text:a>.</text:p>+<text:p text:style-name="Text_20_body"><text:span text:style-name="T1">This is+strong and em.</text:span></text:p>+<text:p text:style-name="Text_20_body">So is+<text:span text:style-name="T1">this</text:span> word.</text:p>+<text:p text:style-name="Text_20_body"><text:span text:style-name="T1">This is+strong and em.</text:span></text:p>+<text:p text:style-name="Text_20_body">So is+<text:span text:style-name="T1">this</text:span> word.</text:p>+<text:p text:style-name="Text_20_body">This is code:+<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="Strikeout">This+is+</text:span><text:span text:style-name="T2">strikeout</text:span><text:span text:style-name="Strikeout">.</text:span></text:p>+<text:p text:style-name="Text_20_body">Superscripts:+a<text:span text:style-name="Superscript">bc</text:span>d+a<text:span text:style-name="T3">hello</text:span>+a<text:span text:style-name="Superscript">hello there</text:span>.</text:p>+<text:p text:style-name="Text_20_body">Subscripts:+H<text:span text:style-name="Subscript">2</text:span>O,+H<text:span text:style-name="Subscript">23</text:span>O,+H<text:span text:style-name="Subscript">many of them</text:span>O.</text:p>+<text:p text:style-name="Text_20_body">These should not be superscripts or+subscripts, because of the unescaped spaces: a^b c^d, a~b c~d.</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="smart-quotes-ellipses-dashes" />Smart+quotes, ellipses,+dashes<text:bookmark-end text:name="smart-quotes-ellipses-dashes" /></text:h>+<text:p text:style-name="First_20_paragraph">“Hello,” said the spider. “‘Shelob’+is my name.”</text:p>+<text:p text:style-name="Text_20_body">‘A’, ‘B’, and ‘C’ are letters.</text:p>+<text:p text:style-name="Text_20_body">‘Oak,’ ‘elm,’ and ‘beech’ are names of+trees. So is ‘pine.’</text:p>+<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_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 —+five.</text:p>+<text:p text:style-name="Text_20_body">Dashes between numbers: 5–7, 255–66,+1987–1999.</text:p>+<text:p text:style-name="Text_20_body">Ellipses…and…and….</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="latex" />LaTeX<text:bookmark-end text:name="latex" /></text:h>+<text:list text:style-name="List_20_1">+  <text:list-item>+    <text:p text:style-name="List_20_Bullet_20_Tight"></text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Bullet_20_Tight">2 + 2 = 4</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Bullet_20_Tight"><text:span text:style-name="Emphasis">x</text:span> ∈ <text:span text:style-name="Emphasis">y</text:span></text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Bullet_20_Tight"><text:span text:style-name="Emphasis">α</text:span> ∧ <text:span text:style-name="Emphasis">ω</text:span></text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Bullet_20_Tight">223</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Bullet_20_Tight"><text:span text:style-name="Emphasis">p</text:span>-Tree</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Bullet_20_Tight">Here’s some display math:+    $$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Bullet_20_Tight">Here’s one that has a line+    break in it:+    <text:span text:style-name="Emphasis">α</text:span> + <text:span text:style-name="Emphasis">ω</text:span> × <text:span text:style-name="Emphasis">x</text:span><text:span text:style-name="Superscript">2</text:span>.</text:p>+  </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">These shouldn’t be math:</text:p>+<text:list text:style-name="List_20_1">+  <text:list-item>+    <text:p text:style-name="List_20_Bullet_20_Tight">To get the famous+    equation, write+    <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="List_20_Bullet_20_Tight">$22,000 is a+    <text:span text:style-name="Emphasis">lot</text:span> of money. So is+    $34,000. (It worked if “lot” is emphasized.)</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Bullet_20_Tight">Shoes ($20) and socks+    ($5).</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Bullet_20_Tight">Escaped+    <text:span text:style-name="Source_20_Text">$</text:span>: $73+    <text:span text:style-name="Emphasis">this should be emphasized</text:span>+    23$.</text:p>+  </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">Here’s a LaTeX table:</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="special-characters" />Special+Characters<text:bookmark-end text:name="special-characters" /></text:h>+<text:p text:style-name="First_20_paragraph">Here is some unicode:</text:p>+<text:list text:style-name="List_20_1">+  <text:list-item>+    <text:p text:style-name="List_20_Bullet_20_Tight">I hat: Î</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Bullet_20_Tight">o umlaut: ö</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Bullet_20_Tight">section: §</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Bullet_20_Tight">set membership: ∈</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Bullet_20_Tight">copyright: ©</text:p>+  </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">AT&amp;T has an ampersand in their+name.</text:p>+<text:p text:style-name="Text_20_body">AT&amp;T is another way to write+it.</text:p>+<text:p text:style-name="Text_20_body">This &amp; that.</text:p>+<text:p text:style-name="Text_20_body">4 &lt; 5.</text:p>+<text:p text:style-name="Text_20_body">6 &gt; 5.</text:p>+<text:p text:style-name="Text_20_body">Backslash: \</text:p>+<text:p text:style-name="Text_20_body">Backtick: `</text:p>+<text:p text:style-name="Text_20_body">Asterisk: *</text:p>+<text:p text:style-name="Text_20_body">Underscore: _</text:p>+<text:p text:style-name="Text_20_body">Left brace: {</text:p>+<text:p text:style-name="Text_20_body">Right brace: }</text:p>+<text:p text:style-name="Text_20_body">Left bracket: [</text:p>+<text:p text:style-name="Text_20_body">Right bracket: ]</text:p>+<text:p text:style-name="Text_20_body">Left paren: (</text:p>+<text:p text:style-name="Text_20_body">Right paren: )</text:p>+<text:p text:style-name="Text_20_body">Greater-than: &gt;</text:p>+<text:p text:style-name="Text_20_body">Hash: #</text:p>+<text:p text:style-name="Text_20_body">Period: .</text:p>+<text:p text:style-name="Text_20_body">Bang: !</text:p>+<text:p text:style-name="Text_20_body">Plus: +</text:p>+<text:p text:style-name="Text_20_body">Minus: -</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="links" />Links<text:bookmark-end text:name="links" /></text:h>+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="explicit" />Explicit<text:bookmark-end text:name="explicit" /></text:h>+<text:p text:style-name="First_20_paragraph">Just a+<text:a xlink:type="simple" xlink:href="/url/" office:name=""><text:span text:style-name="Definition">URL</text:span></text:a>.</text:p>+<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="/url/" office:name="title"><text:span text:style-name="Definition">URL+and title</text:span></text:a>.</text:p>+<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="/url/" office:name="title preceded by two spaces"><text:span text:style-name="Definition">URL+and title</text:span></text:a>.</text:p>+<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="/url/" office:name="title preceded by a tab"><text:span text:style-name="Definition">URL+and title</text:span></text:a>.</text:p>+<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="/url/" office:name="title with &quot;quotes&quot; in it"><text:span text:style-name="Definition">URL+and title</text:span></text:a></text:p>+<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="/url/" office:name="title with single quotes"><text:span text:style-name="Definition">URL+and title</text:span></text:a></text:p>+<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="/url/with_underscore" office:name=""><text:span text:style-name="Definition">with_underscore</text:span></text:a></text:p>+<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="mailto:nobody@nowhere.net" office:name=""><text:span text:style-name="Definition">Email+link</text:span></text:a></text:p>+<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="" office:name=""><text:span text:style-name="Definition">Empty</text:span></text:a>.</text:p>+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="reference" />Reference<text:bookmark-end text:name="reference" /></text:h>+<text:p text:style-name="First_20_paragraph">Foo+<text:a xlink:type="simple" xlink:href="/url/" office:name=""><text:span text:style-name="Definition">bar</text:span></text:a>.</text:p>+<text:p text:style-name="Text_20_body">With+<text:a xlink:type="simple" xlink:href="/url/" office:name=""><text:span text:style-name="Definition">embedded+[brackets]</text:span></text:a>.</text:p>+<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="/url/" office:name=""><text:span text:style-name="Definition">b</text:span></text:a>+by itself should be a link.</text:p>+<text:p text:style-name="Text_20_body">Indented+<text:a xlink:type="simple" xlink:href="/url" office:name=""><text:span text:style-name="Definition">once</text:span></text:a>.</text:p>+<text:p text:style-name="Text_20_body">Indented+<text:a xlink:type="simple" xlink:href="/url" office:name=""><text:span text:style-name="Definition">twice</text:span></text:a>.</text:p>+<text:p text:style-name="Text_20_body">Indented+<text:a xlink:type="simple" xlink:href="/url" office:name=""><text:span text:style-name="Definition">thrice</text:span></text:a>.</text:p>+<text:p text:style-name="Text_20_body">This should [not][] be a link.</text:p>+<text:p text:style-name="Preformatted_20_Text">[not]: /url</text:p>+<text:p text:style-name="First_20_paragraph">Foo+<text:a xlink:type="simple" xlink:href="/url/" office:name="Title with &quot;quotes&quot; inside"><text:span text:style-name="Definition">bar</text:span></text:a>.</text:p>+<text:p text:style-name="Text_20_body">Foo+<text:a xlink:type="simple" xlink:href="/url/" office:name="Title with &quot;quote&quot; inside"><text:span text:style-name="Definition">biz</text:span></text:a>.</text:p>+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="with-ampersands" />With+ampersands<text:bookmark-end text:name="with-ampersands" /></text:h>+<text:p text:style-name="First_20_paragraph">Here’s a+<text:a xlink:type="simple" xlink:href="http://example.com/?foo=1&amp;bar=2" office:name=""><text:span text:style-name="Definition">link+with an ampersand in the URL</text:span></text:a>.</text:p>+<text:p text:style-name="Text_20_body">Here’s a link with an amersand in the+link text:+<text:a xlink:type="simple" xlink:href="http://att.com/" office:name="AT&amp;T"><text:span text:style-name="Definition">AT&amp;T</text:span></text:a>.</text:p>+<text:p text:style-name="Text_20_body">Here’s an+<text:a xlink:type="simple" xlink:href="/script?foo=1&amp;bar=2" office:name=""><text:span text:style-name="Definition">inline+link</text:span></text:a>.</text:p>+<text:p text:style-name="Text_20_body">Here’s an+<text:a xlink:type="simple" xlink:href="/script?foo=1&amp;bar=2" office:name=""><text:span text:style-name="Definition">inline+link in pointy braces</text:span></text:a>.</text:p>+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="autolinks" />Autolinks<text:bookmark-end text:name="autolinks" /></text:h>+<text:p text:style-name="First_20_paragraph">With an ampersand:+<text:a xlink:type="simple" xlink:href="http://example.com/?foo=1&amp;bar=2" office:name=""><text:span text:style-name="Definition">http://example.com/?foo=1&amp;bar=2</text:span></text:a></text:p>+<text:list text:style-name="List_20_1">+  <text:list-item>+    <text:p text:style-name="List_20_Bullet_20_Tight">In a list?</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Bullet_20_Tight"><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:list-item>+  <text:list-item>+    <text:p text:style-name="List_20_Bullet_20_Tight">It should.</text:p>+  </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">An e-mail address:+<text:a xlink:type="simple" xlink:href="mailto:nobody@nowhere.net" office:name=""><text:span text:style-name="Definition">nobody@nowhere.net</text:span></text:a></text:p>+<text:p text:style-name="Quotations">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_20_Text">&lt;http://example.com/&gt;</text:span></text:p>+<text:p text:style-name="Preformatted_20_Text">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>+<text:p text:style-name="First_20_paragraph">From “Voyage dans la Lune” by+Georges Melies (1902):</text:p>+<text:p text:style-name="FigureWithCaption"><draw:frame draw:name="img1"><draw:image xlink:href="lalune.jpg" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad" /></draw:frame></text:p>+<text:p text:style-name="FigureCaption">lalune</text:p>+<text:p text:style-name="Text_20_body">Here is a movie+<draw:frame draw:name="img2"><draw:image xlink:href="movie.jpg" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad" /></draw:frame>+icon.</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="footnotes" />Footnotes<text:bookmark-end text:name="footnotes" /></text:h>+<text:p text:style-name="First_20_paragraph">Here is a footnote+reference,<text:note text:id="ftn0" text:note-class="footnote"><text:note-citation>1</text:note-citation><text:note-body><text:p text:style-name="Footnote">Here+is the footnote. It can go anywhere after the footnote reference. It need not be+placed at the end of the document.</text:p></text:note-body></text:note> and+another.<text:note text:id="ftn1" text:note-class="footnote"><text:note-citation>2</text:note-citation><text:note-body><text:p text:style-name="Footnote">Here’s+the long note. This one contains multiple+blocks.</text:p><text:p text:style-name="Footnote">Subsequent blocks are+indented to show that they belong to the footnote (as with list+items).</text:p><text:p text:style-name="Preformatted_20_Text"><text:s text:c="2" />{ &lt;code&gt; }</text:p><text:p text:style-name="Footnote">If+you want, you can indent every line, but you can also be lazy and just indent+the first line of each block.</text:p></text:note-body></text:note> This should+<text:span text:style-name="Emphasis">not</text:span> be a footnote reference,+because it contains a space.[^my note] Here is an inline+note.<text:note text:id="ftn2" text:note-class="footnote"><text:note-citation>3</text:note-citation><text:note-body><text:p text:style-name="Footnote">This+is <text:span text:style-name="Emphasis">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_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="Quotations">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>+<text:list text:style-name="Numbering_20_1">+  <text:list-item>+    <text:p text:style-name="List_20_Number_20_Tight">And in list     items.<text:note text:id="ftn4" text:note-class="footnote"><text:note-citation>5</text:note-citation><text:note-body><text:p text:style-name="Footnote">In     list.</text:p></text:note-body></text:note></text:p>   </text:list-item>
test/writer.opml view
@@ -31,28 +31,28 @@ <outline text="Code Blocks" _note="Code:&#10;&#10;    ---- (should be four hyphens)&#10;&#10;    sub status {&#10;        print &quot;working&quot;;&#10;    }&#10;&#10;    this code block is indented by one tab&#10;&#10;And:&#10;&#10;        this code block is indented by two tabs&#10;&#10;    These should not be escaped:  \$ \\ \&gt; \[ \{&#10;&#10;--------------------------------------------------------------------------------"> </outline> <outline text="Lists">-  <outline text="Unordered" _note="Asterisks tight:&#10;&#10;-   asterisk 1&#10;-   asterisk 2&#10;-   asterisk 3&#10;&#10;Asterisks loose:&#10;&#10;-   asterisk 1&#10;&#10;-   asterisk 2&#10;&#10;-   asterisk 3&#10;&#10;Pluses tight:&#10;&#10;-   Plus 1&#10;-   Plus 2&#10;-   Plus 3&#10;&#10;Pluses loose:&#10;&#10;-   Plus 1&#10;&#10;-   Plus 2&#10;&#10;-   Plus 3&#10;&#10;Minuses tight:&#10;&#10;-   Minus 1&#10;-   Minus 2&#10;-   Minus 3&#10;&#10;Minuses loose:&#10;&#10;-   Minus 1&#10;&#10;-   Minus 2&#10;&#10;-   Minus 3">+  <outline text="Unordered" _note="Asterisks tight:&#10;&#10;- asterisk 1&#10;- asterisk 2&#10;- asterisk 3&#10;&#10;Asterisks loose:&#10;&#10;- asterisk 1&#10;&#10;- asterisk 2&#10;&#10;- asterisk 3&#10;&#10;Pluses tight:&#10;&#10;- Plus 1&#10;- Plus 2&#10;- Plus 3&#10;&#10;Pluses loose:&#10;&#10;- Plus 1&#10;&#10;- Plus 2&#10;&#10;- Plus 3&#10;&#10;Minuses tight:&#10;&#10;- Minus 1&#10;- Minus 2&#10;- Minus 3&#10;&#10;Minuses loose:&#10;&#10;- Minus 1&#10;&#10;- Minus 2&#10;&#10;- Minus 3">   </outline>   <outline text="Ordered" _note="Tight:&#10;&#10;1.  First&#10;2.  Second&#10;3.  Third&#10;&#10;and:&#10;&#10;1.  One&#10;2.  Two&#10;3.  Three&#10;&#10;Loose using tabs:&#10;&#10;1.  First&#10;&#10;2.  Second&#10;&#10;3.  Third&#10;&#10;and using spaces:&#10;&#10;1.  One&#10;&#10;2.  Two&#10;&#10;3.  Three&#10;&#10;Multiple paragraphs:&#10;&#10;1.  Item 1, graf one.&#10;&#10;    Item 1. graf two. The quick brown fox jumped over the lazy dog's back.&#10;&#10;2.  Item 2.&#10;&#10;3.  Item 3.">   </outline>-  <outline text="Nested" _note="-   Tab&#10;    -   Tab&#10;        -   Tab&#10;&#10;Here's another:&#10;&#10;1.  First&#10;2.  Second:&#10;    -   Fee&#10;    -   Fie&#10;    -   Foe&#10;3.  Third&#10;&#10;Same thing but with paragraphs:&#10;&#10;1.  First&#10;&#10;2.  Second:&#10;&#10;    -   Fee&#10;    -   Fie&#10;    -   Foe&#10;&#10;3.  Third">+  <outline text="Nested" _note="- Tab&#10;  - Tab&#10;    - Tab&#10;&#10;Here's another:&#10;&#10;1.  First&#10;2.  Second:&#10;    - Fee&#10;    - Fie&#10;    - Foe&#10;3.  Third&#10;&#10;Same thing but with paragraphs:&#10;&#10;1.  First&#10;&#10;2.  Second:&#10;&#10;    - Fee&#10;    - Fie&#10;    - Foe&#10;&#10;3.  Third">   </outline>-  <outline text="Tabs and spaces" _note="-   this is a list item indented with tabs&#10;&#10;-   this is a list item indented with spaces&#10;&#10;    -   this is an example list item indented with tabs&#10;&#10;    -   this is an example list item indented with spaces">+  <outline text="Tabs and spaces" _note="- this is a list item indented with tabs&#10;&#10;- this is a list item indented with spaces&#10;&#10;  - this is an example list item indented with tabs&#10;&#10;  - this is an example list item indented with spaces">   </outline>   <outline text="Fancy list markers" _note="(2) begins with 2&#10;&#10;(3) and now 3&#10;&#10;    with a continuation&#10;&#10;    iv. sublist with roman numerals, starting with 4&#10;    v.  more items&#10;        (A) a subsublist&#10;        (B) a subsublist&#10;&#10;Nesting:&#10;&#10;A.  Upper Alpha&#10;    I.  Upper Roman.&#10;        (6) Decimal start with 6&#10;            c)  Lower alpha with paren&#10;&#10;Autonumbering:&#10;&#10;1.  Autonumber.&#10;2.  More.&#10;    1.  Nested.&#10;&#10;Should not be a list item:&#10;&#10;M.A. 2007&#10;&#10;B. Williams&#10;&#10;--------------------------------------------------------------------------------">   </outline> </outline>-<outline text="Definition Lists" _note="Tight using spaces:&#10;&#10;apple&#10;:   red fruit&#10;&#10;orange&#10;:   orange fruit&#10;&#10;banana&#10;:   yellow fruit&#10;&#10;Tight using tabs:&#10;&#10;apple&#10;:   red fruit&#10;&#10;orange&#10;:   orange fruit&#10;&#10;banana&#10;:   yellow fruit&#10;&#10;Loose:&#10;&#10;apple&#10;&#10;:   red fruit&#10;&#10;orange&#10;&#10;:   orange fruit&#10;&#10;banana&#10;&#10;:   yellow fruit&#10;&#10;Multiple blocks with italics:&#10;&#10;*apple*&#10;&#10;:   red fruit&#10;&#10;    contains seeds, crisp, pleasant to taste&#10;&#10;*orange*&#10;&#10;:   orange fruit&#10;&#10;        { orange code block }&#10;&#10;    &gt; orange block quote&#10;&#10;Multiple definitions, tight:&#10;&#10;apple&#10;:   red fruit&#10;:   computer&#10;&#10;orange&#10;:   orange fruit&#10;:   bank&#10;&#10;Multiple definitions, loose:&#10;&#10;apple&#10;&#10;:   red fruit&#10;&#10;:   computer&#10;&#10;orange&#10;&#10;:   orange fruit&#10;&#10;:   bank&#10;&#10;Blank line after term, indented marker, alternate markers:&#10;&#10;apple&#10;&#10;:   red fruit&#10;&#10;:   computer&#10;&#10;orange&#10;&#10;:   orange fruit&#10;&#10;    1.  sublist&#10;    2.  sublist">+<outline text="Definition Lists" _note="Tight using spaces:&#10;&#10;apple&#10;: red fruit&#10;&#10;orange&#10;: orange fruit&#10;&#10;banana&#10;: yellow fruit&#10;&#10;Tight using tabs:&#10;&#10;apple&#10;: red fruit&#10;&#10;orange&#10;: orange fruit&#10;&#10;banana&#10;: yellow fruit&#10;&#10;Loose:&#10;&#10;apple&#10;&#10;: red fruit&#10;&#10;orange&#10;&#10;: orange fruit&#10;&#10;banana&#10;&#10;: yellow fruit&#10;&#10;Multiple blocks with italics:&#10;&#10;*apple*&#10;&#10;: red fruit&#10;&#10;  contains seeds, crisp, pleasant to taste&#10;&#10;*orange*&#10;&#10;: orange fruit&#10;&#10;      { orange code block }&#10;&#10;  &gt; orange block quote&#10;&#10;Multiple definitions, tight:&#10;&#10;apple&#10;: red fruit&#10;: computer&#10;&#10;orange&#10;: orange fruit&#10;: bank&#10;&#10;Multiple definitions, loose:&#10;&#10;apple&#10;&#10;: red fruit&#10;&#10;: computer&#10;&#10;orange&#10;&#10;: orange fruit&#10;&#10;: bank&#10;&#10;Blank line after term, indented marker, alternate markers:&#10;&#10;apple&#10;&#10;: red fruit&#10;&#10;: computer&#10;&#10;orange&#10;&#10;: orange fruit&#10;&#10;  1.  sublist&#10;  2.  sublist"> </outline>-<outline text="HTML Blocks" _note="Simple block on one line:&#10;&#10;&lt;div&gt;&#10;&#10;foo&#10;&#10;&lt;/div&gt;&#10;&#10;And nested without indentation:&#10;&#10;&lt;div&gt;&#10;&#10;&lt;div&gt;&#10;&#10;&lt;div&gt;&#10;&#10;foo&#10;&#10;&lt;/div&gt;&#10;&#10;&lt;/div&gt;&#10;&#10;&lt;div&gt;&#10;&#10;bar&#10;&#10;&lt;/div&gt;&#10;&#10;&lt;/div&gt;&#10;&#10;Interpreted markdown in a table:&#10;&#10;```{=html}&#10;&lt;table&gt;&#10;```&#10;```{=html}&#10;&lt;tr&gt;&#10;```&#10;```{=html}&#10;&lt;td&gt;&#10;```&#10;This is *emphasized*&#10;```{=html}&#10;&lt;/td&gt;&#10;```&#10;```{=html}&#10;&lt;td&gt;&#10;```&#10;And this is **strong**&#10;```{=html}&#10;&lt;/td&gt;&#10;```&#10;```{=html}&#10;&lt;/tr&gt;&#10;```&#10;```{=html}&#10;&lt;/table&gt;&#10;```&#10;```{=html}&#10;&lt;script type=&quot;text/javascript&quot;&gt;document.write('This *should not* be interpreted as markdown');&lt;/script&gt;&#10;```&#10;Here's a simple block:&#10;&#10;&lt;div&gt;&#10;&#10;foo&#10;&#10;&lt;/div&gt;&#10;&#10;This should be a code block, though:&#10;&#10;    &lt;div&gt;&#10;        foo&#10;    &lt;/div&gt;&#10;&#10;As should this:&#10;&#10;    &lt;div&gt;foo&lt;/div&gt;&#10;&#10;Now, nested:&#10;&#10;&lt;div&gt;&#10;&#10;&lt;div&gt;&#10;&#10;&lt;div&gt;&#10;&#10;foo&#10;&#10;&lt;/div&gt;&#10;&#10;&lt;/div&gt;&#10;&#10;&lt;/div&gt;&#10;&#10;This should just be an HTML comment:&#10;&#10;```{=html}&#10;&lt;!-- Comment --&gt;&#10;```&#10;Multiline:&#10;&#10;```{=html}&#10;&lt;!--&#10;Blah&#10;Blah&#10;--&gt;&#10;```&#10;```{=html}&#10;&lt;!--&#10;    This is another comment.&#10;--&gt;&#10;```&#10;Code block:&#10;&#10;    &lt;!-- Comment --&gt;&#10;&#10;Just plain comment, with trailing spaces on the line:&#10;&#10;```{=html}&#10;&lt;!-- foo --&gt;&#10;```&#10;Code:&#10;&#10;    &lt;hr /&gt;&#10;&#10;Hr's:&#10;&#10;```{=html}&#10;&lt;hr&gt;&#10;```&#10;```{=html}&#10;&lt;hr /&gt;&#10;```&#10;```{=html}&#10;&lt;hr /&gt;&#10;```&#10;```{=html}&#10;&lt;hr&gt;&#10;```&#10;```{=html}&#10;&lt;hr /&gt;&#10;```&#10;```{=html}&#10;&lt;hr /&gt;&#10;```&#10;```{=html}&#10;&lt;hr class=&quot;foo&quot; id=&quot;bar&quot; /&gt;&#10;```&#10;```{=html}&#10;&lt;hr class=&quot;foo&quot; id=&quot;bar&quot; /&gt;&#10;```&#10;```{=html}&#10;&lt;hr class=&quot;foo&quot; id=&quot;bar&quot;&gt;&#10;```&#10;&#10;--------------------------------------------------------------------------------">+<outline text="HTML Blocks" _note="Simple block on one line:&#10;&#10;::: {}&#10;foo&#10;:::&#10;&#10;And nested without indentation:&#10;&#10;:::::: {}&#10;:::: {}&#10;::: {}&#10;foo&#10;:::&#10;::::&#10;&#10;::: {}&#10;bar&#10;:::&#10;::::::&#10;&#10;Interpreted markdown in a table:&#10;&#10;&lt;table&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;&#10;This is *emphasized*&#10;&lt;/td&gt;&#10;&lt;td&gt;&#10;And this is **strong**&#10;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/table&gt;&#10;&lt;script type=&quot;text/javascript&quot;&gt;document.write('This *should not* be interpreted as markdown');&lt;/script&gt;&#10;&#10;Here's a simple block:&#10;&#10;::: {}&#10;foo&#10;:::&#10;&#10;This should be a code block, though:&#10;&#10;    &lt;div&gt;&#10;        foo&#10;    &lt;/div&gt;&#10;&#10;As should this:&#10;&#10;    &lt;div&gt;foo&lt;/div&gt;&#10;&#10;Now, nested:&#10;&#10;::::: {}&#10;:::: {}&#10;::: {}&#10;foo&#10;:::&#10;::::&#10;:::::&#10;&#10;This should just be an HTML comment:&#10;&#10;&lt;!-- Comment --&gt;&#10;&#10;Multiline:&#10;&#10;&lt;!--&#10;Blah&#10;Blah&#10;--&gt;&#10;&lt;!--&#10;    This is another comment.&#10;--&gt;&#10;&#10;Code block:&#10;&#10;    &lt;!-- Comment --&gt;&#10;&#10;Just plain comment, with trailing spaces on the line:&#10;&#10;&lt;!-- foo --&gt;&#10;&#10;Code:&#10;&#10;    &lt;hr /&gt;&#10;&#10;Hr's:&#10;&#10;&lt;hr&gt;&#10;&lt;hr /&gt;&#10;&lt;hr /&gt;&#10;&lt;hr&gt;&#10;&lt;hr /&gt;&#10;&lt;hr /&gt;&#10;&lt;hr class=&quot;foo&quot; id=&quot;bar&quot; /&gt;&#10;&lt;hr class=&quot;foo&quot; id=&quot;bar&quot; /&gt;&#10;&lt;hr class=&quot;foo&quot; id=&quot;bar&quot;&gt;&#10;&#10;--------------------------------------------------------------------------------"> </outline> <outline text="Inline Markup" _note="This is *emphasized*, and so *is this*.&#10;&#10;This is **strong**, and so **is this**.&#10;&#10;An *[emphasized link](/url)*.&#10;&#10;***This is strong and em.***&#10;&#10;So is ***this*** word.&#10;&#10;***This is strong and em.***&#10;&#10;So is ***this*** word.&#10;&#10;This is code: `&gt;`, `$`, `\`, `\$`, `&lt;html&gt;`.&#10;&#10;~~This is *strikeout*.~~&#10;&#10;Superscripts: a^bc^d a^*hello*^ a^hello there^.&#10;&#10;Subscripts: H~2~O, H~23~O, H~many of them~O.&#10;&#10;These should not be superscripts or subscripts, because of the unescaped spaces:&#10;a\^b c\^d, a\~b c\~d.&#10;&#10;--------------------------------------------------------------------------------"> </outline> <outline text="Smart quotes, ellipses, dashes" _note="&quot;Hello,&quot; said the spider. &quot;'Shelob' is my name.&quot;&#10;&#10;'A', 'B', and 'C' are letters.&#10;&#10;'Oak,' 'elm,' and 'beech' are names of trees. So is 'pine.'&#10;&#10;'He said, &quot;I want to go.&quot;' Were you alive in the 70's?&#10;&#10;Here is some quoted '`code`' and a &quot;[quoted&#10;link](http://example.com/?foo=1&amp;bar=2)&quot;.&#10;&#10;Some dashes: one---two --- three---four --- five.&#10;&#10;Dashes between numbers: 5--7, 255--66, 1987--1999.&#10;&#10;Ellipses...and...and....&#10;&#10;--------------------------------------------------------------------------------"> </outline>-<outline text="LaTeX" _note="-   `\cite[22-23]{smith.1899}`{=tex}&#10;-   $2+2=4$&#10;-   $x \in y$&#10;-   $\alpha \wedge \omega$&#10;-   $223$&#10;-   $p$-Tree&#10;-   Here's some display math:&#10;    $$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$&#10;-   Here's one that has a line break in it: $\alpha + \omega \times x^2$.&#10;&#10;These shouldn't be math:&#10;&#10;-   To get the famous equation, write `$e = mc^2$`.&#10;-   \$22,000 is a *lot* of money. So is \$34,000. (It worked if &quot;lot&quot; is&#10;    emphasized.)&#10;-   Shoes (\$20) and socks (\$5).&#10;-   Escaped `$`: \$73 *this should be emphasized* 23\$.&#10;&#10;Here's a LaTeX table:&#10;&#10;```{=tex}&#10;\begin{tabular}{|l|l|}\hline&#10;Animal &amp; Number \\ \hline&#10;Dog    &amp; 2      \\&#10;Cat    &amp; 1      \\ \hline&#10;\end{tabular}&#10;```&#10;&#10;--------------------------------------------------------------------------------">+<outline text="LaTeX" _note="- `\cite[22-23]{smith.1899}`{=tex}&#10;- $2+2=4$&#10;- $x \in y$&#10;- $\alpha \wedge \omega$&#10;- $223$&#10;- $p$-Tree&#10;- Here's some display math:&#10;  $$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$&#10;- Here's one that has a line break in it: $\alpha + \omega \times x^2$.&#10;&#10;These shouldn't be math:&#10;&#10;- To get the famous equation, write `$e = mc^2$`.&#10;- \$22,000 is a *lot* of money. So is \$34,000. (It worked if &quot;lot&quot; is&#10;  emphasized.)&#10;- Shoes (\$20) and socks (\$5).&#10;- Escaped `$`: \$73 *this should be emphasized* 23\$.&#10;&#10;Here's a LaTeX table:&#10;&#10;\begin{tabular}{|l|l|}\hline&#10;Animal &amp; Number \\ \hline&#10;Dog    &amp; 2      \\&#10;Cat    &amp; 1      \\ \hline&#10;\end{tabular}&#10;&#10;--------------------------------------------------------------------------------"> </outline>-<outline text="Special Characters" _note="Here is some unicode:&#10;&#10;-   I hat: Î&#10;-   o umlaut: ö&#10;-   section: §&#10;-   set membership: ∈&#10;-   copyright: ©&#10;&#10;AT&amp;T has an ampersand in their name.&#10;&#10;AT&amp;T is another way to write it.&#10;&#10;This &amp; that.&#10;&#10;4 \&lt; 5.&#10;&#10;6 \&gt; 5.&#10;&#10;Backslash: \\&#10;&#10;Backtick: \`&#10;&#10;Asterisk: \*&#10;&#10;Underscore: \_&#10;&#10;Left brace: {&#10;&#10;Right brace: }&#10;&#10;Left bracket: \[&#10;&#10;Right bracket: \]&#10;&#10;Left paren: (&#10;&#10;Right paren: )&#10;&#10;Greater-than: \&gt;&#10;&#10;Hash: \#&#10;&#10;Period: .&#10;&#10;Bang: !&#10;&#10;Plus: +&#10;&#10;Minus: -&#10;&#10;--------------------------------------------------------------------------------">+<outline text="Special Characters" _note="Here is some unicode:&#10;&#10;- I hat: Î&#10;- o umlaut: ö&#10;- section: §&#10;- set membership: ∈&#10;- copyright: ©&#10;&#10;AT&amp;T has an ampersand in their name.&#10;&#10;AT&amp;T is another way to write it.&#10;&#10;This &amp; that.&#10;&#10;4 \&lt; 5.&#10;&#10;6 \&gt; 5.&#10;&#10;Backslash: \\&#10;&#10;Backtick: \`&#10;&#10;Asterisk: \*&#10;&#10;Underscore: \_&#10;&#10;Left brace: {&#10;&#10;Right brace: }&#10;&#10;Left bracket: \[&#10;&#10;Right bracket: \]&#10;&#10;Left paren: (&#10;&#10;Right paren: )&#10;&#10;Greater-than: \&gt;&#10;&#10;Hash: \#&#10;&#10;Period: .&#10;&#10;Bang: !&#10;&#10;Plus: +&#10;&#10;Minus: -&#10;&#10;--------------------------------------------------------------------------------"> </outline> <outline text="Links">   <outline text="Explicit" _note="Just a [URL](/url/).&#10;&#10;[URL and title](/url/ &quot;title&quot;).&#10;&#10;[URL and title](/url/ &quot;title preceded by two spaces&quot;).&#10;&#10;[URL and title](/url/ &quot;title preceded by a tab&quot;).&#10;&#10;[URL and title](/url/ &quot;title with &quot;quotes&quot; in it&quot;)&#10;&#10;[URL and title](/url/ &quot;title with single quotes&quot;)&#10;&#10;[with_underscore](/url/with_underscore)&#10;&#10;[Email link](mailto:nobody@nowhere.net)&#10;&#10;[Empty]().">@@ -61,7 +61,7 @@   </outline>   <outline text="With ampersands" _note="Here's a [link with an ampersand in the URL](http://example.com/?foo=1&amp;bar=2).&#10;&#10;Here's a link with an amersand in the link text: [AT&amp;T](http://att.com/ &quot;AT&amp;T&quot;).&#10;&#10;Here's an [inline link](/script?foo=1&amp;bar=2).&#10;&#10;Here's an [inline link in pointy braces](/script?foo=1&amp;bar=2).">   </outline>-  <outline text="Autolinks" _note="With an ampersand: &lt;http://example.com/?foo=1&amp;bar=2&gt;&#10;&#10;-   In a list?&#10;-   &lt;http://example.com/&gt;&#10;-   It should.&#10;&#10;An e-mail address: &lt;nobody@nowhere.net&gt;&#10;&#10;&gt; Blockquoted: &lt;http://example.com/&gt;&#10;&#10;Auto-links should not occur here: `&lt;http://example.com/&gt;`&#10;&#10;    or here: &lt;http://example.com/&gt;&#10;&#10;--------------------------------------------------------------------------------">+  <outline text="Autolinks" _note="With an ampersand: &lt;http://example.com/?foo=1&amp;bar=2&gt;&#10;&#10;- In a list?&#10;- &lt;http://example.com/&gt;&#10;- It should.&#10;&#10;An e-mail address: &lt;nobody@nowhere.net&gt;&#10;&#10;&gt; Blockquoted: &lt;http://example.com/&gt;&#10;&#10;Auto-links should not occur here: `&lt;http://example.com/&gt;`&#10;&#10;    or here: &lt;http://example.com/&gt;&#10;&#10;--------------------------------------------------------------------------------">   </outline> </outline> <outline text="Images" _note="From &quot;Voyage dans la Lune&quot; by Georges Melies (1902):&#10;&#10;![lalune](lalune.jpg &quot;Voyage dans la Lune&quot;)&#10;&#10;Here is a movie ![movie](movie.jpg) icon.&#10;&#10;--------------------------------------------------------------------------------">
test/writer.org view
@@ -563,16 +563,16 @@ :PROPERTIES: :CUSTOM_ID: smart-quotes-ellipses-dashes :END:-"Hello," said the spider. "'Shelob' is my name."+“Hello,” said the spider. “‘Shelob’ is my name.” -'A', 'B', and 'C' are letters.+‘A’, ‘B’, and ‘C’ are letters. -'Oak,' 'elm,' and 'beech' are names of trees. So is 'pine.'+‘Oak,’ ‘elm,’ and ‘beech’ are names of trees. So is ‘pine.’ -'He said, "I want to go."' Were you alive in the 70's?+‘He said, “I want to go.”’ Were you alive in the 70's? -Here is some quoted '=code=' and a "[[http://example.com/?foo=1&bar=2][quoted-link]]".+Here is some quoted ‘=code=’ and a+“[[http://example.com/?foo=1&bar=2][quoted link]]”.  Some dashes: one---two --- three---four --- five. @@ -599,7 +599,7 @@ These shouldn't be math:  - To get the famous equation, write =$e = mc^2$=.-- $22,000 is a /lot/ of money. So is $34,000. (It worked if "lot" is+- $22,000 is a /lot/ of money. So is $34,000. (It worked if “lot” is   emphasized.) - Shoes ($20) and socks ($5). - Escaped =$=: $73 /this should be emphasized/ 23$.@@ -762,7 +762,7 @@ :PROPERTIES: :CUSTOM_ID: images :END:-From "Voyage dans la Lune" by Georges Melies (1902):+From “Voyage dans la Lune” by Georges Melies (1902):  #+caption: lalune [[file:lalune.jpg]]
test/writer.plain view
@@ -101,45 +101,45 @@  Asterisks tight: --   asterisk 1--   asterisk 2--   asterisk 3+- asterisk 1+- asterisk 2+- asterisk 3  Asterisks loose: --   asterisk 1+- asterisk 1 --   asterisk 2+- asterisk 2 --   asterisk 3+- asterisk 3  Pluses tight: --   Plus 1--   Plus 2--   Plus 3+- Plus 1+- Plus 2+- Plus 3  Pluses loose: --   Plus 1+- Plus 1 --   Plus 2+- Plus 2 --   Plus 3+- Plus 3  Minuses tight: --   Minus 1--   Minus 2--   Minus 3+- Minus 1+- Minus 2+- Minus 3  Minuses loose: --   Minus 1+- Minus 1 --   Minus 2+- Minus 2 --   Minus 3+- Minus 3  Ordered @@ -183,17 +183,17 @@  Nested --   Tab-    -   Tab-        -   Tab+- Tab+  - Tab+    - Tab  Here’s another:  1.  First 2.  Second:-    -   Fee-    -   Fie-    -   Foe+    - Fee+    - Fie+    - Foe 3.  Third  Same thing but with paragraphs:@@ -202,21 +202,21 @@  2.  Second: -    -   Fee-    -   Fie-    -   Foe+    - Fee+    - Fie+    - Foe  3.  Third  Tabs and spaces --   this is a list item indented with tabs+- this is a list item indented with tabs --   this is a list item indented with spaces+- this is a list item indented with spaces -    -   this is an example list item indented with tabs+  - this is an example list item indented with tabs -    -   this is an example list item indented with spaces+  - this is an example list item indented with spaces  Fancy list markers @@ -257,93 +257,93 @@ Tight using spaces:  apple-    red fruit+  red fruit  orange-    orange fruit+  orange fruit  banana-    yellow fruit+  yellow fruit  Tight using tabs:  apple-    red fruit+  red fruit  orange-    orange fruit+  orange fruit  banana-    yellow fruit+  yellow fruit  Loose:  apple -    red fruit+  red fruit  orange -    orange fruit+  orange fruit  banana -    yellow fruit+  yellow fruit  Multiple blocks with italics:  apple -    red fruit+  red fruit -    contains seeds, crisp, pleasant to taste+  contains seeds, crisp, pleasant to taste  orange -    orange fruit+  orange fruit -        { orange code block }+      { orange code block } -      orange block quote+    orange block quote  Multiple definitions, tight:  apple-    red fruit-    computer+  red fruit+  computer  orange-    orange fruit-    bank+  orange fruit+  bank  Multiple definitions, loose:  apple -    red fruit+  red fruit -    computer+  computer  orange -    orange fruit+  orange fruit -    bank+  bank  Blank line after term, indented marker, alternate markers:  apple -    red fruit+  red fruit -    computer+  computer  orange -    orange fruit+  orange fruit -    1.  sublist-    2.  sublist+  1.  sublist+  2.  sublist  HTML Blocks @@ -448,23 +448,22 @@  LaTeX --   --   2 + 2 = 4--   x ∈ y--   α ∧ ω--   223--   p-Tree--   Here’s some display math:-    $$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$--   Here’s one that has a line break in it: α + ω × x².+- +- 2 + 2 = 4+- x ∈ y+- α ∧ ω+- 223+- p-Tree+- Here’s some display math:+  $$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$+- Here’s one that has a line break in it: α + ω × x².  These shouldn’t be math: --   To get the famous equation, write $e = mc^2$.--   $22,000 is a lot of money. So is $34,000. (It worked if “lot” is-    emphasized.)--   Shoes ($20) and socks ($5).--   Escaped $: $73 this should be emphasized 23$.+- To get the famous equation, write $e = mc^2$.+- $22,000 is a lot of money. So is $34,000. (It worked if “lot” is emphasized.)+- Shoes ($20) and socks ($5).+- Escaped $: $73 this should be emphasized 23$.  Here’s a LaTeX table: @@ -474,11 +473,11 @@  Here is some unicode: --   I hat: Î--   o umlaut: ö--   section: §--   set membership: ∈--   copyright: ©+- I hat: Î+- o umlaut: ö+- section: §+- set membership: ∈+- copyright: ©  AT&T has an ampersand in their name. @@ -582,9 +581,9 @@  With an ampersand: http://example.com/?foo=1&bar=2 --   In a list?--   http://example.com/--   It should.+- In a list?+- http://example.com/+- It should.  An e-mail address: nobody@nowhere.net 
test/writer.rst view
@@ -133,45 +133,45 @@  Asterisks tight: --  asterisk 1--  asterisk 2--  asterisk 3+- asterisk 1+- asterisk 2+- asterisk 3  Asterisks loose: --  asterisk 1+- asterisk 1 --  asterisk 2+- asterisk 2 --  asterisk 3+- asterisk 3  Pluses tight: --  Plus 1--  Plus 2--  Plus 3+- Plus 1+- Plus 2+- Plus 3  Pluses loose: --  Plus 1+- Plus 1 --  Plus 2+- Plus 2 --  Plus 3+- Plus 3  Minuses tight: --  Minus 1--  Minus 2--  Minus 3+- Minus 1+- Minus 2+- Minus 3  Minuses loose: --  Minus 1+- Minus 1 --  Minus 2+- Minus 2 --  Minus 3+- Minus 3  Ordered -------@@ -217,20 +217,20 @@ Nested ------ --  Tab+- Tab -   -  Tab+  - Tab -      -  Tab+    - Tab  Here’s another:  1. First 2. Second: -   -  Fee-   -  Fie-   -  Foe+   - Fee+   - Fie+   - Foe  3. Third @@ -240,22 +240,22 @@  2. Second: -   -  Fee-   -  Fie-   -  Foe+   - Fee+   - Fie+   - Foe  3. Third  Tabs and spaces --------------- --  this is a list item indented with tabs+- this is a list item indented with tabs --  this is a list item indented with spaces+- this is a list item indented with spaces -   -  this is an example list item indented with tabs+  - this is an example list item indented with tabs -   -  this is an example list item indented with spaces+  - this is an example list item indented with spaces  Fancy list markers ------------------@@ -610,24 +610,24 @@ LaTeX ===== --  :raw-latex:`\cite[22-23]{smith.1899}`--  :math:`2+2=4`--  :math:`x \in y`--  :math:`\alpha \wedge \omega`--  :math:`223`--  :math:`p`-Tree--  Here’s some display math:+- :raw-latex:`\cite[22-23]{smith.1899}`+- :math:`2+2=4`+- :math:`x \in y`+- :math:`\alpha \wedge \omega`+- :math:`223`+- :math:`p`-Tree+- Here’s some display math: -   .. math:: \frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}--  Here’s one that has a line break in it: :math:`\alpha + \omega \times x^2`.+  .. math:: \frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}+- Here’s one that has a line break in it: :math:`\alpha + \omega \times x^2`.  These shouldn’t be math: --  To get the famous equation, write ``$e = mc^2$``.--  $22,000 is a *lot* of money. So is $34,000. (It worked if “lot” is-   emphasized.)--  Shoes ($20) and socks ($5).--  Escaped ``$``: $73 *this should be emphasized* 23$.+- To get the famous equation, write ``$e = mc^2$``.+- $22,000 is a *lot* of money. So is $34,000. (It worked if “lot” is+  emphasized.)+- Shoes ($20) and socks ($5).+- Escaped ``$``: $73 *this should be emphasized* 23$.  Here’s a LaTeX table: @@ -646,11 +646,11 @@  Here is some unicode: --  I hat: Î--  o umlaut: ö--  section: §--  set membership: ∈--  copyright: ©+- I hat: Î+- o umlaut: ö+- section: §+- set membership: ∈+- copyright: ©  AT&T has an ampersand in their name. @@ -762,9 +762,9 @@  With an ampersand: http://example.com/?foo=1&bar=2 --  In a list?--  http://example.com/--  It should.+- In a list?+- http://example.com/+- It should.  An e-mail address: nobody@nowhere.net 
test/writer.texinfo view
@@ -1,4 +1,6 @@-\input texinfo+\input texinfo  @c -*-texinfo-*-+@settitle Pandoc Test Suite+ @documentencoding UTF-8  @macro textstrikeout{text}@@ -48,23 +50,20 @@  @node Headers @chapter Headers-@anchor{#headers}  @menu-* Level 2 with an embedded link::+* Level 2 with an @uref{/url,embedded link}:: @end menu -@node Level 2 with an embedded link+@node Level 2 with an @uref{/url,embedded link} @section Level 2 with an @uref{/url,embedded link}-@anchor{#level-2-with-an-embedded-link}  @menu-* Level 3 with emphasis::+* Level 3 with @emph{emphasis}:: @end menu -@node Level 3 with emphasis+@node Level 3 with @emph{emphasis} @subsection Level 3 with @emph{emphasis}-@anchor{#level-3-with-emphasis}  @menu * Level 4::@@ -72,21 +71,18 @@  @node Level 4 @subsubsection Level 4-@anchor{#level-4} Level 5  @node Level 1 @chapter Level 1-@anchor{#level-1}  @menu-* Level 2 with emphasis::+* Level 2 with @emph{emphasis}:: * Level 2:: @end menu -@node Level 2 with emphasis+@node Level 2 with @emph{emphasis} @section Level 2 with @emph{emphasis}-@anchor{#level-2-with-emphasis}  @menu * Level 3::@@ -94,12 +90,10 @@  @node Level 3 @subsection Level 3-@anchor{#level-3} with no blank line  @node Level 2 @section Level 2-@anchor{#level-2} with no blank line  @iftex@@ -111,7 +105,6 @@  @node Paragraphs @chapter Paragraphs-@anchor{#paragraphs} Here's a regular paragraph.  In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item.@@ -132,7 +125,6 @@  @node Block Quotes @chapter Block Quotes-@anchor{#block-quotes} E-mail style:  @quotation@@ -178,7 +170,6 @@  @node Code Blocks @chapter Code Blocks-@anchor{#code-blocks} Code:  @verbatim@@ -208,7 +199,6 @@  @node Lists @chapter Lists-@anchor{#lists}  @menu * Unordered::@@ -220,7 +210,6 @@  @node Unordered @section Unordered-@anchor{#unordered} Asterisks tight:  @itemize@@ -298,7 +287,6 @@  @node Ordered @section Ordered-@anchor{#ordered} Tight:  @enumerate @@ -367,7 +355,6 @@  @node Nested @section Nested-@anchor{#nested} @itemize @item Tab@@ -428,7 +415,6 @@  @node Tabs and spaces @section Tabs and spaces-@anchor{#tabs-and-spaces} @itemize @item this is a list item indented with tabs@@ -449,7 +435,6 @@  @node Fancy list markers @section Fancy list markers-@anchor{#fancy-list-markers} @enumerate 2 @item begins with 2@@ -526,7 +511,6 @@  @node Definition Lists @chapter Definition Lists-@anchor{#definition-lists} Tight using spaces:  @table @asis@@ -648,7 +632,6 @@  @node HTML Blocks @chapter HTML Blocks-@anchor{#html-blocks} Simple block on one line:  foo@@ -709,7 +692,6 @@  @node Inline Markup @chapter Inline Markup-@anchor{#inline-markup} This is @emph{emphasized}, and so @emph{is this}.  This is @strong{strong}, and so @strong{is this}.@@ -744,7 +726,6 @@  @node Smart quotes ellipses dashes @chapter Smart quotes, ellipses, dashes-@anchor{#smart-quotes-ellipses-dashes} ``Hello,'' said the spider. ```Shelob' is my name.''  `A', `B', and `C' are letters.@@ -771,7 +752,6 @@  @node LaTeX @chapter LaTeX-@anchor{#latex} @itemize @item @tex@@ -826,7 +806,6 @@  @node Special Characters @chapter Special Characters-@anchor{#special-characters} Here is some unicode:  @itemize@@ -893,7 +872,6 @@  @node Links @chapter Links-@anchor{#links}  @menu * Explicit::@@ -904,7 +882,6 @@  @node Explicit @section Explicit-@anchor{#explicit} Just a @uref{/url/,URL}.  @uref{/url/,URL and title}.@@ -925,7 +902,6 @@  @node Reference @section Reference-@anchor{#reference} Foo @uref{/url/,bar}.  With @uref{/url/,embedded [brackets]}.@@ -950,7 +926,6 @@  @node With ampersands @section With ampersands-@anchor{#with-ampersands} Here's a @uref{http://example.com/?foo=1&bar=2,link with an ampersand in the URL}. @@ -962,7 +937,6 @@  @node Autolinks @section Autolinks-@anchor{#autolinks} With an ampersand: @url{http://example.com/?foo=1&bar=2}  @itemize@@ -974,7 +948,7 @@ It should. @end itemize -An e-mail address: @uref{mailto:nobody@@nowhere.net,nobody@@nowhere.net}+An e-mail address: @uref{mailto:nobody@@nowhere.net,nobody@@nowherenet}  @quotation Blockquoted: @url{http://example.com/}@@ -994,7 +968,6 @@  @node Images @chapter Images-@anchor{#images} From ``Voyage dans la Lune'' by Georges Melies (1902):  @float@@ -1012,7 +985,6 @@  @node Footnotes @chapter Footnotes-@anchor{#footnotes} Here is a footnote reference,@footnote{Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document.} and another.@footnote{Here's the long note. This one contains multiple blocks.
test/writer.typst view
@@ -1,115 +1,162 @@-// Some definitions presupposed by pandoc's typst output.-#let horizontalrule = [-  #line(start: (25%,0%), end: (75%,0%))-]+#let horizontalrule = line(start: (25%,0%), end: (75%,0%)) -#let endnote(num, contents) = [-  #stack(dir: ltr, spacing: 3pt, super[#num], contents)+#show terms.item: it => block(breakable: false)[+  #text(weight: "bold")[#it.term]+  #block(inset: (left: 1.5em, top: -0.4em))[#it.description] ]-#show terms: it => {-  it.children-    .map(child => [-      #strong[#child.term]-      #block(inset: (left: 1.5em, top: -0.4em))[#child.description]-      ])-    .join()-}  #set table(   inset: 6pt,   stroke: none ) +#show figure.where(+  kind: table+): set figure.caption(position: top)++#show figure.where(+  kind: image+): set figure.caption(position: bottom)++#let content-to-string(content) = {+  if content.has("text") {+    content.text+  } else if content.has("children") {+    content.children.map(content-to-string).join("")+  } else if content.has("body") {+    content-to-string(content.body)+  } else if content == [ ] {+    " "+  }+} #let conf(   title: none,+  subtitle: none,   authors: (),   keywords: (),   date: none,+  abstract-title: none,   abstract: none,+  thanks: none,   cols: 1,   margin: (x: 1.25in, y: 1.25in),   paper: "us-letter",   lang: "en",   region: "US",-  font: (),+  font: none,   fontsize: 11pt,+  mathfont: none,+  codefont: none,+  linestretch: 1,   sectionnumbering: none,+  linkcolor: none,+  citecolor: none,+  filecolor: none,+  pagenumbering: "1",   doc, ) = {   set document(     title: title,-    author: authors.map(author => author.name),     keywords: keywords,   )+  set document(+      author: authors.map(author => content-to-string(author.name)).join(", ", last: " & "),+  ) if authors != none and authors != ()   set page(     paper: paper,     margin: margin,-    numbering: "1",+    numbering: pagenumbering,+    columns: cols   )-  set par(justify: true)++  set par(+    justify: true,+    leading: linestretch * 0.65em+  )   set text(lang: lang,            region: region,-           font: font,            size: fontsize)++  set text(font: font) if font != none+  show math.equation: set text(font: mathfont) if mathfont != none+  show raw: set text(font: codefont) if codefont != none+   set heading(numbering: sectionnumbering) -  if title != none {-    align(center)[#block(inset: 2em)[-      #text(weight: "bold", size: 1.5em)[#title]-    ]]+  show link: set text(fill: rgb(content-to-string(linkcolor))) if linkcolor != none+  show ref: set text(fill: rgb(content-to-string(citecolor))) if citecolor != none+  show link: this => {+    if filecolor != none and type(this.dest) == label {+      text(this, fill: rgb(content-to-string(filecolor)))+    } else {+      text(this)+    }   } -  if authors != none and authors != [] {-    let count = authors.len()-    let ncols = calc.min(count, 3)-    grid(-      columns: (1fr,) * ncols,-      row-gutter: 1.5em,-      ..authors.map(author =>-          align(center)[+  if title != none {+    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 {+                footnote(thanks, numbering: "*")+                counter(footnote).update(n => n - 1)+              }]+            #(+              if subtitle != none {+                parbreak()+                text(weight: "bold", size: 1.25em, hyphenate: false)[#subtitle]+              }+             )])+      }++      #if authors != none and authors != [] {+        let count = authors.len()+        let ncols = calc.min(count, 3)+        grid(+          columns: (1fr,) * ncols,+          row-gutter: 1.5em,+          ..authors.map(author => align(center)[             #author.name \             #author.affiliation \             #author.email-          ]-      )-    )-  }--  if date != none {-    align(center)[#block(inset: 1em)[-      #date-    ]]-  }+          ])+        )+      } -  if abstract != none {-    block(inset: 2em)[-    #text(weight: "semibold")[Abstract] #h(1em) #abstract-    ]-  }+      #if date != none {+        align(center)[#block(inset: 1em)[+            #date+          ]]+      } -  if cols == 1 {-    doc-  } else {-    columns(cols, doc)+      #if abstract != none {+        block(inset: 2em)[+          #text(weight: "semibold")[#abstract-title] #h(1em) #abstract+        ]+      }+    ])   }+  doc } #show: doc => conf(   title: [Pandoc Test Suite],   authors: (-    ( name: "John MacFarlane",+    ( name: [John MacFarlane],       affiliation: "",       email: "" ),-    ( name: "Anonymous",+    ( name: [Anonymous],       affiliation: "",       email: "" ),     ),-  date: "July 17, 2006",+  date: [July 17, 2006],+  abstract-title: [Abstract],+  pagenumbering: "1",   cols: 1,   doc, )  -This is a set of tests for pandoc. Most of them are adapted from John Gruber’s+This is a set of tests for pandoc. Most of them are adapted from John Gruber's markdown test suite.  #horizontalrule@@ -140,16 +187,15 @@  = Paragraphs <paragraphs>-Here’s a regular paragraph.+Here's a regular paragraph.  In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item. Because a hard-wrapped line in the middle of a paragraph looked like a list item. -Here’s one with a bullet. \* criminey.+Here's one with a bullet. \* criminey. -There should be a hard line break \-here.+There should be a hard line break \ here.  #horizontalrule @@ -296,7 +342,7 @@  + Item 1, graf one. -  Item 1. graf two. The quick brown fox jumped over the lazy dog’s back.+  Item 1. graf two. The quick brown fox jumped over the lazy dog's back.  + Item 2. @@ -308,7 +354,7 @@   - Tab     - Tab -Here’s another:+Here's another:  + First + Second:@@ -440,13 +486,13 @@  Multiple blocks with italics: -/ #emph[apple];: #block[+/ #emph[apple]: #block[ red fruit  contains seeds, crisp, pleasant to taste ] -/ #emph[orange];: #block[+/ #emph[orange]: #block[ orange fruit  ```@@ -462,11 +508,13 @@  / apple: #block[ red fruit+ computer ]  / orange: #block[ orange fruit+ bank ] @@ -523,7 +571,7 @@  This is #emph[emphasized] And this is #strong[strong]-Here’s a simple block:+Here's a simple block:  #block[ foo@@ -570,33 +618,33 @@ <hr /> ``` -Hr’s:+Hr's:  #horizontalrule  = Inline Markup <inline-markup>-This is #emph[emphasized];, and so #emph[is this];.+This is #emph[emphasized], and so #emph[is this]. -This is #strong[strong];, and so #strong[is this];.+This is #strong[strong], and so #strong[is this]. -An #emph[#link("/url")[emphasized link];];.+An #emph[#link("/url")[emphasized link]]. -#strong[#emph[This is strong and em.];]+#strong[#emph[This is strong and em.]] -So is #strong[#emph[this];] word.+So is #strong[#emph[this]] word. -#strong[#emph[This is strong and em.];]+#strong[#emph[This is strong and em.]] -So is #strong[#emph[this];] word.+So is #strong[#emph[this]] word.  This is code: `>`, `$`, `\`, `\$`, `<html>`. -#strike[This is #emph[strikeout];.]+#strike[This is #emph[strikeout].] -Superscripts: a#super[bc];d a#super[#emph[hello];] a#super[hello~there];.+Superscripts: a#super[bc]d a#super[#emph[hello]] a#super[hello~there]. -Subscripts: H#sub[2];O, H#sub[23];O, H#sub[many~of~them];O.+Subscripts: H#sub[2]O, H#sub[23]O, H#sub[many~of~them]O.  These should not be superscripts or subscripts, because of the unescaped spaces: a^b c^d, a\~b c\~d.@@ -611,14 +659,14 @@  'Oak,' 'elm,' and 'beech' are names of trees. So is 'pine.' -'He said, "I want to go."' Were you alive in the 70’s?+'He said, "I want to go."' Were you alive in the 70's?  Here is some quoted '`code`' and a-"#link("http://example.com/?foo=1&bar=2")[quoted link];".+"#link("http://example.com/?foo=1&bar=2")[quoted link]". -Some dashes: one—two — three—four — five.+Some dashes: one---two --- three---four --- five. -Dashes between numbers: 5–7, 255–66, 1987–1999.+Dashes between numbers: 5--7, 255--66, 1987--1999.  Ellipses…and…and…. @@ -632,11 +680,11 @@ - $alpha and omega$ - $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) $-- Here’s one that has a line break in it: $alpha + omega times x^2$.+- Here's some display math:+  $ 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:+These shouldn't be math:  - To get the famous equation, write `$e = mc^2$`. - \$22,000 is a #emph[lot] of money. So is \$34,000. (It worked if "lot" is@@ -644,7 +692,7 @@ - Shoes (\$20) and socks (\$5). - Escaped `$`: \$73 #emph[this should be emphasized] 23\$. -Here’s a LaTeX table:+Here's a LaTeX table:  #horizontalrule @@ -706,13 +754,13 @@ <links> == Explicit <explicit>-Just a #link("/url/")[URL];.+Just a #link("/url/")[URL]. -#link("/url/")[URL and title];.+#link("/url/")[URL and title]. -#link("/url/")[URL and title];.+#link("/url/")[URL and title]. -#link("/url/")[URL and title];.+#link("/url/")[URL and title].  #link("/url/")[URL and title] @@ -722,21 +770,21 @@  #link("mailto:nobody@nowhere.net")[Email link] -#link("")[Empty];.+#link("")[Empty].  == Reference <reference>-Foo #link("/url/")[bar];.+Foo #link("/url/")[bar]. -With #link("/url/")[embedded \[brackets\]];.+With #link("/url/")[embedded \[brackets\]].  #link("/url/")[b] by itself should be a link. -Indented #link("/url")[once];.+Indented #link("/url")[once]. -Indented #link("/url")[twice];.+Indented #link("/url")[twice]. -Indented #link("/url")[thrice];.+Indented #link("/url")[thrice].  This should \[not\]\[\] be a link. @@ -744,20 +792,20 @@ [not]: /url ``` -Foo #link("/url/")[bar];.+Foo #link("/url/")[bar]. -Foo #link("/url/")[biz];.+Foo #link("/url/")[biz].  == With ampersands <with-ampersands>-Here’s a-#link("http://example.com/?foo=1&bar=2")[link with an ampersand in the URL];.+Here's a+#link("http://example.com/?foo=1&bar=2")[link with an ampersand in the URL]. -Here’s a link with an amersand in the link text: #link("http://att.com/")[AT&T];.+Here's a link with an amersand in the link text: #link("http://att.com/")[AT&T]. -Here’s an #link("/script?foo=1&bar=2")[inline link];.+Here's an #link("/script?foo=1&bar=2")[inline link]. -Here’s an #link("/script?foo=1&bar=2")[inline link in pointy braces];.+Here's an #link("/script?foo=1&bar=2")[inline link in pointy braces].  == Autolinks <autolinks>@@ -785,13 +833,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 @@ -799,7 +847,7 @@ <footnotes> Here is a footnote reference,#footnote[Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document.]-and another.#footnote[Here’s the long note. This one contains multiple blocks.+and another.#footnote[Here's the long note. This one contains multiple blocks.  Subsequent blocks are indented to show that they belong to the footnote (as with list items).
+ test/writer.vimdoc view
@@ -0,0 +1,669 @@+                Pandoc Test Suite by John MacFarlane, Anonymous+++                                         Type |gO| to see the table of contents.+++This is a set of tests for pandoc. Most of them are adapted from John Gruber's+markdown test suite.++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++================================================================================+Headers                                                                  *headers*++--------------------------------------------------------------------------------+Level 2 with an embedded link /url                 *level-2-with-an-embedded-link*++LEVEL 3 WITH EMPHASIS                                      *level-3-with-emphasis*++Level 4                                                                  *level-4*++Level 5                                                                  *level-5*++================================================================================+Level 1                                                                  *level-1*++--------------------------------------------------------------------------------+Level 2 with emphasis                                      *level-2-with-emphasis*++LEVEL 3                                                                  *level-3*++with no blank line++--------------------------------------------------------------------------------+Level 2                                                                  *level-2*++with no blank line++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++================================================================================+Paragraphs                                                            *paragraphs*++Here's a regular paragraph.++In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item.+Because a hard-wrapped line in the middle of a paragraph looked like a list+item.++Here's one with a bullet. * criminey.++There should be a hard line break+here.++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++================================================================================+Block Quotes                                                        *block-quotes*++E-mail style:++  This is a block quote. It is pretty short.++  Code in a block quote:++  >+      sub status {+          print "working";+      }+<+  A list:++  1. item one+  2. item two++  Nested block quotes:++    nested++    nested++This should not be a block quote: 2 > 1.++And a following paragraph.++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++================================================================================+Code Blocks                                                          *code-blocks*++Code:++>+    ---- (should be four hyphens)++    sub status {+        print "working";+    }++    this code block is indented by one tab+<+And:++>+        this code block is indented by two tabs++    These should not be escaped:  \$ \\ \> \[ \{+<+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++================================================================================+Lists                                                                      *lists*++--------------------------------------------------------------------------------+Unordered                                                              *unordered*++Asterisks tight:++- asterisk 1+- asterisk 2+- asterisk 3++Asterisks loose:++- asterisk 1++- asterisk 2++- asterisk 3++Pluses tight:++- Plus 1+- Plus 2+- Plus 3++Pluses loose:++- Plus 1++- Plus 2++- Plus 3++Minuses tight:++- Minus 1+- Minus 2+- Minus 3++Minuses loose:++- Minus 1++- Minus 2++- Minus 3++--------------------------------------------------------------------------------+Ordered                                                                  *ordered*++Tight:++1. First+2. Second+3. Third++and:++1. One+2. Two+3. Three++Loose using tabs:++1. First++2. Second++3. Third++and using spaces:++1. One++2. Two++3. Three++Multiple paragraphs:++1. Item 1, graf one.++   Item 1. graf two. The quick brown fox jumped over the lazy dog's back.++2. Item 2.++3. Item 3.++--------------------------------------------------------------------------------+Nested                                                                    *nested*++- Tab+  - Tab+    - Tab++Here's another:++1. First+2. Second:+   - Fee+   - Fie+   - Foe+3. Third++Same thing but with paragraphs:++1. First++2. Second:++   - Fee+   - Fie+   - Foe++3. Third++--------------------------------------------------------------------------------+Tabs and spaces                                                  *tabs-and-spaces*++- this is a list item indented with tabs++- this is a list item indented with spaces++  - this is an example list item indented with tabs++  - this is an example list item indented with spaces++--------------------------------------------------------------------------------+Fancy list markers                                            *fancy-list-markers*++(2) begins with 2++(3) and now 3++    with a continuation++    iv. sublist with roman numerals, starting with 4+    v. more items+       (A) a subsublist+       (B) a subsublist++Nesting:++A. Upper Alpha+   I. Upper Roman.+      (6) Decimal start with 6+          c) Lower alpha with paren++Autonumbering:++1. Autonumber.+2. More.+   1. Nested.++Should not be a list item:++M.A. 2007++B. Williams++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++================================================================================+Definition Lists                                                *definition-lists*++Tight using spaces:++apple+    red fruit+orange+    orange fruit+banana+    yellow fruit++Tight using tabs:++apple+    red fruit+orange+    orange fruit+banana+    yellow fruit++Loose:++apple+    red fruit++orange+    orange fruit++banana+    yellow fruit++Multiple blocks with italics:++apple+    red fruit++    contains seeds, crisp, pleasant to taste++orange+    orange fruit++    >+        { orange code block }+<+      orange block quote++Multiple definitions, tight:++apple+    red fruit+    computer+orange+    orange fruit+    bank++Multiple definitions, loose:++apple+    red fruit++    computer++orange+    orange fruit++    bank++Blank line after term, indented marker, alternate markers:++apple+    red fruit++    computer++orange+    orange fruit++    1. sublist+    2. sublist++================================================================================+HTML Blocks                                                          *html-blocks*++Simple block on one line:++foo+And nested without indentation:++foo++bar+Interpreted markdown in a table:++This is emphasized+And this is strong+Here's a simple block:++foo++This should be a code block, though:++>+    <div>+        foo+    </div>+<+As should this:++>+    <div>foo</div>+<+Now, nested:++foo+This should just be an HTML comment:++Multiline:++Code block:++>+    <!-- Comment -->+<+Just plain comment, with trailing spaces on the line:++Code:++>+    <hr />+<+Hr's:++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++================================================================================+Inline Markup                                                      *inline-markup*++This is emphasized, and so is this.++This is strong, and so is this.++An emphasized link /url.++This is strong and em.++So is this word.++This is strong and em.++So is this word.++This is code: `>`, `$`, `\`, `\$`, `<html>`.++This is strikeout.++Superscripts: abcd ahello ahello there.++Subscripts: H2O, H23O, Hmany of themO.++These should not be superscripts or subscripts, because of the unescaped spaces:+a^b c^d, a~b c~d.++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++================================================================================+Smart quotes, ellipses, dashes                      *smart-quotes-ellipses-dashes*++"Hello," said the spider. "'Shelob' is my name."++'A', 'B', and 'C' are letters.++'Oak,' 'elm,' and 'beech' are names of trees. So is 'pine.'++'He said, "I want to go."' Were you alive in the 70's?++Here is some quoted '`code`' and a "quoted link+http://example.com/?foo=1&bar=2".++Some dashes: one---two --- three---four --- five.++Dashes between numbers: 5--7, 255--66, 1987--1999.++Ellipses...and...and....++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++================================================================================+LaTeX                                                                      *latex*++- +- `$2+2=4$`+- `$x \in y$`+- `$\alpha \wedge \omega$`+- `$223$`+- `$p$`-Tree+- Here's some display math:+  `$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$`+- Here's one that has a line break in it: `$\alpha + \omega \times x^2$`.++These shouldn't be math:++- To get the famous equation, write `$e = mc^2$`.+- $22,000 is a lot of money. So is $34,000. (It worked if "lot" is emphasized.)+- Shoes ($20) and socks ($5).+- Escaped `$`: $73 this should be emphasized 23$.++Here's a LaTeX table:++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++================================================================================+Special Characters                                            *special-characters*++Here is some unicode:++- I hat: Î+- o umlaut: ö+- section: §+- set membership: ∈+- copyright: ©++AT&T has an ampersand in their name.++AT&T is another way to write it.++This & that.++4 < 5.++6 > 5.++Backslash: \++Backtick: `++Asterisk: *++Underscore: _++Left brace: {++Right brace: }++Left bracket: [++Right bracket: ]++Left paren: (++Right paren: )++Greater-than: >++Hash: #++Period: .++Bang: !++Plus: +++Minus: -++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++================================================================================+Links                                                                      *links*++--------------------------------------------------------------------------------+Explicit                                                                *explicit*++Just a URL /url/.++URL and title /url/.++URL and title /url/.++URL and title /url/.++URL and title /url/++URL and title /url/++with_underscore /url/with_underscore++Email link nobody@nowhere.net++Empty .++--------------------------------------------------------------------------------+Reference                                                              *reference*++Foo bar /url/.++With embedded [brackets] /url/.++b /url/ by itself should be a link.++Indented once /url.++Indented twice /url.++Indented thrice /url.++This should [not][] be a link.++>+    [not]: /url+<+Foo bar /url/.++Foo biz /url/.++--------------------------------------------------------------------------------+With ampersands                                                  *with-ampersands*++Here's a link with an ampersand in the URL http://example.com/?foo=1&bar=2.++Here's a link with an amersand in the link text: AT&T http://att.com/.++Here's an inline link /script?foo=1&bar=2.++Here's an inline link in pointy braces /script?foo=1&bar=2.++--------------------------------------------------------------------------------+Autolinks                                                              *autolinks*++With an ampersand: http://example.com/?foo=1&bar=2++- In a list?+- http://example.com/+- It should.++An e-mail address: nobody@nowhere.net++  Blockquoted: http://example.com/++Auto-links should not occur here: `<http://example.com/>`++>+    or here: <http://example.com/>+<+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++================================================================================+Images                                                                    *images*++From "Voyage dans la Lune" by Georges Melies (1902):++Here is a movie icon.++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++================================================================================+Footnotes                                                              *footnotes*++Here is a footnote reference, |footnote1| and another. |footnote2| This should+not be a footnote reference, because it contains a space.[^my note] Here is an+inline note. |footnote3|++  Notes can go in quotes. |footnote4|++1. And in list items. |footnote5|++This paragraph should not be part of the note, as it is not indented.++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++                                                                       *footnote1*+Here is the footnote. It can go anywhere after the footnote reference. It need+not be placed at the end of the document.++                                                                       *footnote2*+Here's the long note. This one contains multiple blocks.++Subsequent blocks are indented to show that they belong to the footnote (as with+list items).++>+      { <code> }+<+If you want, you can indent every line, but you can also be lazy and just indent+the first line of each block.++                                                                       *footnote3*+This is easier to type. Inline notes may contain links http://google.com and `]`+verbatim characters, as well as [bracketed text].++                                                                       *footnote4*+In quote.++                                                                       *footnote5*+In list.++ vim:tw=80:sw=4:ts=4:ft=help:norl:et:
test/writers-lang-and-dir.context view
@@ -11,7 +11,6 @@ \setupinteractionscreen[option={bookmark,title}]  \setuppagenumbering[location={footer,middle}]-\setupbackend[export=yes] \setupstructure[state=start,method=auto]  % use microtypography
test/writers-lang-and-dir.latex view
@@ -1,10 +1,17 @@ % Options for packages loaded elsewhere \PassOptionsToPackage{unicode}{hyperref} \PassOptionsToPackage{hyphens}{url}-% \documentclass[+  ngerman,+  british,+  nswissgerman,+  spanish,+  french,+  english, ]{article}+\usepackage{xcolor} \usepackage{amsmath,amssymb}+\setcounter{secnumdepth}{-\maxdimen} % remove section numbering \usepackage{iftex} \ifPDFTeX   \usepackage[T1]{fontenc}@@ -35,28 +42,17 @@ }{% if KOMA class   \KOMAoptions{parskip=half}} \makeatother-\usepackage{xcolor}-\setlength{\emergencystretch}{3em} % prevent overfull lines-\providecommand{\tightlist}{%-  \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}-\setcounter{secnumdepth}{-\maxdimen} % remove section numbering \ifLuaTeX-\usepackage[bidi=basic]{babel}+\usepackage[bidi=basic,shorthands=off]{babel} \else-\usepackage[bidi=default]{babel}+\usepackage[bidi=default,shorthands=off]{babel} \fi-\babelprovide[main,import]{english}-\babelprovide[import]{ngerman}-\babelprovide[import]{british}-\babelprovide[import]{nswissgerman}-\babelprovide[import]{spanish}-\babelprovide[import]{french}-% get rid of language-specific shorthands (see #6817):-\let\LanguageShortHands\languageshorthands-\def\languageshorthands#1{} \ifLuaTeX-  \usepackage{selnolig}  % disable illegal ligatures+  \usepackage{selnolig} % disable illegal ligatures \fi+\setlength{\emergencystretch}{3em} % prevent overfull lines+\providecommand{\tightlist}{%+  \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}} \ifPDFTeX   \TeXXeTstate=1   \newcommand{\RL}[1]{\beginR #1\endR}@@ -64,9 +60,19 @@   \newenvironment{RTL}{\beginR}{\endR}   \newenvironment{LTR}{\beginL}{\endL} \fi+\ifluatex+  \newcommand{\RL}[1]{\bgroup\textdir TRT#1\egroup}+  \newcommand{\LR}[1]{\bgroup\textdir TLT#1\egroup}+  \newenvironment{RTL}{\textdir TRT\pardir TRT\bodydir TRT}{}+  \newenvironment{LTR}{\textdir TLT\pardir TLT\bodydir TLT}{}+\fi \usepackage{bookmark} \IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available \urlstyle{same}+% fallback for those not using the hyperref driver hyperxmp:+\makeatletter+\@ifundefined{xmpquote}{\newcommand{\xmpquote}[1]{#1}}{}+\makeatother \hypersetup{   pdflang={en},   hidelinks,
+ test/xlsx-reader/basic.native view
@@ -0,0 +1,381 @@+Pandoc+  Meta { unMeta = fromList [] }+  [ Header 2 ( "sheet-1" , [] , [] ) [ Str "Main" ]+  , Table+      ( "" , [] , [] )+      (Caption Nothing [])+      [ ( AlignDefault , ColWidthDefault )+      , ( AlignDefault , ColWidthDefault )+      , ( AlignDefault , ColWidthDefault )+      ]+      (TableHead+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Plain [ Strong [ Str "Person" ] ] ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Plain [ Strong [ Str "Age" ] ] ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Plain [ Strong [ Str "Location" ] ] ]+             ]+         ])+      [ TableBody+          ( "" , [] , [] )+          (RowHeadColumns 0)+          []+          [ Row+              ( "" , [] , [] )+              [ Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [ Str "Anton" , Space , Str "Antich" ] ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [ Str "23.0" ] ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [ Str "Switzerland" ] ]+              ]+          , Row+              ( "" , [] , [] )+              [ Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [ Str "James" , Space , Str "Bond" ] ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [ Str "35.0" ] ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [ Str "Moscow" ] ]+              ]+          , Row+              ( "" , [] , [] )+              [ Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [] ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [] ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [] ]+              ]+          , Row+              ( "" , [] , [] )+              [ Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [] ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [] ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [] ]+              ]+          , Row+              ( "" , [] , [] )+              [ Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain+                      [ Str "Just"+                      , Space+                      , Str "a"+                      , Space+                      , Str "random"+                      , Space+                      , Str "cell"+                      ]+                  ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [] ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [] ]+              ]+          ]+      ]+      (TableFoot ( "" , [] , [] ) [])+  , Header 2 ( "sheet-2" , [] , [] ) [ Str "Secondary" ]+  , Table+      ( "" , [] , [] )+      (Caption Nothing [])+      [ ( AlignDefault , ColWidthDefault )+      , ( AlignDefault , ColWidthDefault )+      , ( AlignDefault , ColWidthDefault )+      , ( AlignDefault , ColWidthDefault )+      , ( AlignDefault , ColWidthDefault )+      ]+      (TableHead+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Plain+                     [ Str "Sum"+                     , Space+                     , Str "of"+                     , Space+                     , Str "Age"+                     ]+                 ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Plain [ Str "Column" , Space , Str "Labels" ] ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Plain [] ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Plain [] ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Plain [] ]+             ]+         ])+      [ TableBody+          ( "" , [] , [] )+          (RowHeadColumns 0)+          []+          [ Row+              ( "" , [] , [] )+              [ Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [ Str "Row" , Space , Str "Labels" ] ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [ Str "Moscow" ] ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [ Str "Switzerland" ] ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [ Str "(blank)" ] ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [ Str "Grand" , Space , Str "Total" ] ]+              ]+          , Row+              ( "" , [] , [] )+              [ Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [ Str "Anton" , Space , Str "Antich" ] ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [] ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [ Str "23.0" ] ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [] ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [ Str "23.0" ] ]+              ]+          , Row+              ( "" , [] , [] )+              [ Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [ Str "James" , Space , Str "Bond" ] ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [ Str "35.0" ] ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [] ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [] ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [ Str "35.0" ] ]+              ]+          , Row+              ( "" , [] , [] )+              [ Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [ Str "(blank)" ] ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [] ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [] ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [] ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [] ]+              ]+          , Row+              ( "" , [] , [] )+              [ Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [ Str "Grand" , Space , Str "Total" ] ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [ Str "35.0" ] ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [ Str "23.0" ] ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [] ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [ Str "58.0" ] ]+              ]+          ]+      ]+      (TableFoot ( "" , [] , [] ) [])+  ]
+ test/xlsx-reader/basic.xlsx view

binary file changed (absent → 13604 bytes)

xml-light/Text/Pandoc/XML/Light.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.XML.Light-   Copyright   : Copyright (C) 2021-2023 John MacFarlane+   Copyright   : Copyright (C) 2021-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>
xml-light/Text/Pandoc/XML/Light/Output.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.XML.Light.Output-   Copyright   : Copyright (C) 2007 Galois, Inc., 2021-2023 John MacFarlane+   Copyright   : Copyright (C) 2007 Galois, Inc., 2021-2024 John MacFarlane    License     : GNU GPL, version 2 or above  @@ -35,7 +35,7 @@ import Text.Pandoc.XML.Light.Types  ----- duplicates functinos from Text.XML.Output+-- duplicates functions from Text.XML.Output --  -- | The XML 1.0 header
xml-light/Text/Pandoc/XML/Light/Proc.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE FlexibleInstances #-} {- |    Module      : Text.Pandoc.XML.Light.Proc-   Copyright   : Copyright (C) 2007 Galois, Inc., 2021-2023 John MacFarlane+   Copyright   : Copyright (C) 2007 Galois, Inc., 2021-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>
xml-light/Text/Pandoc/XML/Light/Types.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE DeriveDataTypeable #-} {- |    Module      : Text.Pandoc.XML.Light.Types-   Copyright   : Copyright (C) 2007 Galois, Inc., 2021-2023 John MacFarlane+   Copyright   : Copyright (C) 2007 Galois, Inc., 2021-2024 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>