packages feed

pandoc 3.7.0.2 → 3.10

raw patch · 527 files changed

Files

AUTHORS.md view
@@ -2,10 +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@@ -32,6 +34,8 @@ - Aner Lucero - Anti-Distinctlyminty - Antoine Latter+- Anton Antich+- Anton Melnikov - Antonio Terceiro - Arata Mizuki - Arata Mizuki@@ -39,6 +43,7 @@ - Arlo O'Keeffe - Artem Pelenitsyn - Artyom Kazak+- Asliddinbek Azizovich - B. Scott Michel - Bastien Dumont - Ben Firshman@@ -72,18 +77,21 @@ - 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@@ -107,12 +115,14 @@ - 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@@ -126,6 +136,7 @@ - Florian Eitel - Florian Klink - Florian Kohrt+- FoxChillz - Francesco Mazzoli - Francesco Occhipinti - François Gannaz@@ -170,6 +181,7 @@ - Ivar de Bruin - Ivo Clarysse - Jaap de Jong+- Jacob Larkin - James J Balamuta - J. B. Rainsberger - J. Lewis Muir@@ -180,6 +192,7 @@ - Jakob Voß - James Aspnes - James P. Ascher+- James Barlow - James Scott-Brown - Jamie F. Olson - Jan Larres@@ -203,6 +216,7 @@ - Jez Cope - Joe Hermaszewski - Joe Hillenbrand+- Johan Larsson - John KetzerX - John Luke Bentley - John MacFarlane@@ -225,6 +239,7 @@ - Justin Bogner - Justin Wood - Karl Pettersson+- Keenan Brock - Keiichiro Shikano - Kelsey Hightower - Kevin Broch@@ -274,6 +289,7 @@ - Max Bolingbroke - Max Heller - Max Rydahl Andersen+- Meher Chaitanya - Merijn Verstraaten - Michael Beaumont - Michael Chladek@@ -327,6 +343,7 @@ - Pavol Otto - Per Christian Gaustad - Pete Ryland+- Peter Briggs - Peter Fabinksi - Peter Wang - Philip Pesca@@ -340,14 +357,19 @@ - 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@@ -356,6 +378,7 @@ - Santiago Zarate - Sascha Wilde - Scott Morrison+- Sean Soon - Sebastian Talmon - Sebbones - Sen-wen Deng@@ -367,6 +390,7 @@ - Shim Myeongseob - Shin Sang-jae - Sidarth Kapur+- Sidney Mau - Sidharth Kapur - Simon Hengel - Simon Schuster@@ -429,15 +453,18 @@ - 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@@ -454,6 +481,7 @@ - etclub - favonia - guqicun+- har7an - harabat - hseg - infinity0x@@ -465,12 +493,14 @@ - lux-lth - luz paz - lwolfsonkin+- massifrg - mbracke - mbrackeantidot - mh4ckt3mh4ckt1c4s - mjfs - mt_caret - nbehrnd+- nibras shami - niszet - nkalvi - nuew@@ -483,6 +513,7 @@ - priiduonu - qerub - quasicomputational+- reptee - ricnorr - robabla - roblabla@@ -506,3 +537,4 @@ - wiefling - willj-dev - wuffi+- λx.x
CONTRIBUTING.md view
@@ -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 -----@@ -448,7 +448,7 @@ 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.
@@ -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@@ -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
@@ -138,9 +138,6 @@  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@@ -265,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@@ -293,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: @@ -335,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.@@ -402,7 +401,6 @@ [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://ports.macports.org/port/pandoc/ [MacTeX]: https://tug.org/mactex/ [OpenBSD ports]: https://cvsweb.openbsd.org/ports/textproc/pandoc/
MANUAL.txt view
@@ -1,7 +1,7 @@ --- title: Pandoc User's Guide author: John MacFarlane-date: 2025-05-28+date: 2026-06-03 ---  # Synopsis@@ -44,7 +44,7 @@  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:+use the `-o`/`--output` option:      pandoc -o output.html input.txt @@ -151,12 +151,13 @@ 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 [`upquote`] and [`microtype`]-packages are used if available, and [`csquotes`] will be used+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].  The following packages will be used to improve+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),@@ -182,6 +183,7 @@ [`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@@ -191,6 +193,7 @@ [`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@@ -230,6 +233,7 @@ :   Specify input format.  *FORMAT* can be:      ::: {#input-formats}+    - `asciidoc` ([AsciiDoc] markup)     - `bibtex` ([BibTeX] bibliography)     - `biblatex` ([BibLaTeX] bibliography)     - `bits` ([BITS] XML, alias for `jats`)@@ -270,6 +274,7 @@     - `opml` ([OPML])     - `org` ([Emacs Org mode])     - `pod` (Perl's [Plain Old Documentation])+    - `pptx` ([PowerPoint])     - `ris` ([RIS] bibliography)     - `rtf` ([Rich Text Format])     - `rst` ([reStructuredText])@@ -279,6 +284,8 @@     - `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     ::: @@ -297,6 +304,12 @@     - `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)@@ -357,6 +370,8 @@     - `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@@ -401,17 +416,17 @@  `-d` *FILE*, `--defaults=`*FILE* -:   Specify a set of default option settings.  *FILE* is a YAML+:   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 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.+    (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` @@ -420,6 +435,24 @@          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.@@ -461,7 +494,7 @@ `--list-highlight-styles`  :   List supported styles for syntax highlighting, one per line.-    See `--highlight-style`.+    See `--syntax-highlighting`.  `-v`, `--version` @@ -497,7 +530,7 @@ [Jira]: https://jira.atlassian.com/secure/WikiRendererHelpAction.jspa?section=all [txt2tags]: https://txt2tags.org [EPUB]: http://idpf.org/epub-[OPML]: http://dev.opml.org/spec2.html+[OPML]: https://opml.org/spec2.opml [OpenDocument XML]: https://www.oasis-open.org/2021/06/16/opendocument-v1-3-oasis-standard-published/ [ODT]: https://en.wikipedia.org/wiki/OpenDocument [Plain Old Documentation]: https://perldoc.perl.org/perlpod@@ -506,6 +539,8 @@ [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@@ -527,7 +562,7 @@ [reveal.js]: https://revealjs.com/ [FictionBook2]: http://www.fictionbook.org/index.php/Eng:XML_Schema_Fictionbook_2.1 [Jupyter notebook]: https://nbformat.readthedocs.io/en/latest/-[InDesign ICML]: https://manualzz.com/doc/9627253/adobe-indesign-cs6-idml-cookbook+[InDesign ICML]: https://web.archive.org/web/20211006210211/https://wwwimages.adobe.com/www.adobe.com/content/dam/acom/en/devnet/indesign/sdk/cs6/idml/idml-cookbook.pdf [TEI Simple]: https://github.com/TEIC/TEI-Simple [Muse]: https://amusewiki.org/library/manual [PowerPoint]: https://en.wikipedia.org/wiki/Microsoft_PowerPoint@@ -539,6 +574,12 @@ [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} @@ -713,7 +754,7 @@     affected paragraph break. This option only affects the docx     reader. -`--extract-media=`*DIR*+`--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@@ -725,6 +766,10 @@     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@@ -738,6 +783,13 @@     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.@@ -786,10 +838,10 @@     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 keyword=Joe -V author=Sue` makes `author` contain a list+    `-V author=Joe -V author=Sue` makes `author` contain a list     of strings: `Joe` and `Sue`. -`--variable-json=`*KEY*[`=`:*JSON*]+`--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;@@ -800,24 +852,6 @@     separate *KEY* from *VAL*. If the variable already has a     value, this value will be replaced. -`--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`@@ -884,13 +918,10 @@     on `man`, `docbook4`, `docbook5`, or `jats` output.      Note that if you are producing a PDF via `ms` and using-    (the default) `pdfroff` as a `--pdf-engine`, 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`. If `groff` is-    used as the `--pdf-engine`, the table of contents will-    always appear at the end of the document.+    (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* @@ -922,18 +953,25 @@     inside raw HTML blocks when the `markdown_in_html_blocks`     extension is not set. -`--no-highlight`+`--syntax-highlighting=default|none|idiomatic|`*STYLE*`|`*FILE* -:   Disables syntax highlighting for code blocks and inlines, even when-    a language attribute is given.+:   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. -`--highlight-style=`*STYLE*|*FILE*+    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. -:   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+    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@@ -944,11 +982,24 @@     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 `--highlight-style`.  This option may be used with+    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.@@ -1171,7 +1222,10 @@  `--listings[=true|false]` -:   Use the [`listings`] package for LaTeX code blocks. The package+:   *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].@@ -1259,7 +1313,7 @@         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+        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:@@ -1378,7 +1432,7 @@     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+    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`.@@ -1489,7 +1543,7 @@         `pagedjs-cli`;         see [print-css.rocks](https://print-css.rocks) for a good         introduction to PDF generation from HTML/CSS)-    - `-t ms`:  `pdfroff`+    - `-t ms`:  `groff`     - `-t typst`: `typst`      This option is normally intended to be used when a PDF@@ -1700,6 +1754,7 @@    92 PandocUTF8DecodingError    93 PandocIpynbDecodingError    94 PandocUnsupportedCharsetError+   95 PandocInputNotTextError    97 PandocCouldNotFindDataFileError    98 PandocCouldNotFindMetadataFileError    99 PandocResourceNotFound@@ -1708,7 +1763,9 @@ # Defaults files  The `--defaults` option may be used to specify a package-of options, in the form of a YAML file.+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@@ -1718,6 +1775,12 @@ 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: @@ -1910,6 +1973,11 @@ | ```                              | ```                               | +----------------------------------+-----------------------------------+ | ```                              | ``` yaml                          |+| --typst-input foo=bar            | typst-inputs:                     |+|                                  |   foo: bar                        |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          | | --trace                          | trace: true                       | | ```                              | ```                               | +----------------------------------+-----------------------------------+@@ -1951,7 +2019,7 @@ | ```                              | ```                               | +----------------------------------+-----------------------------------+ | ```                              | ``` yaml                          |-| --wrap 60                        | wrap: 60                          |+| --wrap preserve                  | wrap: "preserve"                  | | ```                              | ```                               | +----------------------------------+-----------------------------------+ | ```                              | ``` yaml                          |@@ -1975,11 +2043,11 @@ | ```                              | ```                               | +----------------------------------+-----------------------------------+ | ```                              | ``` yaml                          |-| --no-highlight                   | highlight-style: null             |+| --no-highlight                   | syntax-highlighting: 'none'       | | ```                              | ```                               | +----------------------------------+-----------------------------------+ | ```                              | ``` yaml                          |-| --highlight-style kate           | highlight-style: kate             |+| --syntax-highlighting kate       | syntax-highlighting: kate         | | ```                              | ```                               | +----------------------------------+-----------------------------------+ | ```                              | ``` yaml                          |@@ -2728,7 +2796,7 @@     documents  `abstract-title`-:   title of abstract, currently used only in HTML, EPUB, and docx.+:   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. @@ -2910,6 +2978,13 @@ :   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`. @@ -2933,6 +3008,9 @@ `logo` :   logo image for slides +`logooptions`+:   options for logo image (e.g., `width`, `height`)+ `navigation` :   controls navigation symbols (default is `empty` for no navigation     symbols; other valid values are `frame`, `vertical`, and `horizontal`)@@ -2950,7 +3028,7 @@ :   image for title slide: can be a list  `titlegraphicoptions`-:   options for title slide image+:   options for title slide image (e.g., `width`, `height`)  `shorttitle`, `shortsubtitle`, `shortauthor`, `shortinstitute`, `shortdate` :   some beamer themes use short versions of the title, subtitle, author,@@ -3018,6 +3096,11 @@         - heightrounded         ... +`shorthands`+:   Enable language-specific shorthands when loading `babel`.+    (By default, pandoc includes `shorthands=off` when loading+    `babel`, disabling language-specific shorthands.)+ `hyperrefoptions` :   option for [`hyperref`] package, e.g. `linktoc=all`;     repeat for multiple options:@@ -3207,6 +3290,27 @@ `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@@ -3313,14 +3417,14 @@ `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 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/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+[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@@ -3366,7 +3470,7 @@ ### Variables for Typst  `template`-:   Typst template to use.+:   Typst template to use (relative path only).  `margin` :   A dictionary with the fields defined in the Typst documentation:@@ -3391,6 +3495,19 @@ `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`@@ -3528,7 +3645,7 @@    `html`  output formats-:  `markdown`, `latex`, `context`, `rst`+:  `markdown`, `latex`, `context`, `org`, `rst`  enabled by default in :  `markdown`, `latex`, `context` (both input and output)@@ -3556,13 +3673,13 @@ This extension can be enabled/disabled for the following formats:  input formats-:  `markdown`, `latex`, `rst`, `mediawiki`, `textile`+:  `markdown`, `latex`, `rst`, `mediawiki`, `textile`, `man`  output formats :  `markdown`, `muse`  enabled by default in-:  `markdown`, `muse`+:  `markdown`, `muse`, `man`  The default algorithm used to derive the identifier from the heading text is:@@ -3878,6 +3995,21 @@ 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@@ -4233,10 +4365,10 @@ 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.+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 @@ -4474,19 +4606,19 @@ 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:+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+    : Definition     with lazy continuation. -        Second paragraph of the definition.+      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@@ -4502,9 +4634,6 @@       ~ 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/).@@ -4849,6 +4978,14 @@  [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` ###@@ -4946,6 +5083,7 @@ (`...`) at the bottom.  The initial line `---` must not be followed by a blank line. A YAML metadata block may occur anywhere in the document, but if it is not at the beginning, it must be preceded by a blank line.+(Note that JSON may be used as well, because JSON is a subset of YAML.)  Note that, because of the way pandoc concatenates input files when several are provided, you may also keep the metadata in a@@ -5052,10 +5190,10 @@       \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:+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@@ -5524,22 +5662,34 @@  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.+`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.) -Here are some examples:+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. -    [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'+Here are some examples of reference links and link definitions; -The URL may optionally be surrounded by angle brackets:+    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:@@ -5553,18 +5703,14 @@      [Foo]: /bar/baz -In an *implicit* reference link, the second pair of brackets is-empty:--    See [my website][].--    [my website]: http://foo.bar.baz+The link definition may come either before or after a+reference link that uses the label. -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:+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].     >@@ -5610,12 +5756,12 @@  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.+image's description will be used as the caption. -    ![This is the caption](/url/of/image.png)+    ![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 (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. @@ -5623,12 +5769,24 @@ 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)\+    ![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:@@ -5878,6 +6036,17 @@ 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@@ -6085,9 +6254,6 @@    [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 -Note: This extension currently only works with commonmark:-`commonmark`, `gfm`, `commonmark_x`.- ### Extension: `autolink_bare_uris` ###  Makes all absolute URIs into links, even when not surrounded by@@ -6109,33 +6275,6 @@ 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:@@ -6439,7 +6578,7 @@ ## 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:+in a div with id `refs`, if one exists:[^note-on-refs]      ::: {#refs}     :::@@ -6448,6 +6587,13 @@ 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)@@ -6833,6 +6979,23 @@ 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@@ -7025,8 +7188,10 @@   ~ Either a string value or an object with fields `text` and     `scheme`.  Valid values for `scheme` are `ISBN-10`,     `GTIN-13`, `UPC`, `ISMN-10`, `DOI`, `LCCN`, `GTIN-14`,-    `ISBN-13`, `Legal deposit number`, `URN`, `OCLC`,-    `ISMN-13`, `ISBN-A`, `JP`, `OLCC`.+    `ISBN-13`, `Legal deposit number`, `URN`, `OCLC number`,+    `Co-publisher’s ISBN-13`, `ISMN-13`, `ISBN-A`, `JP e-code`,+    `OLCC number`, `JP Magazine ID`, `UPC-12+5`, `BNF Control number`,+    `ISSN-13`, `ARK`, `Digital file internal version number`.  `title`   ~ Either a string value, or an object with fields `file-as` and@@ -7361,31 +7526,132 @@ cause Setext-style headings to be used; and `--preserve-tabs` will prevent tabs from being turned to spaces. +# Vimdoc++Vimdoc writer generates Vim help files and makes use of the following metadata+variables:++``` yaml+abstract: "A short description"+author: Author+title: Title++# Vimdoc-specific+filename: "definition-lists.txt"+vimdoc-prefix: pandoc+```++Complete header requires `abstract`, `author`, `title` and `filename` to+be set. Compiling file with such metadata produces the following file+(assumes `--standalone`, see [Templates]):++``` vimdoc+*definition-lists.txt*  A short description++                            Title by Author+++                                 Type |gO| to see the table of contents.++[...]++ vim:tw=72:sw=4:ts=4:ft=help:norl:et:+```++If `vimdoc-prefix` is set, all non-command tags are prefixed with its+value, it is used to prevent tag collision: all headers have a tag+(either inferred or explicit) and multiple help pages can have the same+header names, therefore collision is to be expected. Let our input be+the following markdown file:++``` markdown+## Header++`:[range]Fnl {expr}`{#:Fnl}+:   Evaluates {expr} or range++`vim.b`{#vim.b}+:   Buffer-scoped (`:h b:`) variables for the current buffer. Invalid or unset+    key returns `nil`. Can be indexed with an integer to access variables for a+    specific buffer.++[Span]{#span}+:   generic inline container for phrasing content, which does not inherently+    represent anything.+```++Convert it to vimdoc:++``` vimdoc+------------------------------------------------------------------------+Header                                                            *header*++:[range]Fnl {expr}                                                  *:Fnl*+    Evaluates {expr} or range+`vim.b`                                                            *vim.b*+    Buffer-scoped (|b:|) variables for the current buffer. Invalid or+    unset key returns `nil`. Can be indexed with an integer to access+    variables for a specific buffer.+Span                                                                *span*+    generic inline container for phrasing content, which does not+    inherently represent anything.+```++Convert it to vimdoc with metadata variable set (e.g. with+`-M vimdoc-prefix=pandoc`)++``` vimdoc+------------------------------------------------------------------------+Header                                                     *pandoc-header*++:[range]Fnl {expr}                                                  *:Fnl*+    Evaluates {expr} or range+`vim.b`                                                     *pandoc-vim.b*+    Buffer-scoped (|b:|) variables for the current buffer. Invalid or+    unset key returns `nil`. Can be indexed with an integer to access+    variables for a specific buffer.+Span                                                         *pandoc-span*+    generic inline container for phrasing content, which does not+    inherently represent anything.+```++`vim.b` and `Span` got their prefixes but not `:Fnl` because ex-commands+(those starting with `:`) don't get a prefix, since they are considered+unique across help pages.++In both cases `:help b:` became reference `|b:|` (also works with+`:h b:`). Links pointing to either <https://vimhelp.org/> or+<https://neovim.io/doc/user> become references too.++Vim traditionally wraps at 78, but Pandoc defaults to 72. Use+`--columns 78` to match Vim.+ # Syntax highlighting  Pandoc will automatically highlight syntax in [fenced code blocks] that are marked with a language name.  The Haskell library [skylighting] is used for highlighting. Currently highlighting is supported only for-HTML, EPUB, Docx, Ms, Man, and LaTeX/PDF output. To see a list+HTML, EPUB, Docx, Ms, Man, Typst, and LaTeX/PDF output. To see a list of language names that pandoc will recognize, type `pandoc --list-highlight-languages`. -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`.+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 `--highlight-style`. To-get a JSON version of the `pygments` style, for example:+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 --highlight-style my.theme+    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@@ -7397,8 +7663,26 @@ 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 the `--no-highlight` option.+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@@ -7451,6 +7735,14 @@ For docx or odt output, you don't need to enable any extensions for custom styles to work. +For icml output, you can also set an `object-style` in images:++    ![Image with object style](myImage.jpg){object-style="fixedSizeImage"}++In InDesign you'll see that object style given to the image,+and you'll be able to customize it, or load its definition from+a template of yours.+ [pandoc filters]: https://pandoc.org/filters.html  ## Input@@ -7556,6 +7848,11 @@ `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).@@ -7569,10 +7866,10 @@ 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.+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@@ -7584,6 +7881,25 @@ 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@@ -7610,7 +7926,7 @@  ## Prince XML -The non-free HTML-to-PDf converter `prince` has extensive support+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 \@@ -7698,7 +8014,7 @@    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+   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
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@@ -87,10 +88,12 @@ - `native` (native Haskell) - `odt` ([OpenDocument text   document](https://en.wikipedia.org/wiki/OpenDocument))-- `opml` ([OPML](http://dev.opml.org/spec2.html))+- `opml` ([OPML](https://opml.org/spec2.opml)) - `org` ([Emacs Org mode](https://orgmode.org)) - `pod` (Perl’s [Plain Old   Documentation](https://perldoc.perl.org/perlpod))+- `pptx`+  ([PowerPoint](https://en.wikipedia.org/wiki/Microsoft_PowerPoint)) - `ris` ([RIS](https://en.wikipedia.org/wiki/RIS_(file_format))   bibliography) - `rtf` ([Rich Text@@ -105,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@@ -123,6 +129,17 @@ - `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)@@ -157,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@@ -189,7 +206,7 @@ - `native` (native Haskell) - `odt` ([OpenDocument text   document](https://en.wikipedia.org/wiki/OpenDocument))-- `opml` ([OPML](http://dev.opml.org/spec2.html))+- `opml` ([OPML](https://opml.org/spec2.opml)) - `opendocument` ([OpenDocument   XML](https://www.oasis-open.org/2021/06/16/opendocument-v1-3-oasis-standard-published/)) - `org` ([Emacs Org mode](https://orgmode.org))@@ -216,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@@ -262,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 
changelog.md view
@@ -1,3837 +1,5477 @@ # Revision history for pandoc -## 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 Tetx.Pnadoc.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.-    +## 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.
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/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>@@ -604,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/epub.css view
@@ -26,9 +26,6 @@   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"@@ -250,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/common.latex view
@@ -69,6 +69,7 @@ $-- $if(tables)$ \usepackage{longtable,booktabs,array}+\newcounter{none} % for unnumbered tables $if(multirow)$ \usepackage{multirow} $endif$@@ -183,9 +184,9 @@ $-- $if(lang)$ \ifLuaTeX-\usepackage[bidi=basic,shorthands=off,$for(babeloptions)$,$babeloptions$$endfor$]{babel}+\usepackage[bidi=basic$if(shorthands)$$else$,shorthands=off$endif$$for(babeloptions)$,$babeloptions$$endfor$]{babel} \else-\usepackage[bidi=default,shorthands=off,$for(babeloptions)$,$babeloptions$$endfor$]{babel}+\usepackage[bidi=default$if(shorthands)$$else$,shorthands=off$endif$$for(babeloptions)$,$babeloptions$$endfor$]{babel} \fi $if(babel-lang)$ $if(mainfont)$@@ -233,6 +234,12 @@   \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$ $--
+ data/templates/default.bbcode view
@@ -0,0 +1,1 @@+$body$
data/templates/default.beamer view
@@ -108,12 +108,12 @@ $hypersetup.latex()$  $if(title)$-\title$if(shorttitle)$[$shorttitle$]$endif${$title$$if(thanks)$\thanks{$thanks$}$endif$}+\title$if(shorttitle)$[$shorttitle$]$endif${\texorpdfstring{$title$}{$title-meta$}$if(thanks)$\thanks{$thanks$}$endif$} $endif$ $if(subtitle)$-\subtitle$if(shortsubtitle)$[$shortsubtitle$]$endif${$subtitle$}+\subtitle$if(shortsubtitle)$[$shortsubtitle$]$endif${\texorpdfstring{$subtitle$}{$subtitle-meta$}} $endif$-\author$if(shortauthor)$[$shortauthor$]$endif${$for(author)$$author$$sep$ \and $endfor$}+\author$if(shortauthor)$[$shortauthor$]$endif${\texorpdfstring{$for(author)$$author$$sep$ \and $endfor$}{$author-meta$}} \date$if(shortdate)$[$shortdate$]$endif${$date$} $if(institute)$ \institute$if(shortinstitute)$[$shortinstitute$]$endif${$for(institute)$$institute$$sep$ \and $endfor$}@@ -125,7 +125,7 @@ $endfor$} $endif$ $if(logo)$-\logo{\includegraphics{$logo$}}+\logo{\includegraphics$if(logooptions)$[$for(logooptions)$$logooptions$$sep$, $endfor$]$endif${$logo$}} $endif$  \begin{document}
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$
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$" />
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>
data/templates/default.latex view
@@ -1,3 +1,4 @@+$document-metadata.latex()$ $passoptions.latex()$ \documentclass[ $for(babel-otherlangs)$@@ -24,6 +25,9 @@ \usepackage[$for(geometry)$$geometry$$sep$,$endfor$]{geometry} $endif$ \usepackage{amsmath,amssymb}+$if(cancel)$+\usepackage{cancel}+$endif$ $-- $-- section numbering $--@@ -40,7 +44,20 @@ $endfor$ $after-header-includes.latex()$ $hypersetup.latex()$+$if(pdf-trailer-id)$ +\ifXeTeX+\special{pdf:trailerid [ $pdf-trailer-id$ ]}+\fi+\ifPDFTeX+\pdftrailerid{}+\pdftrailer{/ID [ $pdf-trailer-id$ ]}+\fi+\ifLuaTeX+\pdfvariable trailerid {[ $pdf-trailer-id$ ]}+\fi+$endif$+ $if(title)$ \title{$title$$if(thanks)$\thanks{$thanks$}$endif$} $endif$@@ -79,7 +96,9 @@ $endif$ { $if(colorlinks)$-\hypersetup{linkcolor=$if(toccolor)$$toccolor$$else$$endif$}+$if(toccolor)$+\hypersetup{linkcolor=$toccolor$}+$endif$ $endif$ \setcounter{tocdepth}{$toc-depth$} \tableofcontents
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.typst view
@@ -1,13 +1,9 @@ #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,@@ -22,6 +18,11 @@   kind: image ): set figure.caption(position: $if(figure-caption-position)$$figure-caption-position$$else$bottom$endif$) +$if(highlighting-definitions)$+// syntax highlighting functions from skylighting:+$highlighting-definitions$++$endif$ $if(template)$ #import "$template$": conf $else$@@ -60,7 +61,7 @@     ), $endif$ $if(keywords)$-  keywords: ($for(keywords)$$keyword$$sep$,$endfor$),+  keywords: ($for(keywords)$$keywords$$sep$,$endfor$), $endif$ $if(date)$   date: [$date$],@@ -71,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$@@ -86,10 +93,28 @@ $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, )@@ -108,6 +133,9 @@ $body$  $if(citations)$+$for(nocite-ids)$+#cite(label("${it}"), form: none)+$endfor$ $if(csl)$  #set bibliography(style: "$csl$")@@ -117,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/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/hypersetup.latex view
@@ -1,3 +1,7 @@+% fallback for those not using the hyperref driver hyperxmp:+\makeatletter+\@ifundefined{xmpquote}{\newcommand{\xmpquote}[1]{#1}}{}+\makeatother \hypersetup{ $if(title-meta)$   pdftitle={$title-meta$},@@ -12,7 +16,7 @@   pdfsubject={$subject$}, $endif$ $if(keywords)$-  pdfkeywords={$for(keywords)$$keywords$$sep$, $endfor$},+  pdfkeywords={$for(keywords)$\xmpquote{$keywords$}$sep$, $endfor$}, $endif$ $if(colorlinks)$   colorlinks=true,
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$;@@ -180,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
@@ -15,75 +15,106 @@   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 => content-to-string(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: pagenumbering,-    columns: cols,-    )-  set par(justify: true)+    columns: cols+  )++  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) -  place(top, float: true, scope: "parent", clearance: 4mm)[-  #if title != none {-    align(center)[#block(inset: 2em)[-      #text(weight: "bold", size: 1.5em)[#title]-      #(if subtitle != none {-        parbreak()-        text(weight: "bold", size: 1.25em)[#subtitle]-      })-    ]]+  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 date != none {+        align(center)[#block(inset: 1em)[+            #date+          ]]+      } -  #if abstract != none {-    block(inset: 2em)[-    #text(weight: "semibold")[Abstract] #h(1em) #abstract-    ]+      #if abstract != none {+        block(inset: 2em)[+          #text(weight: "semibold")[#abstract-title] #h(1em) #abstract+        ]+      }+    ])   }-  ]-   doc }
pandoc.cabal view
@@ -1,6 +1,6 @@ cabal-version:   2.4 name:            pandoc-version:         3.7.0.2+version:         3.10 build-type:      Simple license:         GPL-2.0-or-later license-file:    COPYING.md@@ -11,9 +11,7 @@ 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,-                 GHC == 9.8.2, GHC == 9.10.1+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@@ -23,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@@ -38,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@@ -103,6 +101,7 @@                  data/templates/affiliations.jats                  data/templates/default.markua                  data/templates/default.typst+                 data/templates/document-metadata.latex                  data/templates/template.typst                  data/templates/common.latex                  data/templates/hypersetup.latex@@ -110,6 +109,8 @@                  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@@ -206,22 +207,25 @@                  citeproc/biblatex-localization/*.lbx.strings                  -- documentation                  MANUAL.txt, COPYRIGHT-extra-doc-files:-                 changelog.md+extra-doc-files: changelog.md,+                 AUTHORS.md,+                 INSTALL.md,+                 README.md,+                 CONTRIBUTING.md,+                 BUGS extra-source-files:-                 -- documentation-                 INSTALL.md, AUTHORS.md, README.md,-                 CONTRIBUTING.md, BUGS,                  -- tests                  test/bodybg.gif                  test/*.native                  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@@ -231,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@@ -245,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@@ -270,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@@ -337,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@@ -383,6 +398,8 @@                  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@@ -417,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@@ -429,7 +448,11 @@                  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:      https://github.com/jgm/pandoc.git@@ -438,9 +461,13 @@   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@@ -450,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@@ -485,7 +511,7 @@   build-depends: xml-light,                  Glob                  >= 0.7      && < 0.11,                  JuicyPixels           >= 3.1.6.1  && < 3.4,-                 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,@@ -495,17 +521,16 @@                  blaze-markup          >= 0.8      && < 0.9,                  bytestring            >= 0.9      && < 0.13,                  case-insensitive      >= 1.2      && < 1.3,-                 citeproc              >= 0.9.0.1  && < 0.10,-                 commonmark            >= 0.2.6.1  && < 0.3,-                 commonmark-extensions >= 0.2.6    && < 0.3,-                 commonmark-pandoc     >= 0.2.3    && < 0.3,+                 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.1,-                 crypton-connection    >= 0.3.1    && < 0.5,+                 crypton               >= 0.30     && < 1.2,                  data-default          >= 0.4      && < 0.9,                  deepseq               >= 1.3      && < 1.6,                  directory             >= 1.2.3    && < 1.4,-                 doclayout             >= 0.5      && < 0.6,+                 doclayout             >= 0.5.0.1  && < 0.6,                  doctemplates          >= 0.11     && < 0.12,                  emojis                >= 0.1.4.1  && < 0.2,                  exceptions            >= 0.8      && < 0.11,@@ -513,14 +538,11 @@                  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.3,                  network-uri           >= 2.6      && < 2.8,                  pandoc-types          >= 1.23.1   && < 1.24,                  parsec                >= 3.1      && < 3.2,@@ -530,34 +552,43 @@                  random                >= 1.2      && < 1.4,                  safe                  >= 0.3.18   && < 0.4,                  scientific            >= 0.3      && < 0.4,-                 skylighting           >= 0.14.5   && < 0.15,-                 skylighting-core      >= 0.14.5   && < 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.10.3 && < 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.15,+                 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.8.0.1  && < 0.9,+                 typst                 >= 0.10     && < 0.11,                  vector                >= 0.12     && < 0.14,-                 djot                  >= 0.1.2.2  && < 0.2,-                 tls                   >= 2.0.1    && < 2.2,-                 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,@@ -574,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,@@ -598,6 +630,8 @@                    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,@@ -613,6 +647,7 @@                    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,@@ -655,6 +690,8 @@                    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,@@ -703,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,@@ -743,6 +788,7 @@                    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,@@ -768,6 +814,7 @@                    Text.Pandoc.Char,                    Text.Pandoc.TeX,                    Text.Pandoc.URI,+                   Text.Pandoc.XMLFormat,                    Text.Pandoc.CSS,                    Text.Pandoc.CSV,                    Text.Pandoc.RoffChar,@@ -806,7 +853,7 @@                   tasty-quickcheck  >= 0.8     && < 0.12,                   text              >= 1.1.1.0 && < 2.2,                   temporary         >= 1.1     && < 1.4,-                  time              >= 1.5     && < 1.15,+                  time              >= 1.5     && < 1.17,                   xml               >= 1.3.12  && < 1.4,                   zip-archive       >= 0.4.3   && < 0.5   other-modules:  Tests.Old@@ -814,6 +861,7 @@                   Tests.Helpers                   Tests.Shared                   Tests.MediaBag+                  Tests.XML                   Tests.Readers.LaTeX                   Tests.Readers.HTML                   Tests.Readers.JATS@@ -836,6 +884,8 @@                   Tests.Readers.RST                   Tests.Readers.RTF                   Tests.Readers.Docx+                  Tests.Readers.Pptx+                  Tests.Readers.Xlsx                   Tests.Readers.ODT                   Tests.Readers.Txt2Tags                   Tests.Readers.EPUB@@ -867,6 +917,7 @@                   Tests.Writers.OOXML                   Tests.Writers.Ms                   Tests.Writers.AnnotatedTable+                  Tests.Writers.BBCode  benchmark benchmark-pandoc   import:          common-executable
src/Text/Pandoc/App.hs view
@@ -26,6 +26,7 @@           , parseOptionsFromArgs           , options           , applyFilters+          , versionInfo           ) where import qualified Control.Exception as E import Control.Monad ( (>=>), when, forM, forM_ )@@ -41,13 +42,15 @@ import qualified Data.Text.Lazy.Encoding as TE import qualified Data.Text.Encoding.Error as TE import Data.Char (toLower)-import System.Directory (doesDirectoryExist, createDirectory)+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)@@ -55,7 +58,7 @@ 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,                                        sandbox')@@ -115,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] ++@@ -232,6 +238,7 @@         , readerAbbreviations = abbrevs         , readerExtensions = readerExts         , readerStripComments = optStripComments opts+        , readerTypstInputs = optTypstInputs opts         }    metadataFromFile <- getMetadataFromFiles readerNameBase readerOpts@@ -352,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
src/Text/Pandoc/App/CommandLineOptions.hs view
@@ -21,6 +21,7 @@           , options           , engines           , setVariable+          , versionInfo           ) where import Control.Monad.Trans import Control.Monad.State.Strict@@ -30,7 +31,8 @@          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,24 +196,19 @@                      ,"text-styles"])                   ,confNumFormat = Generic                   ,confTrailingNewline = True} sty-    VersionInfo -> do-      prg <- getProgName-      defaultDatadir <- defaultUserDataDir-      UTF8.hPutStrLn stdout-       $ T.pack-       $ prg ++ " " ++ T.unpack pandocVersionText ++-         "\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.@@ -222,8 +220,8 @@           map ("html5",) htmlEngines ++           map ("latex",) latexEngines ++           map ("beamer",) latexEngines ++-          [ ("ms", "pdfroff")-          , ("ms", "groff")+          [ ("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,7 +368,7 @@                      return opt{ optVariables =                                   setVariable (T.pack key) (T.pack val) $                                     optVariables opt })-                  "KEY[:VALUE]")+                  "KEY[=VALUE]")                  ""      , Option "" ["variable-json"]@@ -524,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"@@ -543,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 ->@@ -602,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" @@ -653,7 +664,7 @@                      let (key, val) = splitField arg                      return opt{ optRequestHeaders =                        (T.pack key, T.pack val) : optRequestHeaders opt })-                  "NAME:VALUE")+                  "NAME=VALUE")                  ""      , Option "" ["no-check-certificate"]@@ -671,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 $@@ -813,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" @@ -1027,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" @@ -1172,7 +1197,7 @@  copyrightMessage :: String copyrightMessage = intercalate "\n" [- "Copyright (C) 2006-2024 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." ] @@ -1270,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
@@ -14,7 +14,7 @@   , readInput   ) where -import Control.Monad ((>=>))+import Control.Monad ((>=>), when) import Control.Monad.Except (throwError, catchError) import Data.Text (Text) import Network.URI (URI (..), parseURI)@@ -109,12 +109,29 @@                            (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
src/Text/Pandoc/App/Opt.hs view
@@ -2,6 +2,7 @@ {-# LANGUAGE OverloadedStrings   #-} {-# LANGUAGE CPP                 #-} {-# LANGUAGE DeriveGeneric       #-}+{-# LANGUAGE PatternSynonyms     #-} {-# LANGUAGE TemplateHaskell     #-} {-# LANGUAGE FlexibleInstances   #-} {-# LANGUAGE FlexibleContexts    #-}@@ -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 (..))@@ -43,7 +44,8 @@                             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))@@ -60,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@@ -124,8 +126,8 @@     , 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@@ -157,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@@ -183,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@@ -211,8 +213,8 @@        <*> 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"@@ -245,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"@@ -271,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{@@ -319,6 +321,7 @@     , optOutputFile            = oOutputFile     , optInputFiles            = oInputFiles     , optSyntaxDefinitions     = oSyntaxDefinitions+    , optSyntaxHighlighting    = oSyntaxHighlighting     , optAbbreviations         = oAbbreviations     , optReferenceDoc          = oReferenceDoc     , optEpubMetadata          = oEpubMetadata@@ -337,7 +340,6 @@     , optBibliography          = oBibliography     , optCitationAbbreviations = oCitationAbbreviations     , optPdfEngine             = oPdfEngine-    , optHighlightStyle        = oHighlightStyle     }   = do       oTo' <- mapM (fmap T.pack . resolveVars . T.unpack) oTo@@ -365,7 +367,7 @@       oBibliography' <- mapM resolveVars oBibliography       oCitationAbbreviations' <- mapM resolveVars oCitationAbbreviations       oPdfEngine' <- mapM resolveVars oPdfEngine-      oHighlightStyle' <- mapM (fmap T.pack . resolveVars . T.unpack) oHighlightStyle+      oSyntaxHighlighting' <- T.pack <$> resolveVars (T.unpack oSyntaxHighlighting)       return opt{ optTo                    = oTo'                 , optFrom                  = oFrom'                 , optTemplate              = oTemplate'@@ -373,6 +375,7 @@                 , optOutputFile            = oOutputFile'                 , optInputFiles            = oInputFiles'                 , optSyntaxDefinitions     = oSyntaxDefinitions'+                , optSyntaxHighlighting    = oSyntaxHighlighting'                 , optAbbreviations         = oAbbreviations'                 , optReferenceDoc          = oReferenceDoc'                 , optEpubMetadata          = oEpubMetadata'@@ -391,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   @@ -438,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@@ -555,8 +568,9 @@       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 =@@ -569,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" ->@@ -647,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" ->@@ -773,8 +792,8 @@     , optEmbedResources        = False     , optLinkImages            = False     , optHtmlQTags             = False-    , optHighlightStyle        = Just "pygments"     , optSyntaxDefinitions     = []+    , optSyntaxHighlighting    = DefaultHighlightingString     , optTopLevelDivision      = TopLevelDefault     , optHTMLMathMethod        = PlainMath     , optAbbreviations         = Nothing@@ -806,7 +825,6 @@     , optIndentedCodeClasses   = []     , optDataDir               = Nothing     , optCiteMethod            = Citeproc-    , optListings              = False     , optPdfEngine             = Nothing     , optPdfEngineOpts         = []     , optSlideLevel            = Nothing@@ -832,6 +850,7 @@     , optBibliography          = []     , optCitationAbbreviations = Nothing     , optSandbox               = False+    , optTypstInputs           = []     }  yamlToMeta :: Value -> Parser Meta@@ -853,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,6 +2,7 @@ {-# LANGUAGE FlexibleContexts    #-} {-# LANGUAGE LambdaCase          #-} {-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE PatternSynonyms     #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TupleSections       #-} {- |@@ -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@@ -251,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
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@@ -408,14 +422,14 @@ mvPunct moveNotes locale (q : s : x@(Cite _ [il]) : ys)   | isSpacy s   , isNote il-  = let spunct = T.takeWhile isPunctuation $ stringify ys+  = 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)@@ -423,13 +437,13 @@    , 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)))+           (B.toList (dropTextWhile isPunct (B.fromList ys))) mvPunct moveNotes locale (s : x@(Cite _ [il]) : ys)   | isSpacy s   , isNote il@@ -442,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@@ -478,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) =@@ -503,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]@@ -569,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@@ -474,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 @@ -820,7 +823,7 @@ bibComment = do   cistring "comment"   spaces'-  void inBraces <|> bibSkip <|> return ()+  void inBraces  bibPreamble :: BibParser () bibPreamble = do@@ -967,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@@ -1114,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@@ -1207,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/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,31 +38,38 @@  import Control.Monad.Except (throwError) import Control.Monad.IO.Class (MonadIO, liftIO)-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, extractURIData)+       (PandocMonad,+        getMediaBag, report, extractURIData) import Text.Pandoc.Definition (Pandoc, Inline (Image)) import Text.Pandoc.Error (PandocError (..)) import Text.Pandoc.Logging (LogMessage (..), messageVerbosity, showLogMessage)@@ -70,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@@ -82,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@@ -124,50 +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)      = 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.@@ -222,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,12 +28,14 @@   , getZonedTime   , readFileFromDirs   , report-  , setTrace+  , runSilently   , setRequestHeader   , setNoCheckCertificate   , getLog   , setVerbosity   , getVerbosity+  , setTrace+  , getTrace   , getMediaBag   , setMediaBag   , insertMedia@@ -47,6 +49,9 @@   , setOutputFile   , setResourcePath   , getResourcePath+  , setRequestHeaders+  , getRequestHeaders+  , getSourceURL   , readMetadataFile   , toTextM   , fillMediaBag@@ -164,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@@ -179,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@@ -248,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@@ -371,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"@@ -498,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/Error.hs view
@@ -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,49 +86,49 @@     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," <>                  " and convert that with pandoc."         "pdf" -> "\nPandoc can convert to PDF, but not from PDF."-        "asciidoc" -> "\nPandoc can convert to asciidoc, but not from asciidoc."         _     -> ""     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|typst" <>@@ -136,21 +137,32 @@          "doc" -> "\nPandoc can convert to DOCX, but not to DOC."          _     -> ""     PandocUnsupportedExtensionError ext f ->-      "The extension " <> ext <> " is not supported " <>+      "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 =@@ -184,6 +196,7 @@       PandocUTF8DecodingError{} -> 92       PandocIpynbDecodingError{} -> 93       PandocUnsupportedCharsetError{} -> 94+      PandocInputNotTextError{} -> 95       PandocCouldNotFindDataFileError{} -> 97       PandocCouldNotFindMetadataFileError{} -> 98       PandocResourceNotFound{} -> 99
src/Text/Pandoc/Extensions.hs view
@@ -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@@ -511,7 +514,6 @@        , Ext_mark        , Ext_mmd_link_attributes        , Ext_mmd_header_identifiers-       , Ext_compact_definition_lists        , Ext_gutenberg        , Ext_smart        , Ext_literate_haskell@@ -519,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@@ -583,6 +586,8 @@     extensionsFromList     [ Ext_citations     , Ext_smart+    , Ext_smart_quotes+    , Ext_special_strings     , Ext_fancy_lists     , Ext_task_lists     ]@@ -659,4 +664,5 @@     [ Ext_smart ]   getAll "typst"           = extensionsFromList [Ext_citations, Ext_smart]   getAll "djot"            = extensionsFromList [Ext_sourcepos]+  getAll "man"             = autoIdExtensions   getAll _                 = mempty
src/Text/Pandoc/Format.hs view
@@ -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 (..))@@ -142,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 "-+"@@ -181,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"@@ -204,6 +205,9 @@     ".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"@@ -229,6 +233,10 @@     ".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
src/Text/Pandoc/Highlighting.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Highlighting-   Copyright   : Copyright (C) 2008-2024 John MacFarlane+   Copyright   : Copyright (C) 2008-2025 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -30,7 +30,12 @@                                 , formatConTeXtBlock                                 , styleToConTeXt                                 , formatANSI+                                -- ** Typst+                                , formatTypstBlock+                                , formatTypstInline+                                , styleToTypst                                 -- * Styles+                                , defaultStyle                                 , pygments                                 , espresso                                 , zenburn@@ -44,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/ImageSize.hs view
@@ -38,7 +38,7 @@ import qualified Data.ByteString.Lazy as BL import Data.Binary.Get import Data.Bits ((.&.), shiftR, shiftL)-import Data.Word (bitReverse32)+import Data.Word (bitReverse32, Word32) import Data.Maybe (isJust, fromJust) import Data.Char (isDigit) import Control.Monad@@ -57,11 +57,12 @@ import qualified Data.Attoparsec.ByteString.Char8 as A import qualified Codec.Picture.Metadata as Metadata 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 | Webp+data ImageType = Png | Gif | Jpeg | Svg | Pdf | Eps | Emf | Tiff | Webp | Avif                  deriving Show data Direction = Width | Height instance Show Direction where@@ -72,6 +73,8 @@                | Centimeter Double                | Millimeter Double                | Inch Double+               | Point Double+               | Pica Double                | Percent Double                | Em Double                deriving Eq@@ -81,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" @@ -113,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"@@ -131,6 +139,7 @@                      "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@@ -148,6 +157,7 @@        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@@ -201,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) @@ -208,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 @@ -242,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) @@ -265,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 @@ -294,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@@ -314,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 =@@ -344,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 {@@ -451,3 +483,173 @@   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
@@ -105,12 +105,14 @@   | 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,@@ -290,6 +292,8 @@            , "column" .= toJSON (sourceColumn pos)            , "message" .= msg            ]+      UnsupportedPdfStandard s ->+           ["contents" .= s]  showPos :: SourcePos -> Text showPos pos = Text.pack $ sn ++ "line " ++@@ -377,8 +381,7 @@        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."@@ -438,6 +441,8 @@        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 =@@ -497,3 +502,4 @@        UnclosedDiv{}                 -> WARNING        UnsupportedCodePage{}         -> WARNING        YamlWarning{}                 -> WARNING+       UnsupportedPdfStandard{}      -> WARNING
src/Text/Pandoc/Options.hs view
@@ -3,6 +3,7 @@ {-# LANGUAGE DeriveGeneric      #-} {-# LANGUAGE LambdaCase         #-} {-# LANGUAGE OverloadedStrings  #-}+{-# LANGUAGE PatternSynonyms    #-} {-# LANGUAGE TemplateHaskell    #-} {- |    Module      : Text.Pandoc.Options@@ -21,6 +22,10 @@                            , HTMLMathMethod (..)                            , CiteMethod (..)                            , ObfuscationMethod (..)+                           , HighlightMethod (..)+                           , pattern NoHighlightingString+                           , pattern DefaultHighlightingString+                           , pattern IdiomaticHighlightingString                            , HTMLSlideVariant (..)                            , EPUBVersion (..)                            , WrapOption (..)@@ -32,6 +37,7 @@                            , def                            , isEnabled                            , defaultMathJaxURL+                           , defaultWebTeXURL                            , defaultKaTeXURL                            ) where import Control.Applicative ((<|>))@@ -41,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@@ -67,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@@ -83,6 +91,7 @@                , readerDefaultImageExtension = ""                , readerTrackChanges          = AcceptChanges                , readerStripComments         = False+               , readerTypstInputs           = []                }  defaultAbbrevs :: Set.Set Text@@ -114,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 $@@ -124,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@@ -184,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@@ -328,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@@ -372,8 +417,7 @@                       , writerHtmlQTags        = False                       , writerSlideLevel       = Nothing                       , writerTopLevelDivision = TopLevelDefault-                      , writerListings         = False-                      , writerHighlightStyle   = Just pygments+                      , writerHighlightMethod  = DefaultHighlighting                       , writerSetextHeaders    = False                       , writerListTables       = False                       , writerEpubSubdirectory = "EPUB"@@ -400,7 +444,10 @@ 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@latest/dist/"
src/Text/Pandoc/PDF.hs view
@@ -43,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))@@ -57,7 +58,8 @@ 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 ".html" source-    "typst" -> do-      source <- writer opts doc-      verbosity <- getVerbosity-      liftIO $+    "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"]@@ -112,9 +142,8 @@                     paperargs ++ pdfargs       generic2pdf program args source     "groff" -> 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"]@@ -125,33 +154,22 @@                    ["-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+    "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"] ""@@ -159,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@@ -200,16 +218,7 @@   verbosity <- getVerbosity   liftIO $ toPdfViaTempFile verbosity program args (:[]) ".html" 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)-+-- 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@@ -328,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) @@ -372,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)@@ -435,7 +444,7 @@      (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 outfile ".log"      logExists <- fileExists logFile@@ -449,8 +458,7 @@      if not (null rerunWarnings') && runNumber < maxruns         then do           report $ MakePDFInfo "Rerun needed"-                    (T.intercalate "\n"-                      (map (UTF8.toText . BC.toStrict) rerunWarnings'))+                    (T.intercalate "\n" (map utf8ToText rerunWarnings'))           go env'' programArgs (runNumber + 1)        else do           (log', pdf) <- getResultingPDF (Just logFile) outfile@@ -503,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@@ -536,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@@ -620,6 +628,7 @@                                , "SELFAUTOPARENT"                                , "SFDFONTS"                                , "SHELL"+                               , "SOURCE_DATE_EPOCH"                                , "T1FONTS"                                , "T1INPUTS"                                , "T42FONTS"
src/Text/Pandoc/Parsing.hs view
@@ -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/General.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE BangPatterns               #-} {-# LANGUAGE FlexibleContexts           #-} {-# LANGUAGE OverloadedStrings          #-} {- |@@ -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.@@ -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
@@ -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@@ -249,3 +295,14 @@                    else fromIntegral numColumns       fracs = map (\l -> fromIntegral l / quotient) lengths in   drop 1 fracs++-- | List of lists of `RowSpan` of 1.+singleRowSpans :: [[RowSpan]]+singleRowSpans = repeat $ repeat 1++-- | List of lists of `ColsSpan` of 1.+singleColumnSpans :: [[ColSpan]]+singleColumnSpans = repeat $ repeat 1++singleSpansBlocks :: [[Blocks]] -> [[(Blocks, RowSpan, ColSpan)]]+singleSpansBlocks blocks = zipWith3 zip3 blocks singleRowSpans singleColumnSpans
src/Text/Pandoc/Parsing/Lists.hs view
@@ -113,7 +113,7 @@            => 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
src/Text/Pandoc/Parsing/Math.hs view
@@ -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/Readers.hs view
@@ -25,7 +25,10 @@     -- * Readers: converting /to/ Pandoc format     Reader (..)   , readers+  , readAsciiDoc   , readDocx+  , readPptx+  , readXlsx   , readODT   , readMarkdown   , readCommonMark@@ -65,6 +68,7 @@   , readTypst   , readDjot   , readPod+  , readXML   -- * Miscellaneous   , getReader   , getDefaultExtensions@@ -81,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@@ -118,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) @@ -136,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)@@ -155,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)@@ -174,6 +185,7 @@           ,("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/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,7 +185,7 @@ 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 ("",["mark"],[]) <$> convertInlines ils
src/Text/Pandoc/Readers/DocBook.hs view
@@ -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),@@ -45,13 +46,14 @@ import Text.Pandoc.Class.PandocMonad (PandocMonad, report) import Text.Pandoc.Options import Text.Pandoc.Logging (LogMessage(..))-import Text.Pandoc.Shared (safeRead, extractSpaces)+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)  {- @@ -171,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@@ -436,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@@ -546,6 +548,7 @@                       , dbBook          :: Bool                       , dbContent       :: [Content]                       , dbLiteralLayout :: Bool+                      , dbElementStack  :: [Text]                       } deriving Show  instance Default DBState where@@ -554,7 +557,9 @@                , dbMeta = mempty                , dbBook = False                , dbContent = []-               , dbLiteralLayout = False }+               , dbLiteralLayout = False+               , dbElementStack = []+               }   readDocBook :: (PandocMonad m, ToSources a)@@ -619,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@@ -722,9 +731,7 @@   , "articleinfo"   , "attribution"   , "authorinitials"-  , "bibliodiv"   , "biblioentry"-  , "bibliography"   , "bibliomisc"   , "bibliomixed"   , "blockquote"@@ -763,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"@@ -795,8 +790,14 @@   , "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"] @@ -851,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@@ -861,8 +869,8 @@                                      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)@@ -911,8 +919,8 @@         "refsect2" -> sect 2         "refsect3" -> sect 3         "refsection" -> gets dbSectionLevel >>= sect . (+1)-        l | l `elem` titledBlockElements -> parseAdmonition l-        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@@ -931,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@@ -976,6 +982,9 @@         "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@@ -1056,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)@@ -1072,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@@ -1094,11 +1102,10 @@                                                             in  ColWidth . scale <$> ws'                                                 Nothing  -> replicate numrows ColWidthDefault                       let toRow = Row nullAttr-                          toHeaderRow l = [toRow l | not (null l)]                       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@@ -1113,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 >>=@@ -1136,17 +1146,20 @@            b <- p            case mbt of              Nothing -> return b-             Just t -> return $ divWith (attrValue "id" e,[],[])+             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+         parseAdmonition alwaysIncludeTitle label = do            mbt <- getTitle            -- this will ignore the title element if it is present:            b <- getBlocks e-           let t = divWith ("", ["title"], []) (plain $ fromMaybe mempty mbt)+           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],[]) (t <> b) @@ -1172,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@@ -1189,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 <$>@@ -1227,8 +1249,8 @@      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@@ -1350,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@@ -1358,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
@@ -74,7 +74,8 @@ 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@@ -82,7 +83,7 @@ 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)@@ -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}@@ -481,6 +483,7 @@                           ++ [("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@@ -533,8 +536,13 @@                => 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) $@@ -551,8 +559,7 @@   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 =-                                                    Citeproc.citationItemId item })+                                        itemData{ referenceId = getItemId item })                                   (Citeproc.citationItemData item)) items   modify $ \st ->     st{ docxReferences = foldr@@ -623,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)@@ -809,6 +816,8 @@           -> singleton $ Figure attr' capt [Plain im]         [Div attr bls']           -> toCaptioned (attr <> attr') bls'+        [BlockQuote bls']+          -> toCaptioned attr' bls'         _ -> captContents   pure $ toCaptioned nullAttr (toList bs) bodyPartToBlocks (Tbl _ _ _ _ []) =@@ -832,8 +841,9 @@       alignments = case rows of                      [] -> replicate width Pandoc.AlignDefault                      Docx.Row _ cs : _ -> concatMap getAlignment cs-      totalWidth = sum grid-      widths = (\w -> ColWidth (fromInteger w / fromInteger totalWidth)) <$> grid+      widths = map (\n -> if n == 0+                             then ColWidthDefault+                             else ColWidth n) grid    extStylesEnabled <- asks (isEnabled Ext_styles . docxOptions)   let attr = case mbsty of
src/Text/Pandoc/Readers/Docx/Combine.hs view
@@ -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
@@ -35,6 +35,7 @@ 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@@ -57,6 +58,8 @@     <|>     indexref     <|>+    crossref+    <|>     addIn     <|>     return UnknownField@@ -140,6 +143,15 @@   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
src/Text/Pandoc/Readers/Docx/Parse.hs view
@@ -67,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@@ -92,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@@ -110,6 +110,7 @@                            , envParStyles     :: ParStyleMap                            , envLocation      :: DocumentLocation                            , envDocXmlPath    :: FilePath+                           , envTextWidth     :: Int                            }                deriving Show @@ -151,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@@ -292,7 +307,7 @@               | HRule               deriving Show -type TblGrid = [Integer]+type TblGrid = [Double]  newtype TblLook = TblLook {firstRowFormatting::Bool}               deriving Show@@ -310,6 +325,9 @@ data Cell = Cell Align GridSpan VMerge [BodyPart]             deriving Show +emptyCell :: Cell+emptyCell = Cell AlignDefault 1 Restart []+ type GridSpan = Integer  data VMerge = Continue@@ -423,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@@ -433,6 +452,7 @@                        , envParStyles = parstyles                        , envLocation = InDocument                        , envDocXmlPath = docXmlPath+                       , envTextWidth = fromMaybe 9360 textWidth                        }       rState = ReaderState { stateWarnings = []                            , stateFldCharState = []@@ -453,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@@ -475,9 +497,17 @@   return $ Document namespaces body  elemToBody :: NameSpaces -> Element -> D Body-elemToBody ns element | isElem ns "w" "body" element =-  Body . addCaptioned <$> mapD (elemToBodyPart ns) (elChildren element)-elemToBody _ _ = throwError WrongElem+elemToBody ns element+  | isElem ns "w" "body" element =+      Body . addCaptioned <$> concatMapM (elemToBodyParts ns) (elChildren element)+  | otherwise = throwError WrongElem+  where+    elemToBodyParts ns' el+      | qName (elName el) == "textbox-image"+      = addSplitGroupCaptioned . splitMixedParagraphs+          <$> mapD (elemToBodyPart ns') (elChildren el)+      | otherwise+      = ((:[]) <$> elemToBodyPart ns' el) `catchError` (\_ -> return [])  archiveToStyles :: Archive -> (CharStyleMap, ParStyleMap) archiveToStyles = archiveToStyles' getStyleId getStyleId@@ -540,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]@@ -563,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]@@ -654,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 =@@ -682,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@@ -707,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@@ -749,7 +807,7 @@ 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@@ -778,6 +836,28 @@     = Captioned parstyle parparts x : addCaptioned xs addCaptioned (x:xs) = x : addCaptioned xs +-- Split paragraphs that contain both a Drawing and text into two body parts,+-- so that the captioning logic can combine them.+splitMixedParagraphs :: [BodyPart] -> [BodyPart]+splitMixedParagraphs [] = []+splitMixedParagraphs (Paragraph ps parts : rest)+  | (drawings@(_:_), texts@(_:_)) <- partition isDrawingPart parts+  = Paragraph ps drawings : Paragraph ps texts : splitMixedParagraphs rest+  where isDrawingPart Drawing{} = True+        isDrawingPart _         = False+splitMixedParagraphs (x:xs) = x : splitMixedParagraphs xs++-- For textbox-image groups: combine image + any adjacent text into Captioned+addSplitGroupCaptioned :: [BodyPart] -> [BodyPart]+addSplitGroupCaptioned [] = []+addSplitGroupCaptioned (Paragraph parstyle parparts : x : xs)+  | isCaptionable x+  = Captioned parstyle parparts x : addSplitGroupCaptioned xs+addSplitGroupCaptioned (x : Paragraph parstyle parparts : xs)+  | isCaptionable x+  = Captioned parstyle parparts x : addSplitGroupCaptioned xs+addSplitGroupCaptioned (x:xs) = x : addSplitGroupCaptioned xs+ isCaptionable :: BodyPart -> Bool isCaptionable (Paragraph _ [Drawing{}]) = True isCaptionable (Tbl{}) = True@@ -867,9 +947,15 @@                        Just l  -> elemToTblLook ns l                        Nothing -> return defaultTblLook -    grid <- grid'+    grid'' <- grid'     tblLook <- tblLook'     rows <- mapD (elemToRow ns) (elChildren element)+    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 @@ -899,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 @@ -1022,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))@@ -1057,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@@ -1139,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))@@ -1161,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@@ -1190,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 = concatMap (take 1 . 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@@ -1358,20 +1447,24 @@  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- where-  a_ns = "http://schemas.openxmlformats.org/drawingml/2006/main" +-- | Checks if any style in the style hierarchy is a caption style. hasCaptionStyle :: ParagraphStyle -> Bool-hasCaptionStyle parstyle = any (isCaptionStyleName . pStyleName) (pStyle parstyle)+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@@ -1387,3 +1480,23 @@        (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+   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
@@ -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.
src/Text/Pandoc/Readers/EndNote.hs view
@@ -81,6 +81,9 @@   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
@@ -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)@@ -237,12 +237,13 @@           -> pLineBlock           | otherwise           -> pDiv+        "aside" -> pDiv         "section" -> pDiv         "header" -> pDiv         "main" -> pDiv         "figure" -> pFigure         "iframe" -> pIframe-        "style" -> mempty <$ pHtmlBlock "style" -- see #10643+        "style" -> pRawHtmlBlock         "textarea" -> pRawHtmlBlock         "switch"           | epubExts@@ -444,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) @@ -489,6 +490,7 @@ isDivLike "section" = True isDivLike "header"  = True isDivLike "main"    = True+isDivLike "aside"   = True isDivLike _         = False  pDiv :: PandocMonad m => TagParser m Blocks@@ -502,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@@ -537,7 +541,7 @@  pRawHtmlBlock :: PandocMonad m => TagParser m Blocks pRawHtmlBlock = do-  raw <- pHtmlBlock "script" <|> pHtmlBlock "textarea"+  raw <- pHtmlBlock "script" <|> pHtmlBlock "style" <|> pHtmlBlock "textarea"           <|> pRawTag   exts <- getOption readerExtensions   if extensionEnabled Ext_raw_html exts && not (T.null raw)@@ -659,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@@ -716,7 +716,7 @@         "input"           | lookup "type" attr == Just "checkbox"           -> asks inListItem >>= guard >> pCheckbox-        "style" -> mempty <$ pHtmlBlock "style" -- see #10643+        "style" -> B.rawInline "html" <$> pHtmlBlock "style"         "script"           | Just x <- lookup "type" attr           , "math/tex" `T.isPrefixOf` x -> pScriptMath
src/Text/Pandoc/Readers/HTML/Table.hs view
@@ -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/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@@ -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                                "" -> []
src/Text/Pandoc/Readers/LaTeX.hs view
@@ -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)@@ -110,6 +110,7 @@        (if bottomLevel < 1            then walk (adjustHeaders (1 - bottomLevel))            else id) $+       walk (resolveFootnoteMarks (sFootnoteTexts st)) $        walk (resolveRefs (sLabels st)) doc'   return $ Pandoc meta bs' @@ -124,7 +125,19 @@         _ -> x resolveRefs _ x = x +-- | Resolve footnote marks (\footnotemark) to actual notes using+-- the footnote texts collected from \footnotetext commands.+resolveFootnoteMarks :: M.Map Int Blocks -> Inline -> Inline+resolveFootnoteMarks fnTexts (Span (_, classes, kvs) _)+  | "footnote-mark" `elem` classes+  , Just numText <- lookup "note-num" kvs+  , [(n, "")] <- reads (T.unpack numText)+  = case M.lookup n fnTexts of+      Just contents -> Note (toList contents)+      Nothing       -> Str ""  -- No matching footnotetext found+resolveFootnoteMarks _ x = x + -- testParser :: LP PandocIO a -> Text -> IO a -- testParser p t = do --   res <- runIOorExplode (runParserT p defaultLaTeXState{@@ -144,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.@@ -177,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@@ -187,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:@@ -371,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)@@ -394,8 +420,9 @@     , ("lowercase", makeLowercase <$> tok)     , ("thanks", skipopts >> note <$> grouped block)     , ("footnote", skipopts >> footnote)+    , ("footnotemark", footnotemark)+    , ("footnotetext", footnotetext)     , ("newline", pure B.linebreak)-    , ("linebreak", pure B.linebreak)     , ("passthrough", fixPassthroughEscapes <$> tok)     -- \passthrough macro used by latex writer                            -- for listings@@ -424,7 +451,6 @@     , ("textcolor", coloredInline "color")     , ("colorbox", coloredInline "background-color")     -- etoolbox-    , ("ifstrequal", ifstrequal)     , ("newtoggle", braced >>= newToggle)     , ("toggletrue", braced >>= setToggle True)     , ("togglefalse", braced >>= setToggle False)@@ -442,6 +468,9 @@     , ("ifdim", ifdim)     -- generally only used in \date     , ("today", today)+    -- this is used internally by pandoc but the definition is too complicated+    -- for pandoc to handle (see #11140):+    , ("pandocbounded", tok)     ]  bracedFilename :: PandocMonad m => LP m Text@@ -463,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@@ -561,18 +623,6 @@                   report $ UndefinedToggle name' pos   return () -ifstrequal :: (PandocMonad m, Monoid a) => LP m a-ifstrequal = do-  str1 <- tok-  str2 <- tok-  ifequal <- withVerbatimMode braced-  ifnotequal <- withVerbatimMode 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@@ -935,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"))@@ -961,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)@@ -1019,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 ()@@ -1035,8 +1091,8 @@    , ("letter", env "letter" letterContents)    , ("minipage", divWith ("",["minipage"],[]) <$>        env "minipage" (skipopts *> spaces *> optional braced *> spaces *> blocks))-   , ("figure", env "figure" $ skipopts *> figure')-   , ("figure*", env "figure*" $ skipopts *> figure')+   , ("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)@@ -1062,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)    ]@@ -1105,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@@ -1208,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
@@ -281,6 +281,7 @@   , ("_", lit "_")   , ("{", lit "{")   , ("}", lit "}")+  , ("-", lit "\x00ad") -- soft hyphen   , ("qed", lit "\a0\x25FB")   , ("lq", return (str "‘"))   , ("rq", return (str "’"))@@ -314,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/Math.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} module Text.Pandoc.Readers.LaTeX.Math-  ( dollarsMath+  ( withMathMode+  , dollarsMath   , inlineEnvironments   , inlineEnvironmentNames   , inlineEnvironment@@ -13,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)@@ -28,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)@@ -70,10 +79,10 @@                                    "\n\\end{" <> y <> "}"  mathEnv :: PandocMonad m => Text -> LP m Text-mathEnv name = do+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@@ -89,20 +98,21 @@ 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*")-  , ("flalign", mathEnvWith id (Just "aligned") "flalign")-  , ("flalign*", mathEnvWith id (Just "aligned") "flalign*")+  , ("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")@@ -125,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@@ -150,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@@ -158,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@@ -196,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
@@ -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@@ -186,6 +188,7 @@                               , sLogMessages   = []                               , sIdentifiers   = Set.empty                               , sVerbatimMode  = False+                              , sMathMode      = False                               , sCaption       = Nothing                               , sInListItem    = False                               , sInTableCell   = False@@ -193,6 +196,7 @@                               , sLastFigureNum = DottedNum []                               , sLastTableNum  = DottedNum []                               , sLastNoteNum   = 0+                              , sFootnoteTexts = M.empty                               , sTheoremMap    = M.empty                               , sLastTheoremStyle = PlainStyle                               , sLastLabel     = Nothing@@ -277,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@@ -299,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@@ -648,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"
src/Text/Pandoc/Readers/LaTeX/Table.hs view
@@ -35,6 +35,8 @@   , ("tabular*", env "tabular*" $ simpTable block inline "tabular*" True)   , ("tabularx", env "tabularx" $ simpTable block inline "tabularx" True)   , ("tabular", env "tabular"  $ simpTable block inline "tabular" False)+  , ("supertabular", env "supertabular" $ simpTable block inline "supertabular" False)+  , ("supertabular*", env "supertabular*" $ simpTable block inline "supertabular*" False)   ]  where    blocks = mconcat <$> many block@@ -377,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
@@ -22,9 +22,10 @@  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@@ -42,7 +43,6 @@ 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@@ -190,6 +190,28 @@        <|> T.singleton <$> noneOf "\n"        <|> try (newline >> notFollowedBy blankline >> return " ") +litBetween :: PandocMonad m => Char -> Char -> MarkdownParser m Text+litBetween op cl = try $ do+  char op+  mconcat <$> (manyTill litChar (char cl))++litCharNoSpace :: PandocMonad m => MarkdownParser m Text+litCharNoSpace = T.singleton <$> escapedChar''+       <|> characterReference+       <|> (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.@@ -330,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)@@ -356,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@@ -369,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@@ -629,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@@ -761,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@@ -798,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@@ -845,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@@ -967,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  --@@ -1060,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@@ -1083,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@@ -1151,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 @@ -1187,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 @@ -1230,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 ""@@ -1252,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@@ -1265,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@@ -1308,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@@ -1329,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 @@ -1346,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@@ -1375,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,@@ -1383,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@@ -1420,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@@ -1479,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)) <|>@@ -1490,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@@ -1518,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@@ -1583,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@@ -1724,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"@@ -1821,14 +1856,12 @@         return $ "(" <> result <> ")"   let linkTitle' = try $ spnl >> linkTitle   let urlChunk = do-        notFollowedBy linkTitle'         try parenthesizedChars-          <|> (notFollowedBy (oneOf " )") >> litChar)+          <|> (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 <|> try base64DataURI <|> sourceURL+  src <- try (litBetween '<' '>') <|> try base64DataURI <|> sourceURL   tit <- option "" linkTitle'   skipSpaces   char ')'@@ -1864,7 +1897,7 @@           (before, after)             | titleAfter -> (T.drop 1 after, before)             | otherwise -> (before, T.drop 1 after)-    guard $ T.all (`notElem` ['\n','\r','\f','\t']) url+    guard $ T.all (\c -> c /= '\n' && c /= '\r' && c /= '\f' && c /= '\t') url     return . pure . constructor attr url "" $        B.text $ fromEntities title @@ -1909,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@@ -2068,7 +2101,9 @@     char '^'     updateState $ \st -> st{ stateInNote = True                            , stateNoteNumber = stateNoteNumber st + 1 }-    contents <- inBalancedBrackets inlines+    contents <- withQuoteContext NoQuote $ inBalancedBrackets inlines+    notFollowedBy (char '(' <|> char '[' <|> ('{' <$ attributes))+      -- ^[link](foo)^ is superscript     updateState $ \st -> st{ stateInNote = False }     return $ B.note . B.para <$> contents @@ -2170,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 @@ -2253,7 +2290,7 @@   rest <- option (return []) $ try $ char ';' >> spnl >> citeList   spnl   char ']'-  notFollowedBy $ oneOf "[("+  notFollowedBy $ oneOf "[({"   return $ do     suff' <- suff     rest' <- rest
src/Text/Pandoc/Readers/MediaWiki.hs view
@@ -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,17 +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.Char (isCJK)+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.@@ -56,6 +56,7 @@                                             , mwLogMessages = []                                             , mwInTT = False                                             , mwAllowNewlines = True+                                            , mwMeta = nullMeta                                             }             sources   case parsed of@@ -70,6 +71,7 @@                        , mwLogMessages     :: [LogMessage]                        , mwInTT            :: Bool                        , mwAllowNewlines   :: Bool+                       , mwMeta            :: Meta                        }  type MWParser m = ParsecT Sources MWState m@@ -90,7 +92,7 @@ --  specialChars :: [Char]-specialChars = "'[]<=&*{}|\":\\"+specialChars = "'[]<=&*{}|\":\\_"  spaceChars :: [Char] spaceChars = " \n\t"@@ -102,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@@ -160,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@@ -533,6 +601,7 @@       <|> doubleQuotes       <|> strong       <|> emph+      <|> behaviorSwitch       <|> image       <|> internalLink       <|> externalLink@@ -571,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@@ -586,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@@ -597,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'@@ -716,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/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@@ -415,7 +418,7 @@      = False  ---constructPara :: ODTReaderSafe Blocks Blocks -> ODTReaderSafe Blocks Blocks+constructPara :: ODTReaderSafe a Blocks -> ODTReaderSafe a Blocks constructPara reader = proc blocks -> do   fStyle <- readStyleByName -< blocks   case fStyle of@@ -546,6 +549,14 @@ firstMatch :: a -> FirstMatch a firstMatch = FirstMatch . Alt . Just +newtype CombiningBlocks = CombiningBlocks { unCombiningBlocks :: Blocks }++instance Semigroup CombiningBlocks where+  CombiningBlocks l <> CombiningBlocks r = CombiningBlocks (combineBlocks l r)++instance Monoid CombiningBlocks where+  mempty = CombiningBlocks mempty+ -- matchingElement :: (Monoid e)                 => Namespace -> ElementName@@ -559,14 +570,20 @@ -- matchChildContent'   :: (Monoid result)                      => [ElementMatcher result]-                     ->  ODTReaderSafe _x result+                     ->  ODTReaderSafe a result matchChildContent' ls = returnV mempty >>> matchContent' ls  --+matchSmushedChildBlocks' :: [ElementMatcher CombiningBlocks] ->  ODTReaderSafe a Blocks+matchSmushedChildBlocks' ls = liftA unCombiningBlocks+                              $ returnV mempty+                                >>> matchContent' ls++-- matchChildContent    :: (Monoid result)                      => [ElementMatcher result]                      ->  ODTReaderSafe  (result, XML.Content) result-                     ->  ODTReaderSafe _x result+                     ->  ODTReaderSafe a result matchChildContent ls fallback = returnV mempty >>> matchContent ls fallback  --------------------------------------------@@ -634,34 +651,46 @@                                         ] read_plain_text  ---read_paragraph   :: BlockMatcher-read_paragraph    = matchingElement NsText "p"-                    $ constructPara-                    $ liftA para-                    $ withNewStyle-                    $ matchChildContent [ read_span-                                        , read_spaces-                                        , read_line_break-                                        , read_tab-                                        , read_link-                                        , read_note-                                        , read_citation-                                        , read_bookmark-                                        , read_bookmark_start-                                        , read_reference_start-                                        , read_bookmark_ref-                                        , read_reference_ref-                                        , read_frame-                                        , read_text_seq-                                        ] read_plain_text+read_paragraph   :: ElementMatcher CombiningBlocks+read_paragraph    = matchingElement NsText "p" $+                      liftA CombiningBlocks $ proc blocks -> do+                        fStyle <- readStyleByName -< blocks+                        case fStyle of+                          Right style | isPreformattedStyle style -> do+                            liftA (codeBlock . stringify) $ matchParagraphContent -< blocks+                          _ ->+                            constructPara $ liftA para $ withNewStyle matchParagraphContent -< blocks+                        where+                          isPreformattedStyle :: (StyleName, Style) -> Bool+                          isPreformattedStyle ("Preformatted_20_Text", _) = True+                          isPreformattedStyle (_, Style { styleParentName = Just "Preformatted_20_Text" }) = True+                          isPreformattedStyle _ = False  +matchParagraphContent :: ODTReaderSafe a Inlines+matchParagraphContent = matchChildContent [ read_span+                                          , read_spaces+                                          , read_line_break+                                          , read_tab+                                          , read_link+                                          , read_note+                                          , read_citation+                                          , read_bookmark+                                          , read_bookmark_start+                                          , read_reference_start+                                          , read_bookmark_ref+                                          , read_reference_ref+                                          , read_frame+                                          , read_text_seq+                                          ] read_plain_text++ ---------------------- -- Headers ----------------------  ---read_header      :: BlockMatcher+read_header      :: ElementMatcher CombiningBlocks read_header       = matchingElement NsText "h"                     $  proc blocks -> do   level    <- ( readAttrWithDefault NsText "outline-level" 1@@ -683,15 +712,16 @@               ) -< blocks   anchor   <- getHeaderAnchor -< children   let idAttr = (anchor, [], []) -- no classes, no key-value pairs-  arr (uncurry3 headerWith) -< (idAttr, level, children)+  arr (CombiningBlocks . uncurry3 headerWith) -< (idAttr, level, children)  ---------------------- -- Lists ----------------------  ---read_list        :: BlockMatcher+read_list        :: ElementMatcher CombiningBlocks read_list         = matchingElement NsText "list"+                    $ liftA CombiningBlocks                     $ constructList                     $ matchChildContent' [ read_list_item                                          , read_list_header@@ -706,26 +736,26 @@ read_list_element               :: ElementName -> ElementMatcher [Blocks] read_list_element listElement   = matchingElement NsText listElement                                   $ liftA (compactify.(:[]))-                                    ( matchChildContent' [ read_paragraph-                                                         , read_header-                                                         , read_list-                                                         , read_section-                                                         ]+                                    ( matchSmushedChildBlocks' [ read_paragraph+                                                               , read_header+                                                               , read_list+                                                               , read_section+                                                               ]                                     )  ---------------------- -- Sections ---------------------- -read_section :: ElementMatcher Blocks+read_section :: ElementMatcher CombiningBlocks read_section = matchingElement NsText "section"-                 $ liftA (divWith nullAttr)-                 $ matchChildContent' [ read_paragraph-                                      , read_header-                                      , read_list-                                      , read_table-                                      , read_section-                                      ]+                 $ liftA (CombiningBlocks . divWith nullAttr)+                 $ matchSmushedChildBlocks' [ read_paragraph+                                            , read_header+                                            , read_list+                                            , read_table+                                            , read_section+                                            ]   ----------------------@@ -768,7 +798,7 @@  read_note_body   :: BlockMatcher read_note_body    = matchingElement NsText "note-body"-                    $ matchChildContent' [ read_paragraph ]+                    $ matchSmushedChildBlocks' [ read_paragraph ]  ------------------------- -- Citations@@ -792,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@@ -847,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)@@ -883,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@@ -904,7 +950,7 @@ _ANCHOR_PREFIX_ = "anchor"  ---readAnchorAttr :: ODTReader _x Anchor+readAnchorAttr :: ODTReader a Anchor readAnchorAttr = findAttrText NsText "name"  -- | Beware: may fail@@ -945,7 +991,7 @@                      $ maybeAddAnchorFrom readAnchorAttr  -- | Beware: may fail-findAnchorRef :: ODTReader _x Anchor+findAnchorRef :: ODTReader a Anchor findAnchorRef = (      findAttrText NsText "ref-name"                   >>?^ (_ANCHOR_PREFIX_,)                 ) >>?! getPrettyAnchor@@ -980,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@@ -998,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,7 @@ 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(..)) @@ -298,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)
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/Org/Blocks.hs view
@@ -38,7 +38,7 @@ 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)@@ -73,6 +73,7 @@ block :: PandocMonad m => OrgParser m (F Blocks) block = choice [ mempty <$ blanklines                , table+               , dynamicBlock                , orgBlock                , figure                , example@@ -115,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)@@ -129,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@@ -184,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@@ -200,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], []) .@@ -227,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@@ -243,8 +247,13 @@  -- | Read the raw string content of a block rawBlockContent :: Monad m => Text -> OrgParser m Text-rawBlockContent blockType = try $ do-  blkLines <- manyTill rawLine blockEnder+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   -- split lines into indentation/contents tuples@@ -264,9 +273,6 @@    rawLine :: Monad m => OrgParser m Text    rawLine = try $ ("" <$ blankline) <|> anyLine -   blockEnder :: Monad m => OrgParser m ()-   blockEnder = try $ skipSpaces <* stringAnyCase ("#+end_" <> blockType)-    commaEscaped suff = case T.uncons suff of      Just (',', cs)        | "*"  <- T.take 1 cs -> cs@@ -307,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 ->@@ -427,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")@@ -438,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 -- @@ -522,7 +558,7 @@    exampleLine = try $ exampleLineStart *> anyLine  exampleCode :: Text -> Blocks-exampleCode = B.codeBlockWith ("", ["example"], [])+exampleCode = B.codeBlockWith ("", [], [])   --
src/Text/Pandoc/Readers/Org/Inlines.hs view
@@ -2,8 +2,8 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Readers.Org.Inlines-   Copyright   : Copyright (C) 2014-2024 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 <albert+pandoc@tarleb.com> @@ -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 '$'@@ -890,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 $@@ -924,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
@@ -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,7 +3,7 @@ {-# LANGUAGE OverloadedStrings     #-} {- |    Module      : Text.Pandoc.Readers.Org.ParserState-   Copyright   : Copyright (C) 2014-2024 Albert Krewinkel+   Copyright   : Copyright (C) 2014-2025 Albert Krewinkel    License     : GNU GPL, version 2 or above     Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>@@ -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,6 +1,6 @@ {- |    Module      : Text.Pandoc.Readers.Org.Parsing-   Copyright   : Copyright (C) 2014-2024 Albert Krewinkel+   Copyright   : Copyright (C) 2014-2025 Albert Krewinkel    License     : GNU GPL, version 2 or above     Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>@@ -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/Pod.hs view
@@ -258,7 +258,11 @@     entity (T.stripPrefix "0" -> Just suf)         | Just (n, "") <- oct (T.unpack suf) = lookupEntity $ "#" <> tshow n     entity (TR.decimal @Integer -> Right (x, "")) = lookupEntity $ "#" <> tshow x-    entity x = lookupEntity 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
+ 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
@@ -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
@@ -15,7 +15,7 @@ -} module Text.Pandoc.Readers.RST ( readRST ) where import Control.Arrow (second)-import Control.Monad (forM_, guard, liftM, mplus, mzero, when, unless)+import Control.Monad (forM_, guard, liftM, mplus, mzero, when, unless, void) import Control.Monad.Except (throwError) import Control.Monad.Identity (Identity (..)) import Data.Char (isHexDigit, isSpace, toUpper, isAlphaNum, generalCategory,@@ -23,7 +23,7 @@                                   DashPunctuation, OtherSymbol)) import Data.List (deleteFirstsBy, elemIndex, nub, partition, sort, transpose) import qualified Data.Map as M-import Data.Maybe (fromMaybe, maybeToList, isJust)+import Data.Maybe (fromMaybe, maybeToList, isJust, isNothing, catMaybes) import Data.Sequence (ViewR (..), viewr) import Data.Text (Text) import qualified Data.Text as T@@ -288,7 +288,7 @@   guard $ indent >= minIndent   char ':'   name <- many1TillChar (noneOf "\n") (char ':')-  (() <$ lookAhead newline) <|> skipMany1 spaceChar+  (void (lookAhead newline)) <|> skipMany1 spaceChar   first <- anyLine   rest <- option "" $ try $ do lookAhead (count indent (char ' ') >> spaceChar)                                indentedBlock@@ -343,7 +343,7 @@ optArg = do   c <- letter <|> char '<'   if c == '<'-     then () <$ manyTill (noneOf "<>") (char '>')+     then void $ manyTill (noneOf "<>") (char '>')      else skipMany (alphaNum <|> char '_' <|> char '-')  longOpt :: PandocMonad m => RSTParser m ()@@ -672,7 +672,7 @@ listItem start = try $ do   (markerLength, first) <- rawListItem start   rest <- many (listContinuation markerLength)-  skipMany1 blankline <|> () <$ lookAhead start+  skipMany1 blankline <|> void (lookAhead start)   -- parsing with ListItemState forces markers at beginning of lines to   -- count as list item markers, even if not separated by blank space.   -- see definition of "endline"@@ -710,7 +710,7 @@ comment :: Monad m => RSTParser m Blocks comment = try $ do   string ".."-  skipMany1 spaceChar <|> (() <$ lookAhead newline)+  skipMany1 spaceChar <|> void (lookAhead newline)   -- notFollowedBy' directiveLabel -- comment comes after directive so unnec.   _ <- anyLine   optional indentedBlock@@ -855,8 +855,9 @@            let figcls = concatMap (T.words . snd) figclasskv            let figattr = ("", figcls ++ aligncls, [])            let capt = B.caption Nothing (B.plain caption <> legend)+           let alt = maybe caption (B.text . trim) (lookup "alt" fields)            return $ B.figureWith figattr capt $-             B.plain (B.imageWith (imgident, imgcls, imgkvs) src "" (B.text src))+             B.plain (B.imageWith (imgident, imgcls, imgkvs) src "" alt)         "image" -> do            let src = escapeURI $ trim top            let alt = B.str $ maybe "image" trim $ lookup "alt" fields@@ -911,7 +912,10 @@          let tspecs = zip aligns' widths          return $ B.singleton $ Table attr (B.caption Nothing (B.plain title))                                   tspecs thead tbody tfoot-       _ -> return mempty+       _ -> do+         pos <- getPosition+         logMessage $ SkippedContent body pos+         return mempty   where     -- only valid on the very first row of a table section     rowLength (Row _ rb) = sum $ cellLength <$> rb@@ -1037,7 +1041,7 @@  parseCell :: PandocMonad m => Text -> RSTParser m Blocks parseCell t = singleParaToPlain-   <$> parseFromString' parseBlocks (t <> "\n\n")+   <$> parseFromString' parseBlocks (trim t <> "\n\n")   -- TODO:@@ -1358,7 +1362,6 @@ --    support for them -- -- Simple tables TODO:---  - column spans --  - multiline support --  - ensure that rightmost column span does not need to reach end --  - require at least 2 columns@@ -1367,67 +1370,105 @@ dashedLine ch = do   dashes <- many1 (char ch)   sp     <- many (char ' ')-  return (length dashes, length $ dashes ++ sp)+  return (length dashes, length sp)  simpleDashedLines :: Monad m => Char -> ParsecT Sources st m [(Int,Int)]-simpleDashedLines ch = try $ many1 (dashedLine ch)+simpleDashedLines ch = try $ do+  lines' <- many1 (dashedLine ch)+  skipMany spaceChar+  newline+  return $ addSpaces lines'+ where+  addSpaces [] = []+  addSpaces [(dashes, _)] = [(dashes, dashes)] -- Don't count trailing whitespaces+  addSpaces ((dashes, sp) : moreLines) =+    (dashes, dashes + sp) : addSpaces moreLines  -- Parse a table row separator-simpleTableSep :: Monad m => Char -> RSTParser m Char-simpleTableSep ch = try $ simpleDashedLines ch >> newline+simpleTableSep :: Monad m => Char -> RSTParser m ()+simpleTableSep ch = void (simpleDashedLines ch)  -- Parse a table footer-simpleTableFooter :: Monad m => RSTParser m Text-simpleTableFooter = try $ simpleTableSep '=' >> blanklines+simpleTableFooter :: Monad m => RSTParser m ()+simpleTableFooter = try $ simpleTableSep '=' >> void blanklines  -- Parse a raw line and split it into chunks by indices.-simpleTableRawLine :: Monad m => [Int] -> RSTParser m [Text]-simpleTableRawLine indices = simpleTableSplitLine indices <$> anyLine+simpleTableRawLine :: Monad m => [Int] -> RSTParser m [(Text, ColSpan)]+simpleTableRawLine indices = do+  row <- rowWithOptionalColSpan -simpleTableRawLineWithInitialEmptyCell :: Monad m => [Int] -> RSTParser m [Text]+  case simpleTableSplitLine indices row of+    Just rowLine -> return rowLine+    Nothing -> Prelude.fail "col spans don't match"++simpleTableRawLineWithInitialEmptyCell :: Monad m => [Int] -> RSTParser m [(Text, ColSpan)] simpleTableRawLineWithInitialEmptyCell indices = try $ do   cs <- simpleTableRawLine indices   let isEmptyCell = T.all (\c -> c == ' ' || c == '\t')   case cs of-    c:_ | isEmptyCell c -> return cs+    c:_ | isEmptyCell (fst c) -> return cs     _ -> mzero  -- Parse a table row and return a list of blocks (columns).-simpleTableRow :: PandocMonad m => [Int] -> RSTParser m [Blocks]+simpleTableRow :: PandocMonad m => [Int] -> RSTParser m [(Blocks, RowSpan, ColSpan)] simpleTableRow indices = do-  notFollowedBy' simpleTableFooter+  notFollowedBy' (void blanklines <|> simpleTableFooter)   firstLine <- simpleTableRawLine indices   conLines  <- many $ simpleTableRawLineWithInitialEmptyCell indices-  let cols = map T.unlines . transpose $ firstLine : conLines +++  let cols = map T.unlines . transpose $ (map fst firstLine) : (map (map fst) conLines) ++                                   [replicate (length indices) ""                                     | not (null conLines)]-  mapM parseCell cols+  let rowParser = mapM parseCell cols+  fmap (\blocks -> zip3 blocks (repeat 1) (map snd firstLine)) rowParser -simpleTableSplitLine :: [Int] -> Text -> [Text]-simpleTableSplitLine indices line =-  map trimr $ drop 1 $ splitTextByIndices (init indices) line+simpleTableSplitLine :: [Int] -> (Text, Maybe [Int]) -> Maybe [(Text, ColSpan)]+simpleTableSplitLine indices (line, maybeColspanIndices) =+  fmap (zip tableLines) columnSpans+ where+  splitTableLines lineIndices = map trimr $ drop 1 $ splitTextByIndices (init lineIndices) line+  (tableLines, columnSpans) = case maybeColspanIndices of+      Nothing -> (splitTableLines indices, Just $ repeat 1)+      Just colSpanIndices -> (splitTableLines colSpanIndices, colSpans indices colSpanIndices)  simpleTableHeader :: PandocMonad m                   => Bool  -- ^ Headerless table-                  -> RSTParser m ([Blocks], [Alignment], [Int])+                  -> RSTParser m ([[(Blocks, RowSpan, ColSpan)]], [Alignment], [Int]) simpleTableHeader headless = try $ do   optional blanklines+  dashes <- simpleDashedLines '='+   rawContent  <- if headless-                    then return ""-                    else simpleTableSep '=' >> 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@@ -1435,7 +1476,7 @@ simpleTable headless = do   let wrapIdFst (a, b, c) = (Identity a, b, c)       wrapId = fmap Identity-  tbl <- runIdentity <$> tableWith+  tbl <- runIdentity <$> tableWithSpans            (wrapIdFst <$> simpleTableHeader headless)            (wrapId <$> simpleTableRow)            sep simpleTableFooter@@ -1479,27 +1520,20 @@                        , 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 => RSTParser m Inlines escapedChar = do c <- escaped anyChar-                 unless (canPrecedeOpener c) $ updateLastStrPos-                 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 =@@ -1509,7 +1543,7 @@ symbol :: Monad m => RSTParser m Inlines symbol = do   c <- oneOf specialChars-  unless (canPrecedeOpener c) $ updateLastStrPos+  unless (canPrecedeOpener c) updateLastStrPos   return $ B.str $ T.singleton c  -- parses inline code, between codeStart and codeEnd@@ -1658,7 +1692,7 @@       <|> (char '\\' >> ((\c -> ['\\',c]) <$> noneOf "\n"))       <|> (string "\n" <* notFollowedBy blankline)       <|> try (string "`" <*-                notFollowedBy (() <$ roleMarker) <*+                notFollowedBy (void roleMarker) <*                 lookAhead (satisfy isAlphaNum))        )   char '`'@@ -1806,3 +1840,37 @@     s{ stateKeys = M.insert (toKey name) (("#" <> ident, ""), nullAttr)                     (stateKeys s) }   pure $ B.spanWith (ident,[],[]) (B.text name)++dashedLinesToLinesWithIndices :: [(Int, Int)] -> ([Int], [Int])+dashedLinesToLinesWithIndices dashes =+  let lines'  = map snd dashes+      indices = scanl (+) 0 lines'+  in  (lines', indices)++-- | Determines column spans by appying indices of a table border with column span indices.+--+-- The indices need to align.+colSpans :: [Int] -> [Int] -> Maybe [ColSpan]+colSpans [] []  = Just []+colSpans [] _   = Nothing+colSpans _ []   = Nothing+colSpans (index : indices) colSpanIndices@(colIndex : colSpanIndicesTail)+    | index /= colIndex = colSpans indices colSpanIndices+    | otherwise =+        -- For a matching index start counting the column spans.+        let (spanCount, remainingIndices, remainingColSpanindices) = colSpanCount indices colSpanIndicesTail 1+        in  (:) spanCount <$> colSpans remainingIndices remainingColSpanindices++-- | Counts column spans by consuming all non-matching indices until a matching one is encountered.+--+-- If the indices match, the end of a column span has been encountered and the+-- column count can be returned. Otherwise, if the indices don't match, add to+-- the span count until a matching index is found.+colSpanCount :: [Int] -> [Int] -> ColSpan -> (ColSpan, [Int], [Int])+colSpanCount [] colSpanIndices spanCount = (spanCount, [], colSpanIndices)+colSpanCount _ [] spanCount = (spanCount, [], [])+colSpanCount indices@(index : indicesTail) colSpanIndices@(colIndex : colSpanIndicesTail) spanCount+    | index == colIndex = case colSpanIndicesTail of+        [] -> (spanCount, indicesTail, colSpanIndicesTail)+        _ -> (spanCount, indices, colSpanIndices)+    | otherwise = colSpanCount indicesTail colSpanIndices $ spanCount + 1
src/Text/Pandoc/Readers/RTF.hs view
@@ -20,7 +20,7 @@ import Control.Monad import Control.Monad.Except (throwError) import Crypto.Hash (hashWith, SHA1(SHA1))-import Data.List (find, foldl')+import qualified Data.List as L import Data.Word (Word8, Word16) import Data.Default import Data.Text (Text)@@ -305,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@@ -546,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@@ -558,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"@@ -627,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 @@ -671,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@@ -678,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@@ -784,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 @@ -881,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 _)) =@@ -906,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@@ -944,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@@ -964,7 +1016,7 @@      (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)  defaultAnsiWordToChar :: Word8 -> Char
src/Text/Pandoc/Readers/Roff.hs view
@@ -268,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
src/Text/Pandoc/Readers/Textile.hs view
@@ -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)]@@ -732,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))
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
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@@ -120,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@@ -208,31 +231,42 @@ 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' <- getField "attribution" fields@@ -241,11 +275,11 @@                         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@@ -274,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@@ -287,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 ->+  ,("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 <-@@ -333,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@@ -345,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@@ -364,16 +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+  ,("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@@ -384,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 =@@ -409,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@@ -448,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@@ -465,9 +526,15 @@                pWithContents                 (B.fromList . blocksToInlines . B.toList <$> pBlocks) body       pure $ B.link src "" description)-  ,("image", \_ fields -> do+  ,("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) <-@@ -478,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@@ -490,23 +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+  ,("pad", \_ _ fields ->  -- ignore paddingy       getField "body" fields >>= pWithContents pInlines)-  ,("block", \mbident fields ->+  ,("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)
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/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/SelfContained.hs view
@@ -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@@ -420,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 #-}@@ -56,6 +57,7 @@                      inlineListToIdentifier,                      textToIdentifier,                      isHeaderBlock,+                     hasLineBreaks,                      onlySimpleTableCells,                      isTightList,                      taskListItemFromAscii,@@ -90,7 +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)+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 (..) )@@ -138,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@@ -235,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@@ -261,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)  --@@ -407,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 @@ -607,6 +617,18 @@                      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@@ -713,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@@ -733,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@@ -749,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/Templates.hs view
@@ -102,6 +102,7 @@        "native"  -> return ""        "csljson" -> return ""        "json"    -> return ""+       "xml"     -> return ""        "fb2"     -> return ""        "pptx"    -> return ""        "ipynb"   -> return ""@@ -120,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/Translations.hs view
@@ -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/UTF8.hs view
@@ -8,7 +8,7 @@    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/Writers.hs view
@@ -76,8 +76,16 @@     , writeTexinfo     , writeTextile     , writeTypst+    , writeXML     , writeXWiki     , writeZimWiki+    , writeVimdoc+    , writeBBCode+    , writeBBCodeSteam+    , writeBBCodeFluxBB+    , writeBBCodePhpBB+    , writeBBCodeHubzilla+    , writeBBCodeXenforo     , getWriter     ) where @@ -128,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)@@ -203,6 +221,14 @@   ,("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
@@ -1,7 +1,8 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Writers.ANSI-   Copyright   : Copyright (C) 2024 Evan Silberman+   Copyright   : © 2024 Evan Silberman+                 © 2025 Pandoc contributors    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -14,6 +15,7 @@ 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 ((<+>), ($$), ($+$))@@ -30,6 +32,7 @@ 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@@ -76,26 +79,37 @@   metadata <- metaToContext opts                  (blockListToANSI opts)                  (inlineListToANSI opts) meta-  width <- gets stColumns-  let title = titleBlock width metadata+  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) = D.cblock width hr $+$ hangMarks hangWidth marks notes-                 | otherwise = D.empty+  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 (Just width) main-         Just tpl -> toStrict $ D.renderANSI (Just width) $ renderTemplate tpl context+         Nothing  -> toStrict $ D.renderANSI colwidth main+         Just tpl -> toStrict $ D.renderANSI colwidth+                              $ renderTemplate tpl context -titleBlock :: Int -> Context Text -> D.Doc Text-titleBlock width meta = if null most then D.empty else D.cblock width $ most $+$ hr+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@@ -155,15 +169,20 @@ -- Doc Text. blockToANSI opts (CodeBlock attr str) = do   table <- gets stInTable-  inner <- case (table, writerHighlightStyle opts) of-    (_, Nothing) -> return $ defaultStyle str+  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, Just 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+    (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@@ -173,7 +192,6 @@   contents <- withFewerColumns 2 $ blockListToANSI opts blocks   return ( D.prefixed "│ " contents $$ D.blankline) --- TODO: Row spans don't work blockToANSI opts (Table _ (Caption _ caption) colSpecs (TableHead _ thead) tbody (TableFoot _ tfoot)) = do   let captionInlines = blocksToInlines caption   captionMarkup <-@@ -195,22 +213,40 @@       maxWidth k = claimWidth k   let widths = map maxWidth inWidths   let decor = [D.hsep $ map rule widths]-  head' <- mapM (goRow widths . unRow) thead-  body' <- mapM (goRow widths . unRow) (unBodies tbody)-  foot' <- mapM (goRow widths . unRow) tfoot+  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-    unBody (TableBody _ _ hd bd) = hd <> bd-    unBodies = concatMap unBody-    goRow ws cs = do-      (d, _) <- foldM goCell ([], ws) cs-      return $ D.hcat $ intersperse (D.vfill " ") $ reverse d-    goCell (r, ws) (Cell _ aln _ (ColSpan cspan) inner) = do+    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, ws')+      return ((render innerDoc):r, colPos + cspan, ws')     tcell AlignLeft    = D.lblock     tcell AlignRight   = D.rblock     tcell AlignCenter  = D.cblock
src/Text/Pandoc/Writers/AsciiDoc.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP  #-} {-# LANGUAGE LambdaCase        #-} {-# LANGUAGE OverloadedStrings #-} {- |@@ -28,9 +29,15 @@ 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)@@ -43,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@@ -150,6 +163,7 @@   needsEscape '+' = True   needsEscape '`' = True   needsEscape '*' = True+  needsEscape '#' = True   needsEscape '_' = True   needsEscape '<' = True   needsEscape '>' = True@@ -269,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@@ -290,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="@@ -310,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@@ -335,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 }@@ -416,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 <>@@ -433,18 +483,24 @@     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 =@@ -464,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@@ -538,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 }@@ -554,25 +612,27 @@   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   contents <- inlineListToAsciiDoc opts lst@@ -709,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/ConTeXt.hs view
@@ -4,7 +4,7 @@ {-# LANGUAGE ViewPatterns        #-} {- |    Module      : Text.Pandoc.Writers.ConTeXt-   Copyright   : Copyright (C) 2007-2024 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@@ -131,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@@ -233,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)@@ -625,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
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
src/Text/Pandoc/Writers/DocBook.hs view
@@ -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@@ -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
@@ -6,744 +6,850 @@ {-# LANGUAGE OverloadedStrings   #-} {- |    Module      : Text.Pandoc.Writers.Docx-   Copyright   : Copyright (C) 2012-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 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.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.MIME (getMimeTypeDef)-import Text.Pandoc.Options-import Text.Pandoc.Readers.Docx.Parse (extractTarget)-import Text.Pandoc.Writers.Docx.StyleMap-import Text.Pandoc.Writers.Docx.Types-import Text.Pandoc.Writers.Docx.OpenXML (writeOpenXML, maxListLevel)-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 Data.Generics (mkT, everywhere)-import Text.Collate.Lang (renderLang, Lang(..))--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' = makeSectionsWithOffsets (writerNumberOffset opts)-                   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 == "ja" || 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 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-        }--  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")-                    ]--  let initialSt = defaultWriterState {-          stStyleMaps  = styleMaps-        , stTocTitle   = tocTitle-        , stCurId      = newMaxRelId + 1-        }--  -- 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 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")]--- -- 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--  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--  let contents' = BL.fromStrict $ UTF8.fromText contents--  -- word/document.xml-  let contentEntry = toEntry "word/document.xml" epochtime contents'--  -- 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)--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 <> "."+   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
@@ -9,7 +9,7 @@ {-# LANGUAGE TypeApplications    #-} {- |    Module      : Text.Pandoc.Writers.Docx-   Copyright   : Copyright (C) 2012-2024 John MacFarlane+   Copyright   : Copyright (C) 2012-2025 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -30,7 +30,7 @@ import Data.Ord (comparing) import Data.String (fromString) import qualified Data.Map as M-import Data.Maybe (fromMaybe, isNothing, maybeToList, isJust)+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@@ -220,6 +220,15 @@       ]) -- 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@@ -317,7 +326,9 @@  -- | 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)+blocksToOpenXML opts =+  fmap concat . mapM (blockToOpenXML opts)+  . separateTables . filter (not . isForeignRawBlock)  isForeignRawBlock :: Block -> Bool isForeignRawBlock (RawBlock format _) = format /= "openxml"@@ -395,13 +406,19 @@                 Nothing -> return []            else return []   contents <- (number ++) <$> inlinesToOpenXML opts lst-  sectpr <- asks envSectPr-  let addSectionBreak-       | isSection-       , Just sectPrElem <- sectpr-        = (Elem (mknode "w:p" []-                   (mknode "w:pPr" [] [sectPrElem])) :)-       | otherwise = id+  -- Add section break before section-level headers, but not for the first one+  -- to avoid a blank first page (#10578, #11482).+  addSectionBreak <- if isSection+    then do+      isFirst <- gets stFirstSectionHeader+      if isFirst+        then do+          modify $ \s -> s { stFirstSectionHeader = False }+          pure id+        else sectionSeparator >>= \case+          Just sep -> pure (sep:)+          Nothing  -> pure id+    else pure id   addSectionBreak <$>     if T.null ident        then return [Elem $ mknode "w:p" [] (map Elem paraProps ++ contents)]@@ -421,6 +438,10 @@      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@@ -758,17 +779,20 @@       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) _) =+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)-  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')] () ]-     ]+  -- 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@@ -873,18 +897,21 @@           [ 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")-    $ 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+    $ 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@@ -900,6 +927,7 @@                                 , 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" []@@ -1041,6 +1069,7 @@             Just Emf  -> ".emf"             Just Tiff -> ".tiff"             Just Webp -> ".webp"+            Just Avif -> ".avif"             Nothing   -> ""         imgpath = "media/" <> ident <> imgext         mbMimeType = mt <|> getMimeType (T.unpack imgpath)
src/Text/Pandoc/Writers/Docx/Types.hs view
@@ -121,6 +121,7 @@        , stDelId          :: Int        , stStyleMaps      :: StyleMaps        , stFirstPara      :: Bool+       , stFirstSectionHeader :: Bool  -- ^ True until first section header is processed        , stNumIdUsed      :: Bool  -- ^ True if the current numId (envListNumId) has been used.                                    --   Should only be used once, for the first paragraph.        , stInTable        :: Bool@@ -146,6 +147,7 @@       , stDelId          = 1       , stStyleMaps      = StyleMaps M.empty M.empty       , stFirstPara      = False+      , stFirstSectionHeader = True       , stNumIdUsed      = False       , stInTable        = False       , stInList         = False
src/Text/Pandoc/Writers/EPUB.hs view
@@ -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@@ -1048,10 +1048,9 @@         coverageNodes = maybe [] (dcTag' "coverage") $ epubCoverage md         rightsNodes = maybe [] (dcTag' "rights") $ epubRights md         coverImageNodes = maybe []-            (\img -> [unode "meta" !  [(metaprop,"cover"),-                                       ("content",toId img)] $ ()-                        | version == EPUB2])-            $ mbCoverImage+            (\img -> [unode "meta" !  [("name","cover"),+                                       ("content",toId img)] $ ()])+            mbCoverImage         modifiedNodes = [ unode "meta" ! [(metaprop, "dcterms:modified")] $                showDateTimeISO8601 currentTime | version == EPUB3 ]         belongsToCollectionNodes =@@ -1141,11 +1140,18 @@         schemeToOnix "ISBN-13"              = "15"         schemeToOnix "Legal deposit number" = "17"         schemeToOnix "URN"                  = "22"-        schemeToOnix "OCLC"                 = "23"+        schemeToOnix "OCLC number"          = "23"+        schemeToOnix "Co-publisher’s ISBN-13" = "24"         schemeToOnix "ISMN-13"              = "25"         schemeToOnix "ISBN-A"               = "26"-        schemeToOnix "JP"                   = "27"-        schemeToOnix "OLCC"                 = "28"+        schemeToOnix "JP e-code"            = "27"+        schemeToOnix "OLCC number"          = "28"+        schemeToOnix "JP Magazine ID"       = "29"+        schemeToOnix "UPC-12+5"             = "30"+        schemeToOnix "BNF Control number"   = "31"+        schemeToOnix "ISSN-13"              = "34"+        schemeToOnix "ARK"                  = "35"+        schemeToOnix "Digital file internal version number" = "36"         schemeToOnix _                      = "01"  showDateTimeISO8601 :: UTCTime -> Text@@ -1197,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/GridTable.hs view
@@ -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
@@ -35,7 +35,8 @@ import Control.Monad ( liftM, when, foldM, unless ) import Control.Monad.Trans ( MonadTrans(lift) ) import Data.Char (ord, isSpace, isAscii)-import Data.List (intercalate, intersperse, partition, delete, (\\), foldl')+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)@@ -48,12 +49,12 @@ 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@@ -125,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@@ -317,7 +318,8 @@         MathJax url           | slideVariant /= RevealJsSlides ->           -- mathjax is handled via a special plugin in revealjs-            H.script ! A.src (toValue $ toURI html5 url)+            H.script ! A.defer mempty+                    ! A.src (toValue $ toURI html5 url)                     ! A.type_ "text/javascript"                     $ case slideVariant of                             SlideousSlides ->@@ -356,10 +358,14 @@   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 .@@ -427,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) .@@ -665,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]@@ -785,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@@ -845,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@@ -926,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 }@@ -943,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;@@ -1030,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@@ -1397,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@@ -1437,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)@@ -1536,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@@ -1590,7 +1636,7 @@                               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@@ -1668,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)@@ -1747,23 +1795,24 @@ 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"]----- We need to remove links from link text, because an <a> element is--- not allowed inside another <a> element.-removeLinks :: [Inline] -> [Inline]-removeLinks = walk go- where-  go (Link attr ils _) = Span attr ils-  go x = x  toURI :: Bool -> Text -> Text toURI isHtml5 t = if isHtml5 then t else escapeURI t
src/Text/Pandoc/Writers/ICML.hs view
@@ -44,6 +44,7 @@ data WriterState = WriterState{     blockStyles  :: Set.Set Text   , inlineStyles :: Set.Set Text+  , objectStyles :: Set.Set Text   , links        :: Hyperlink   , listDepth    :: Int   , maxListDepth :: Int@@ -55,6 +56,7 @@ defaultWriterState = WriterState{     blockStyles  = Set.empty   , inlineStyles = Set.empty+  , objectStyles = Set.empty   , links        = []   , listDepth    = 1   , maxListDepth = 0@@ -147,9 +149,10 @@              meta   (main, st) <- runStateT (blocksToICML opts [] blocks) defaultWriterState   let context = defField "body" main-              $ defField "charStyles" (charStylesToDoc st)-              $ defField "parStyles"  (parStylesToDoc st)-              $ defField "hyperlinks" (hyperlinksToDoc $ links st) metadata+              $ defField "charStyles"   (charStylesToDoc st)+              $ defField "parStyles"    (parStylesToDoc st)+              $ defField "objectStyles" (objectStylesToDoc st)+              $ defField "hyperlinks"   (hyperlinksToDoc $ links st) metadata   return $ render colwidth $     (if writerPreferAscii opts then fmap toEntities else id) $     case writerTemplate opts of@@ -272,6 +275,16 @@                          else empty       in  inTags True "CharacterStyle" ([("Self", "CharacterStyle/"<>s), ("Name", s)] ++ attrs') props +-- | Convert a WriterState with its object styles to the ICML listing of Object Styles.+objectStylesToDoc :: WriterState -> Doc Text+objectStylesToDoc st = vcat $ map makeStyle $ Set.toAscList $ objectStyles st+  where+    makeStyle s =+      let attrs = []+          props = inTags True "Properties" [] $+                    inTags False "BasedOn" [("type", "string")] (text "$ID/None")+      in  inTags True "ObjectStyle" ([("Self", "ObjectStyle/"<>s), ("Name", s)] ++ attrs) props+ -- | Escape colon characters as %3a escapeColons :: Text -> Text escapeColons txt = Text.replace ":" "%3a" txt@@ -601,6 +614,10 @@       attrs = [("AppliedCharacterStyle", stl)]   in  (stlStr, attrs) +-- | Key for specifying user-defined object (image) styles+objectStyleKey :: Text+objectStyleKey = "object-style"+ -- | Assemble an ICML Image. imageICML :: PandocMonad m => WriterOptions -> Style -> Attr -> Target -> WS m (Doc Text) imageICML opts style attr (src, _) = do@@ -647,19 +664,31 @@                 then mempty                 else  selfClosingTag "Link" [("Self", "ueb"),                                              ("LinkResourceURI", src')]-      image  = inTags True "Image"-                   [("Self","ue6"), ("ItemTransform", scale<>" -"<>hw<>" -"<>hh)]-                 $ vcat [-                     inTags True "Properties" [] $ vcat [-                         inTags True "Profile" [("type","string")] $ text "$ID/Embedded"-                       , selfClosingTag "GraphicBounds" [("Left","0"), ("Top","0")-                         , ("Right",  showFl $ ow*ow / imgWidth)-                         , ("Bottom", showFl $ oh*oh / imgHeight)]-                       , contents-                       ]-                   , link-                   ]-      doc    = inTags True "CharacterStyleRange" attrs-                 $ inTags True "Rectangle" [("Self","uec"), ("StrokeWeight", "0"),-                     ("ItemTransform", scale<>" "<>hw<>" -"<>hh)] (props $$ image)-  state $ \st -> (doc, st{ inlineStyles = Set.insert stlStr $ inlineStyles st } )+      (_,_,kvs) = attr+      applyObjectStyle = lookup objectStyleKey kvs+      image = inTags True "Image"+            [("Self","ue6"), ("ItemTransform", scale <> " -" <> hw <> " -" <> hh)]+            $ vcat [+                inTags True "Properties" [] $ vcat [+                    inTags True "Profile" [("type","string")] $ text "$ID/Embedded",+                    selfClosingTag "GraphicBounds" [("Left","0"), ("Top","0"),+                    ("Right", showFl $ ow * ow / imgWidth),+                    ("Bottom", showFl $ oh * oh / imgHeight)],+                    contents+                ],+                link+            ]+      doc   = inTags True "CharacterStyleRange" attrs+          $ inTags True "Rectangle"+              ([("Self","uec"),+                ("StrokeWeight", "0"),+                ("ItemTransform", scale <> " " <> hw <> " -" <> hh)] +++                maybe [] (\aos -> [("AppliedObjectStyle", "ObjectStyle/" <> aos)]) applyObjectStyle+              )+              (props $$ image)+  state $ \st -> (doc, st{+      inlineStyles = Set.insert stlStr $ inlineStyles st,+      objectStyles = case applyObjectStyle of+          Just styleName -> Set.insert styleName $ objectStyles st+          Nothing        -> objectStyles st+    })
src/Text/Pandoc/Writers/JATS.hs view
@@ -360,11 +360,21 @@   return $ inTags True cls attr contents blockToJATS opts (Div (ident,_,kvs) bs) = do   contents <- blocksToJATS opts bs-  let attr = [("id", escapeNCName ident) | not (T.null ident)] ++-             [("xml:lang",l) | ("lang",l) <- kvs] ++-             [(k,v) | (k,v) <- kvs, k `elem` ["specific-use",-                 "content-type", "orientation", "position"]]-  return $ inTags True "boxed-text" attr contents+  -- Attributes that are allowed on both @<p>@ and @<boxed-text>@ elements+  let generic_attr = [("id", escapeNCName ident) | not (T.null ident)] +++                     [("xml:lang",l) | ("lang",l) <- kvs] +++                     [(k,v) | (k,v) <- kvs, k `elem` ["specific-use",+                                                      "content-type"]]+  let boxed_attr = [(k,v) | (k,v) <- kvs, k `elem` ["orientation", "position"]]+  let attr = generic_attr <> boxed_attr+  return $+    if null attr+    then contents+    else -- The contents must be wrapped in an appropriate element.+      let element = if null boxed_attr+                    then "p"+                    else "boxed-text"+      in inTags True element (generic_attr <> boxed_attr) contents blockToJATS opts (Header _ _ title) = do   title' <- inlinesToJATS opts (map fixLineBreak title)   return $ inTagsSimple "title" title'@@ -439,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/LaTeX.hs view
@@ -7,7 +7,7 @@ {-# LANGUAGE ViewPatterns        #-} {- |    Module      : Text.Pandoc.Writers.LaTeX-   Copyright   : Copyright (C) 2006-2024 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), Val(..), 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]@@ -176,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) $@@ -196,7 +219,18 @@                            _         -> [])                     $ 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@@ -206,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) $@@ -221,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 .@@ -254,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' =@@ -282,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@@ -469,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 -> []) ++@@ -502,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@@ -616,11 +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 }@@ -637,7 +699,7 @@       , stSubfigure = stSubfigure st || isSubfigure       } -  let containsTable = getAny . (query $ \case+  let containsTable = getAny . query (\case         Table {}  -> Any True         _         -> Any False)   st <- get@@ -652,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)@@ -745,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}}@@ -782,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/@@ -797,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.@@ -907,6 +970,7 @@   inHeading <- gets stInHeading   inItem <- gets stInItem   inSoul <- gets stInSoulCommand+  inCaption <- gets stInCaption   let listingsCode = do         let listingsopts = (case getListingsLanguage classes of                                 Just l  -> (("language", mbBraced l):)@@ -959,13 +1023,22 @@   -- (see #1294). with regular texttt we don't get an error, but we get   -- incorrect results if there is a space (see #5529).   let inMbox x = "\\mbox" <> braces x-  (if inSoul then inMbox else id) <$>-   case () of++  -- 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@@ -1002,10 +1075,16 @@ 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   inSoul <- gets stInSoulCommand   let contents = literal (handleMathComment str)+  when (needsCancel str) $ modify $ \st -> st{ stCancel = True }   return $     if inSoul -- #9597        then "$" <> contents <> "$"@@ -1014,6 +1093,7 @@   setEmptyLine False   inSoul <- gets stInSoulCommand   let contents = literal (handleMathComment str)+  when (needsCancel str) $ modify $ \st -> st{ stCancel = True }   return $     if inSoul -- # 9597        then "$$" <> contents <> "$$"@@ -1053,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@@ -1145,9 +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)+  -- and ensure that the note is on the frame, not e.g. the column (#5769, #5954)+  incremental <- gets stIncremental   let beamerMark = if beamer-                      then text "<.->[frame]"+                      then if incremental+                           then text "<.->[frame]"+                           else text "<\\value{beamerpauses}->[frame]"                       else empty   if externalNotes      then do@@ -1197,6 +1284,15 @@   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@@ -1289,3 +1385,127 @@   , "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
@@ -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
@@ -21,7 +21,7 @@ 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@@ -73,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@@ -182,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 
src/Text/Pandoc/Writers/LaTeX/Lang.hs view
@@ -40,7 +40,7 @@ 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/Table.hs view
@@ -98,8 +98,10 @@   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'
src/Text/Pandoc/Writers/LaTeX/Types.hs view
@@ -2,6 +2,7 @@   ( LW   , WriterState (..)   , startingState+  , PdfStandard (..)   ) where  import Control.Monad.State.Strict (StateT)@@ -53,8 +54,17 @@   , 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@@ -93,4 +103,6 @@   , stIsFirstInDefinition = False   , stLang = Nothing   , stInSoulCommand = False+  , stCancel = False+  , stInCaption = False   }
src/Text/Pandoc/Writers/LaTeX/Util.hs view
@@ -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"
src/Text/Pandoc/Writers/Man.hs view
@@ -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)@@ -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@@ -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
@@ -25,7 +25,7 @@ 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@@ -526,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) @@ -576,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@@ -589,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@@ -602,10 +609,13 @@         | otherwise            = "> "   contents <- blockListToMarkdown opts blocks   return $ text leader <> prefixed leader contents <> blankline-blockToMarkdown' opts t@(Table (ident,_,_) blkCapt specs thead tbody tfoot) = do+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@@ -616,16 +626,17 @@   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 && not hasColRowSpans+  let isSimple = hasSimpleCells && not hasFooter &&+                 all (==0) widths && not hasColRowSpans   let isPlainBlock (Plain _) = True       isPlainBlock _         = False   let hasBlocks = not (all (all (all isPlainBlock)) $ headers:rows)@@ -638,50 +649,47 @@   let widths' = case numcols - length widths of                      x | x > 0 -> widths ++ replicate x 0.0                        | otherwise -> widths+  let mkTable f = do+       rawHeaders <- padRow <$> mapM (blockListToMarkdown opts) headers+       rawRows <- mapM (fmap padRow . mapM (blockListToMarkdown opts)) rows+       f (all null headers) aligns' widths' rawHeaders rawRows   case True of      _ | isSimple &&          isEnabled Ext_simple_tables opts -> do-           rawHeaders <- padRow <$> mapM (blockListToMarkdown opts) headers-           rawRows <- mapM (fmap padRow . mapM (blockListToMarkdown opts))-                      rows-           tbl <- pandocTable opts False (all null headers)-                      aligns' widths' rawHeaders rawRows+           tbl <- mkTable (pandocTable opts False)            return $ nest 2 (tbl $$ caption''') $$ blankline        | isSimple &&          isEnabled Ext_pipe_tables opts -> do-           rawHeaders <- padRow <$> mapM (blockListToMarkdown opts) headers-           rawRows <- mapM (fmap padRow . mapM (blockListToMarkdown opts))-                      rows-           tbl <- pipeTable opts (all null headers) aligns' widths'-                     rawHeaders rawRows+           tbl <- mkTable (pipeTable opts)            return $ (tbl $$ caption''') $$ blankline-       | not (hasBlocks || hasColRowSpans) &&+       | not (hasBlocks || hasColRowSpans || hasFooter) &&          isEnabled Ext_multiline_tables opts -> do-           rawHeaders <- padRow <$> mapM (blockListToMarkdown opts) headers-           rawRows <- mapM (fmap padRow . mapM (blockListToMarkdown opts))-                      rows-           tbl <- pandocTable opts True (all null headers)-                     aligns' widths' rawHeaders rawRows+           tbl <- mkTable (pandocTable opts True)            return $ nest 2 (tbl $$ caption''') $$ blankline        | isEnabled Ext_grid_tables opts &&-          (hasColRowSpans || writerColumns opts >= 8 * numcols) -> do+          (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-           rawHeaders <- padRow <$> mapM (blockListToMarkdown opts) headers-           rawRows <- mapM (fmap padRow . mapM (blockListToMarkdown opts))-                      rows-           tbl <- pipeTable opts (all null headers) aligns' widths'-                    rawHeaders rawRows+           tbl <- mkTable (pipeTable opts)            return $ (tbl $$ caption''') $$ blankline        | isEnabled Ext_raw_html opts -> do -- HTML fallback            tbl <- literal . removeBlankLinesInHTML <$>                      writeHtml5String opts{ writerTemplate = Nothing }                      (Pandoc nullMeta [t])            return $ tbl $$ blankline  -- caption is in the HTML table+       | hasSimpleCells,+         hasColRowSpans,+         isEnabled Ext_pipe_tables opts -> do+           -- In this case an approximate pipe table will be rendered,+           -- without col/row spans. This is better than nothing, since+           -- we have no other way to render the table correctly (#11128).+           tbl <- mkTable (pipeTable opts)+           return $ (tbl $$ caption''') $$ blankline        | otherwise          -> do            report (BlockNotRendered t)@@ -719,30 +727,32 @@   return $ mconcat contents <> blankline blockToMarkdown' opts (Figure figattr capt body) = do   let combinedAttr imgattr = case imgattr of-        ("", cls, kv)-          | (figid, [], []) <- figattr -> Just (figid, cls, kv)-        _ -> Nothing-  let combinedAlt alt = case capt of-        Caption Nothing [] -> if null alt-                              then Just [Str "image"]-                              else Just alt-        Caption Nothing [Plain captInlines]-          | null alt || stringify captInlines == stringify alt-            -> Just captInlines-        Caption Nothing [Para captInlines]-          | null alt || stringify captInlines == stringify alt-            -> Just captInlines+        ("", cls, kvs)+          | (figid, [], []) <- figattr+            -> Just (figid, cls, [(k,v) | (k,v) <- kvs+                                        , k /= "alt" ||+                                          v /= "" && v /= trim (stringify capt)])         _ -> Nothing   case body of     [Plain [Image imgAttr alt (src, ttl)]]       | isEnabled Ext_implicit_figures opts-      , Just descr    <- combinedAlt alt       , Just imgAttr' <- combinedAttr imgAttr       , isEnabled Ext_link_attributes opts || imgAttr' == nullAttr         -> do           -- use implicit figures if possible           let tgt' = (src, fromMaybe ttl $ T.stripPrefix "fig:" ttl)-          contents <- inlineListToMarkdown opts [Image imgAttr' descr tgt']+          let descr = case capt of+                        Caption _ bs -> blocksToInlines bs+          -- add alt attribute if image description different from caption,+          -- so this won't be lost:+          let imgAttr'' = case imgAttr' of+                            (i,c,kv)+                              | not (null alt)+                              , Nothing <- lookup "alt" kv+                              , stringify descr /= stringify alt ->+                                 (i, c, ("alt", stringify alt) : kv)+                            _ -> imgAttr'+          contents <- inlineListToMarkdown opts [Image imgAttr'' descr tgt']           return $ contents <> blankline     _ ->       -- fallback to raw html if possible or div otherwise@@ -851,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@@ -948,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
@@ -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@@ -500,24 +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_gfm opts ->-                return $ "$`" <> literal str <> "`$"+                return $ "$`" <> literal str' <> "`$"             | isEnabled Ext_tex_math_dollars opts ->-                return $ delimited "$" "$" (literal str)+                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) @@ -540,7 +546,7 @@                              $$ literal (T.dropAround (=='\n') str)                              $$ literal "```") <> cr             | isEnabled Ext_tex_math_dollars opts ->-                return $ delimited "$$" "$$" (literal str)+                return $ "$$" <> literal str <> "$$"             | isEnabled Ext_tex_math_single_backslash opts ->                 return $ "\\[" <> literal str <> "\\]"             | isEnabled Ext_tex_math_double_backslash opts ->@@ -583,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
src/Text/Pandoc/Writers/MediaWiki.hs view
@@ -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)@@ -62,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@@ -85,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@@ -98,60 +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 initEsc = if startsWithListMarker contents -- #9700-                   then "\\"-                   else ""+  let contents' = render Nothing contents+  let initEsc = if startsWithListMarker contents'+                   then literal "<nowiki></nowiki>"+                   else mempty   return $ if tags-              then  "<p>" <> contents <> "</p>"-              else initEsc <> 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 ">"@@ -166,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)@@ -177,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 <-@@ -189,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 <-@@ -201,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)@@ -224,20 +234,20 @@           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@@ -245,12 +255,12 @@   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@@ -287,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@@ -356,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@@ -385,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)@@ -405,126 +407,130 @@      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) = do   inDefLabel <- gets stInDefLabel-  return $+  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 [
src/Text/Pandoc/Writers/Ms.hs view
@@ -76,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
src/Text/Pandoc/Writers/ODT.hs view
@@ -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)@@ -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)@@ -224,6 +228,56 @@  where    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)
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@@ -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@@ -121,10 +145,6 @@ 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 } @@ -163,22 +183,25 @@   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,56 +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-         liststyles <- gets stListStyles-         let ls = case liststyles of-                    [] -> (1,[])  -- should never happen-                    (s:_) -> s-         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)@@ -354,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)@@ -390,15 +458,16 @@     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+        _ -> 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"@@ -413,7 +482,7 @@                            setInDefinitionList False                            return r       unhighlighted s = flush . vcat <$>-            (mapM (inPreformattedTags . (:[])) (map preformatted (T.lines s)))+            (mapM ((inPreformattedTags . (:[])) . preformatted) (T.lines s))       mkDiv    attr s = do         let (ident,_,kvs) = attr             i = withLangFromAttr attr $@@ -424,16 +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+      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 _) = do+          (Ann.Table (ident, _, _) (Caption _ c) colspecs thead tbodies tfoot) = do         tn <- length <$> gets stTableStyles         pn <- length <$> gets stParaStyles         let  genIds      = map chr [65..]@@ -459,10 +531,11 @@                                 else unNumberedCaption "TableCaption"         th <- colHeadsToOpenDocument o (map fst paraHStyles) thead         tr <- mapM (tableBodyToOpenDocument o (map fst paraHStyles) (map fst paraStyles)) tbodies+        tf <- tableFootToOpenDocument o (map fst paraStyles) tfoot         let tableDoc = inTags True "table:table" [                             ("table:name"      , name)                           , ("table:style-name", name)-                          ] (vcat columns $$ th $$ vcat tr)+                          ] (vcat columns $$ th $$ vcat tr $$ tf)         return $           case writerTableCaptionPosition opts of             CaptionAbove -> captionDoc $$ tableDoc@@ -521,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)@@ -574,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)@@ -630,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@@ -654,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 })@@ -744,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)@@ -830,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 []@@ -849,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,8 +3,8 @@ {- |    Module      : Text.Pandoc.Writers.Org    Copyright   : © 2010-2015 Puneeth Chaganti <punchagan@gmail.com>-                   2010-2024 John MacFarlane <jgm@berkeley.edu>-                   2016-2024 Albert Krewinkel <albert+pandoc@tarleb.com>+                   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 <albert+pandoc@tarleb.com>@@ -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
@@ -915,6 +915,7 @@                  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)@@ -1416,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) $@@ -2443,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 ->@@ -2458,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 @@ -2487,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@@ -2515,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} @@ -2669,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"@@ -2688,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
@@ -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,8 +252,8 @@   let admonition = case classes of                         (cl:_)                           | cl `elem` admonitions-                          -> ".. " <> literal cl <> "::"-                        cls -> ".. container::" <> space <>+                          -> blankline <> ".. " <> literal cl <> "::"+                        cls -> blankline <> ".. container::" <> space <>                                    literal (T.unwords (filter (/= "container") cls))   -- if contents start with block quote, we need to insert   -- an empty comment to fix the indentation point (#10236)@@ -323,12 +324,12 @@                      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+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@@ -341,9 +342,11 @@   opts <- gets stOptions   let specs' = map (\(_,width) -> (AlignDefault, width)) specs       renderGrid = gridTable opts blocksToDoc specs' thead tbody tfoot-      isSimple = all (== 0) widths && length widths > 1+      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'@@ -358,7 +361,7 @@   return $ blankline $$            (if null caption || isList                then tbl-               else (".. table:: " <> caption') $$ blankline $$ nest 3 tbl) $$+               else (blankline <> ".. table:: " <> caption') $$ blankline $$ nest 3 tbl) $$            blankline blockToRST (BulletList items) = do   contents <- mapM bulletListItemToRST items@@ -672,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 =@@ -918,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/Shared.hs view
@@ -45,10 +45,16 @@                      , toLegacyTable                      , splitSentences                      , ensureValidXmlIdentifiers+                     , removeLinks                      , setupTranslations                      , isOrderedListMarker                      , toTaskListItem                      , delimited+                     , allRowsEmpty+                     , tableBodiesToRows+                     , insertCurrentSpansAtColumn+                     , takePreviousSpansAtColumn+                     , decrementTrailingRowSpans                      ) where import Safe (lastMay, maximumMay)@@ -57,8 +63,9 @@ import Data.Either (isRight) import Data.Aeson (ToJSON (..), encode) import Data.Char (chr, ord, isSpace, isLetter, isUpper)-import Data.List (groupBy, intersperse, foldl', transpose)-import Data.List.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@@ -73,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)@@ -82,6 +89,7 @@ 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 @@ -199,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@@ -315,9 +332,18 @@              (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]] -> ([Int], [Int], [Int])-extractColWidths opts rows = (currentwidths, fullwidths, minwidths)+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))@@ -325,11 +351,15 @@                                  (calcOffset c `div` (cellColSpan c) +                                   calcOffset c `rem` (cellColSpan c))    fullwidths = getWidths (max 1 . offset . cellContents)-   currentwidths = getWidths cellWidth    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 _ [] = []@@ -346,21 +376,37 @@ redoWidths opts colspecs rows = map (resetWidths newwidths) rows  where   numcols = length colspecs-  isSimple = all ((== ColWidthDefault) . snd) colspecs-  (actualwidths, fullwidths, minwidths) = extractColWidths opts rows-  totwidth = writerColumns opts - (3 * numcols) - 1-  evenwidth = totwidth `div` numcols + totwidth `rem` numcols-  keepwidths = filter (< evenwidth) fullwidths-  evenwidth' = (totwidth - sum keepwidths) `div`-                (numcols - length keepwidths)-  ensureMinWidths = zipWith max minwidths-  newwidths = ensureMinWidths $-              case isSimple of-                True | sum fullwidths <= totwidth -> fullwidths-                     | otherwise -> map (\w -> if w < evenwidth-                                                  then w-                                                  else evenwidth') fullwidths-                False -> actualwidths+  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 =@@ -375,7 +421,7 @@                   cellTopBorder = NoLine }  addDummies :: [[RenderedCell Text]] -> [[RenderedCell Text]]-addDummies = reverse . foldl' go []+addDummies = reverse . L.foldl' go []  where    go [] cs = [cs]    go (prevRow:rs) cs = addDummiesToRow prevRow cs : prevRow : rs@@ -462,7 +508,7 @@  formatHeaderLine :: Show a => LineStyle -> [[RenderedCell a]] -> Doc Text formatHeaderLine lineStyle rows =-  literal $ foldl'+  literal $ L.foldl'     (\t row -> combineBorders t (render Nothing $ formatBorder (const lineStyle) True row))     mempty rows @@ -473,7 +519,7 @@                             then char '|'                             else char '+'  where-   (lastBorderStyle, borderParts) = foldl' addBorder (NoLine, mempty) cs+   (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@@ -527,7 +573,7 @@  toCharWidth :: WriterOptions -> Double -> Int toCharWidth opts width =-  max 1 (floor (width * fromIntegral (writerColumns opts)) - 3)+  max 0 (floor (width * fromIntegral (writerColumns opts)) - 3)  gridRow :: (Monad m, HasChars a)         => WriterOptions@@ -568,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@@ -578,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@@ -589,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@@ -799,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@@ -842,3 +902,66 @@   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/Texinfo.hs view
@@ -17,7 +17,8 @@ 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.Map as M@@ -148,6 +149,19 @@ 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@@ -158,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@@ -330,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
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,36 +18,48 @@     writeTypst   ) where import Text.Pandoc.Definition-import Text.Pandoc.Class ( PandocMonad)+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(..) )+                             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 )-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, isDigit)+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)@@ -54,7 +67,9 @@ data WriterState =   WriterState {     stOptions :: WriterOptions,-    stEscapeContext :: EscapeContext }+    stEscapeContext :: EscapeContext,+    stHighlighting :: Bool+    }  type TW m = StateT WriterState m @@ -64,18 +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@@ -87,16 +112,24 @@                           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@@ -107,15 +140,15 @@   where     go (k,v) =       case T.splitOn ":" k of-        "typst":"text":x:[] -> second ((x,v):)-        "typst":x:[] -> first ((x,v):)+        ["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)+toTypstPropsListSep = hsep . intersperse "," . map (literal . formatTypstProp)  toTypstPropsListTerm :: [(Text, Text)] -> Doc Text toTypstPropsListTerm [] = ""@@ -131,10 +164,10 @@  toTypstSetText :: [(Text, Text)] -> Doc Text toTypstSetText [] = ""-toTypstSetText typstTextAttrs = "set text" <> parens (toTypstPropsListSep typstTextAttrs) <> "; "+toTypstSetText typstTextAttrs = "set text" <> parens (toTypstPropsListSep typstTextAttrs) <> ";"  toTypstPoundSetText :: [(Text, Text)] -> Doc Text-toTypstPoundSetText [] = ""+toTypstPoundSetText [] = mempty toTypstPoundSetText typstTextAttrs = "#" <> toTypstSetText typstTextAttrs  toTypstBracesSetText :: [(Text, Text)] -> Doc Text -> Doc Text@@ -147,12 +180,9 @@ blockToTypst :: PandocMonad m => Block -> TW m (Doc Text) blockToTypst block =   case block of-    Plain inlines -> do-      opts <- gets stOptions-      inlinesToTypst (addLineStartEscapes opts inlines)+    Plain inlines -> inlinesToTypst inlines     Para inlines -> do-      opts <- gets stOptions-      ($$ blankline) <$> inlinesToTypst (addLineStartEscapes opts inlines)+      ($$ blankline) <$> inlinesToTypst inlines     Header level (ident,cls,_) inlines -> do       contents <- inlinesToTypst inlines       let lab = toLabel FreestandingLabel ident@@ -172,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)@@ -182,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@@ -271,7 +313,7 @@                      ColSpan n -> [ "colspan: " <> tshow n ]) ++                   map formatTypstProp typstAttrs2             cellContents <- blocksToTypst bs-            let contents2 = brackets (toTypstPoundSetText typstTextAttrs <> cellContents)+            let contents2 = brackets (toTypstPoundSetText typstTextAttrs $$ cellContents)             pure $ if null cellattrs                       then contents2                       else "table.cell" <>@@ -324,12 +366,13 @@     Figure (ident,_,_) (Caption _mbshort capt) blocks -> do       caption <- blocksToTypst capt       opts <-  gets stOptions+      let toImage (Image attr inlines (src, _)) =+            Just $ mkImage opts False src attr (getAlt attr inlines)+          toImage _ = Nothing       contents <- case blocks of                      -- don't need #box around block-level image-                     [Para [Image attr _ (src, _)]]-                       -> pure $ mkImage opts False src attr-                     [Plain [Image attr _ (src, _)]]-                       -> pure $ mkImage opts False src attr+                     [Para [img]] | Just i <- toImage img -> pure i+                     [Plain [img]] | Just i <- toImage img -> pure i                      _ -> brackets <$> blocksToTypst blocks       let lab = toLabel FreestandingLabel ident       return $ "#figure(" <> nest 2 ((contents <> ",")@@ -342,9 +385,18 @@     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" <> toTypstPropsListParens typstAttrs <> "["-        $$ toTypstPoundSetText typstTextAttrs <> contents+        $$ toTypstPoundSetText allTypstTextAttrs+        $$ contents         $$ ("]" <+> lab)  defListItemToTypst :: PandocMonad m => ([Inline], [[Block]]) -> TW m (Doc Text)@@ -362,8 +414,30 @@   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@@ -378,7 +452,7 @@         WrapPreserve -> return cr         WrapAuto     -> return space         WrapNone     -> return space-    LineBreak -> return (space <> "\\" <> cr)+    LineBreak -> return (space <> "\\" <> space)     Math mathType str -> do       res <- convertMath TM.writeTypst mathType str       case res of@@ -390,13 +464,26 @@              case mathType of                InlineMath -> return $ "$" <> literal r <> "$"                DisplayMath -> return $ "$ " <> literal r <> " $"-    Code (_,cls,_) code -> return $-      case cls of-        (lang:_) -> "#raw(lang:" <> doubleQuoted lang <>-                        ", " <> doubleQuoted code <> ")" <> endCode-        _ | T.any (=='`') code -> "#raw(" <> doubleQuoted code <> ")"-                                     <> endCode-          | otherwise -> "`" <> literal code <> "`"+    Code (ident,cls,kvs) code -> do+      opts <- gets stOptions+      let defaultHighlightedCode =+            case cls of+              (lang:_) | writerHighlightMethod opts /= NoHighlighting+                       -> "#raw(lang:" <> doubleQuoted lang <>+                              ", " <> doubleQuoted code <> ")"+              _ | 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@@ -442,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@@ -451,17 +537,17 @@           pure $ "#link" <> parens dest <>                     (if inlines == [Str src]                           then mempty-                          else nowrap $ brackets contents) <> endCode-    Image attr _inlines (src,_tit) -> do+                          else nowrap $ brackets contents)+    Image attr inlines (src,_tit) -> do       opts <-  gets stOptions-      pure $ mkImage opts True src attr+      pure $ mkImage opts True src attr (getAlt attr inlines)     Note blocks -> do       contents <- blocksToTypst blocks-      return $ "#footnote" <> brackets (chomp contents) <> endCode+      return $ "#footnote" <> brackets (chomp contents)  -- see #9104; need box or image is treated as block-level-mkImage :: WriterOptions -> Bool -> Text -> Attr -> Doc Text-mkImage opts useBox src attr+mkImage :: WriterOptions -> Bool -> Text -> Attr -> Maybe Text -> Doc Text+mkImage opts useBox src attr mbAlt   | useBox = "#box" <> parens coreImage   | otherwise = coreImage  where@@ -475,31 +561,47 @@      (case dimension Width attr of         Nothing -> mempty         Just dim -> ", width: " <> showDim dim)+  altAttr = case mbAlt of+              Just alt -> ", alt: " <> doubleQuoted alt+              Nothing -> mempty   isData = "data:" `T.isPrefixOf` src'-  dataSvg = "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><image xlink:href=\"" <> src' <> "\" /></svg>"-  coreImage-    | isData = "image.decode" <> parens(doubleQuoted dataSvg <> dimAttrs)-    | otherwise = "image" <> parens (doubleQuoted src' <> dimAttrs)+  eitherImageData = if isData+                       then runPure (fetchItem src)+                       else Left $ PandocSomeError "not a data URI"+  toArray = parens . hcat . intersperse "," . map (literal . tshow) . B.unpack+  attrs = dimAttrs <> altAttr+  coreImage = "image" <> parens+    (case eitherImageData of+      Right (contents, Just "image/svg+xml")+        -> "bytes" <> parens (doubleQuoted (UTF8.toText contents)) <> attrs+      Right (bytes, _mime) -> "bytes" <> parens (toArray bytes) <> attrs+      Left _ -> doubleQuoted src' <> attrs) +-- | Extract alt text from image attributes and inlines.+-- Use explicit alt attribute if present; otherwise use inlines.+-- Empty alt="" means decorative image (no alt text).+getAlt :: Attr -> [Inline] -> Maybe Text+getAlt (_, _, kvs) imgInlines =+  case lookup "alt" kvs of+    Just "" -> Nothing  -- decorative+    Just alt -> Just alt+    Nothing -> case imgInlines of+                 [] -> Nothing+                 _ -> Just (stringify imgInlines)+ textstyle :: PandocMonad m => Doc Text -> [Inline] -> TW m (Doc Text) textstyle s inlines = do-  opts <-  gets stOptions-  (<> endCode) . (s <>) . brackets-    <$> inlinesToTypst (addLineStartEscapes opts inlines)+  (s <>) . brackets . fixInitialAfterBreakEscape+    <$> inlinesToTypst inlines -addLineStartEscapes :: WriterOptions -> [Inline] -> [Inline]-addLineStartEscapes opts = go True- where-   go True (Str t : xs)-        | isOrderedListMarker t = RawInline "typst" "\\" : Str t : go False xs-        | Just (c, t') <- T.uncons t-        , needsEscapeAtLineStart c-        , T.null t' = RawInline "typst" "\\" : Str t : go False xs-   go _ (SoftBreak : xs)-        | writerWrapText opts == WrapPreserve = SoftBreak : go True xs-   go _ (LineBreak : xs) = LineBreak : go True xs-   go _ (x : xs) = x : go False xs-   go _ [] = []+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 == "."@@ -508,24 +610,35 @@ 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@@ -570,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@@ -596,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@@ -605,9 +721,6 @@   escapeChar '\\' = "\\\\"   escapeChar '"' = "\\\""   escapeChar c = T.singleton c--endCode :: Doc Text-endCode = beforeNonBlank ";"  extractLabel :: Text -> Maybe Text extractLabel = go . T.unpack
+ 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/XML.hs view
@@ -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/Helpers.hs view
@@ -16,6 +16,7 @@                      , TestResult(..)                      , setupEnvironment                      , showDiff+                     , nativeDiff                      , testGolden                      , (=?>)                      , purely@@ -131,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.png")-        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
@@ -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"@@ -257,6 +263,25 @@       [ 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@@ -319,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/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@@ -243,6 +215,18 @@             "text in shape format"             "docx/text_in_shape_format.docx"             "docx/text_in_shape_format.native"+          , testCompare+            "image inside textbox content"+            "docx/textbox_image.docx"+            "docx/textbox_image.native"+          , testCompare+            "image inside textbox content with duplicate encoding"+            "docx/textbox_image_duplicate_encoding.docx"+            "docx/textbox_image_duplicate_encoding.native"+          , testCompare+            "image with textbox caption in same paragraph"+            "docx/image_with_textbox_caption.docx"+            "docx/image_with_textbox_caption.native"           ]         , testGroup "blocks"           [ testCompare@@ -346,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"@@ -497,6 +485,15 @@           [ testMediaBag             "image extraction"             "docx/image.docx"+          , testMediaBag+            "image inside textbox content populates media bag"+            "docx/textbox_image.docx"+          , testMediaBag+            "image inside textbox content with duplicate encoding populates media bag"+            "docx/textbox_image_duplicate_encoding.docx"+          , testMediaBag+            "image with textbox caption in same paragraph populates media bag"+            "docx/image_with_textbox_caption.docx"           ]         , testGroup "custom styles"           [ testCompare
test/Tests/Readers/HTML.hs view
@@ -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/Markdown.hs view
@@ -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 }@@ -379,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"           [@@ -461,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" =?>@@ -478,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" =?>@@ -492,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"@@ -590,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/ODT.hs view
@@ -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/Block.hs view
@@ -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"               ]
test/Tests/Readers/Org/Block/CodeBlock.hs view
@@ -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/Header.hs view
@@ -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/Inline.hs view
@@ -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")@@ -95,6 +99,14 @@   , "Subscript multi char" =:       "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" =?>
test/Tests/Readers/Org/Inline/Smart.hs view
@@ -47,6 +47,10 @@     ("/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/'" =?>      para ("Singles on the " <> singleQuoted (emph "meat market")))
test/Tests/Readers/Pod.hs view
@@ -145,6 +145,17 @@             "E<rchevron>" =?>             para "»"         ]+      , testGroup "html"+        [ "trade" =:+           "E<trade>" =?>+           para "™"+        , "ccaron" =:+           "E<ccaron>" =?>+           para "č"+        , "cent" =:+           "E<cent>" =?>+           para "¢"+        ]       , testGroup "numeric"         [ "decimal" =:             "E<162>" =?>@@ -170,6 +181,7 @@         , 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/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/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@@ -213,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@@ -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/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/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/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/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/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/10160.md view
@@ -7,5 +7,9 @@ \begin{table}[h] \end{table} ^D-[ Para [ Math DisplayMath "[0,1)" ] ]+[ Para+    [ Math+        DisplayMath "\\begin{equation}\n  [0,1)\n\\end{equation}"+    ]+] ```
test/command/10185.md view
@@ -36,7 +36,7 @@ \section{References}\label{references}  \protect\phantomsection\label{refs}-\begin{CSLReferences}{1}{0}+\begin{CSLReferences}{1}{1} \bibitem[\citeproctext]{ref-foo} John Doe. n.d. \emph{The Title}. 
test/command/10271.md view
@@ -16,7 +16,7 @@ % pandoc -f markdown-smart -t typst+smart "don't do it---" ^D-\"don\'t do it---\"+\"don\'t do it-\-\-\"  ``` ```
+ 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/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/10791.md view
@@ -5,10 +5,11 @@ [^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="T1">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="T1">Heart+<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="T1">+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/10816.md view
@@ -0,0 +1,7 @@+```+% pandoc -f markdown -t typst+# Test①+^D+= Test①+#label("test①")+```
+ 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/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/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/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/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/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/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/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/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/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/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/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/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/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. ```  ```
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/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/7219.md view
@@ -20,6 +20,6 @@ and also in (1958)  Reese, Trevor R. 1958. “Georgia in Anglo-Spanish Diplomacy, 1736-1739.”-William and Mary Quarterly, 3rd series, 15: 168–90.+William and Mary Quarterly, 3rd series, vol. 15: 168–90.  ```
test/command/7272.md view
@@ -14,6 +14,7 @@   </tbody> </table> ^D+{\def\LTcaptype{none} % do not increment counter \begin{longtable}[]{@{}   >{\raggedright\arraybackslash}p{(\linewidth - 0\tabcolsep) * \real{1.0000}}@{}} \toprule\noalign{}@@ -25,4 +26,5 @@ text2 }\strut \end{minipage} \\ \end{longtable}+} ```
+ 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
@@ -32,7 +32,7 @@ <<refs>>  <<ref-item1>>-Doe, John. 2005. /First Book/. Cambridge: Cambridge University Press.+Doe, John. 2005. /First Book/. Cambridge University Press. ```  @@ -45,7 +45,7 @@ <<refs>>  <<ref-item1>>-Doe, John. 2005. /First Book/. Cambridge: Cambridge University Press.+Doe, John. 2005. /First Book/. Cambridge University Press. ```  ```
test/command/7473.md view
@@ -24,7 +24,14 @@     [ Plain         [ Image             ( "" , [] , [ ( "width" , "1in" ) ] )-            [ Str "example.png" ]+            [ Str "This"+            , Space+            , Str "is"+            , Space+            , Str "a"+            , Space+            , Str "caption."+            ]             ( "example.png" , "" )         ]     ]
test/command/7512.md view
@@ -4,7 +4,12 @@ [d,\delta]=0. \end{equation*} ^D-[ Para [ Math DisplayMath "[d,\\delta]=0." ] ]+[ Para+    [ Math+        DisplayMath+        "\\begin{equation*}\n[d,\\delta]=0.\n\\end{equation*}"+    ]+] ```  ```
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/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/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/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/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/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/8665.md view
@@ -23,7 +23,7 @@ ^D [cols=",",options="header",] |===-|h1 |h2-|!@#$%^&++*++()++{++}{vbar}~?{plus}-',."++<>[]\`++ |col 2+<|h1 <|h2+<|!@++#++$%^&++*++()++{++}{vbar}~?{plus}-',."++<>[]\`++ <|col 2 |=== ```
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/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/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/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/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 \/\/+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,11 +1,11 @@ ``` % pandoc command/9002.docx -t html ^D-<table>+<table style="width:40%;"> <caption><p>This is my table!</p></caption> <colgroup>-<col style="width: 50%" />-<col style="width: 50%" />+<col style="width: 20%" />+<col style="width: 20%" /> </colgroup> <thead> <tr>@@ -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/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/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/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/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.md view
@@ -3,7 +3,7 @@ ^D <p>Lorem ipsum.</p> <figure>-<img src="media/image1.png" style="width:1.10263in;height:1.10263in" />+<img src="media/image1.png" style="width:1.09702in;height:1.09702in" /> <figcaption><p>Blue square.</p></figcaption> </figure> ```
test/command/9452.md view
@@ -14,6 +14,6 @@  With supplement @something2024[p.~3]. -And just the year #cite(<something2024>, form: "year");.+And just the year (#cite(<something2024>, form: "year")).  ```
test/command/9472.md view
@@ -49,9 +49,9 @@   \KOMAoptions{parskip=half}} \makeatother \ifLuaTeX-\usepackage[bidi=basic,shorthands=off,]{babel}+\usepackage[bidi=basic,shorthands=off]{babel} \else-\usepackage[bidi=default,shorthands=off,]{babel}+\usepackage[bidi=default,shorthands=off]{babel} \fi \ifLuaTeX   \usepackage{selnolig} % disable illegal ligatures@@ -62,6 +62,10 @@ \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/9700.md view
@@ -8,7 +8,7 @@ ^D This is a normal sentence with a manual text footnote* -\* The footnote explains why it couldn’t just be inside parentheses+<nowiki></nowiki>* The footnote explains why it couldn’t just be inside parentheses -\#foobar #foobar+<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/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/9904.md view
@@ -153,7 +153,7 @@ , Div     ( "refs"     , [ "references" , "csl-bib-body" , "hanging-indent" ]-    , [ ( "entry-spacing" , "0" ) ]+    , []     )     [ Div         ( "ref-item1" , [ "csl-entry" ] , [] )@@ -166,8 +166,6 @@             , Space             , Emph [ Str "First" , Space , Str "Book" ]             , Str "."-            , Space-            , Str "Cambridge:"             , Space             , Str "Cambridge"             , Space
+ 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/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/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/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/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
@@ -33,6 +33,7 @@     2. list ^D \begin{description}+\tightlist \item[Definition] Foo 
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/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
@@ -61,17 +61,17 @@  Uch, Ann. 2000. -‘Udhrī, Jamīl al-. 2000. “Inverted Curly Apostrophe = Opening Single-Curly Quote (for Ayn).”+‘Udhrī, Jamīl al-. 2000. Inverted Curly Apostrophe = Opening Single+Curly Quote (for Ayn). -ʿUdhrī, Jamīl al-. 2000. “Ayn.”+ʿUdhrī, Jamīl al-. 2000. Ayn. -’Udhrī, Jamīl al-. 2000a. “Curly Apostrophe = Closing Single Curly Quote-(for Hamza).”+’Udhrī, Jamīl al-. 2000a. Curly Apostrophe = Closing Single Curly Quote+(for Hamza). -ʾUdhrī, Jamīl al-. 2000. “Hamza.”+ʾUdhrī, Jamīl al-. 2000. Hamza. -’Udhrī, Jamīl al-. 2000b. “Straight Apostrophe.”+’Udhrī, Jamīl al-. 2000b. Straight Apostrophe.  Uebel, Joe. 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
@@ -11,9 +11,7 @@     (Caption Nothing [ Plain [ Str "capt" ] ])     [ Plain         [ Image-            ( "" , [] , [] )-            [ Str "img/dummy.png" ]-            ( "img/dummy.png" , "" )+            ( "" , [] , [] ) [ 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/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
@@ -26,7 +26,8 @@ <div typst:text:fill="purple">foo</div> ^D #block[-#set text(fill: purple); foo+#set text(fill: purple);+foo ] ``` @@ -63,7 +64,7 @@ </table> ^D #figure(-  align(center)[#set text(fill: orange); #table(+  align(center)[#set text(fill: orange);#table(     columns: 2,     align: (auto,auto,),     [A], [B],@@ -98,7 +99,8 @@   align(center)[#table(     columns: 2,     align: (auto,auto,),-    [A], [#set text(fill: fuchsia); B],+    [A], [#set text(fill: fuchsia);+    B],   )]   , kind: table   )@@ -114,7 +116,8 @@   align(center)[#table(     columns: 2,     align: (auto,center,),-    [A], table.cell(align: center)[#set text(fill: maroon); B],+    [A], table.cell(align: center)[#set text(fill: maroon);+    B],   )]   , kind: table   )@@ -169,7 +172,7 @@ ^D Paragraph before. -#{set text(size: 3em); table(+#{set text(size: 3em);table(   columns: 3,   align: (auto,auto,auto,),   [A], [B], [C],@@ -195,7 +198,7 @@ Paragraph before.  #figure(-  align(center)[#set text(size: 3em); #table(+  align(center)[#set text(size: 3em);#table(     columns: 3,     align: (auto,auto,auto,),     [A], [B], [C],
test/djot-reader.native view
@@ -2,1024 +2,2364 @@   Meta { unMeta = fromList [] }   [ Div       ( "Pandoc-Test-Suite" , [ "section" ] , [] )-      [ 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" ] , [] )-      [ Header 1 ( "" , [] , [] ) [ Str "Headers" ]-      , Div-          ( "level-2-with-an-embedded-link" , [ "section" ] , [] )-          [ Header-              2-              ( "" , [] , [] )-              [ Str "Level 2 with an "-              , Link-                  ( "" , [] , [] )-                  [ Str "embedded link" ]-                  ( "/url" , "" )-              ]-          , Div-              ( "level-3-with-emphasis" , [ "section" ] , [] )-              [ Header-                  3-                  ( "" , [] , [] )-                  [ Str "Level 3 with " , Emph [ Str "emphasis" ] ]-              , Div-                  ( "level-4" , [ "section" ] , [] )-                  [ Header 4 ( "" , [] , [] ) [ Str "Level 4" ]-                  , Div-                      ( "level-5" , [ "section" ] , [] )-                      [ Header 5 ( "" , [] , [] ) [ Str "Level 5" ] ]-                  ]-              ]-          ]-      ]-  , Div-      ( "level-1" , [ "section" ] , [] )-      [ Header 1 ( "" , [] , [] ) [ Str "Level 1" ]-      , Div-          ( "level-2-with-emphasis" , [ "section" ] , [] )-          [ Header-              2-              ( "" , [] , [] )-              [ Str "Level 2 with " , Emph [ Str "emphasis" ] ]-          , Div-              ( "level-3" , [ "section" ] , [] )-              [ Header 3 ( "" , [] , [] ) [ Str "Level 3" ]-              , Para [ Str "with no blank line" ]-              ]-          ]-      , Div-          ( "level-2" , [ "section" ] , [] )-          [ Header 2 ( "" , [] , [] ) [ Str "Level 2" ]-          , Para [ Str "with no blank line" ]-          , HorizontalRule-          ]-      ]-  , Div-      ( "paragraphs" , [ "section" ] , [] )-      [ 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" ] , [] )-      [ 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" ] , [] )-      [ 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" ] , [] )-      [ Header 1 ( "" , [] , [] ) [ Str "Lists" ]-      , Div-          ( "unordered" , [ "section" ] , [] )-          [ 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" ] , [] )-          [ 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" ] , [] )-          [ 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" ] , [] )-          [ 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" ] , [] )-          [ 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" ] , [] )-      [ 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" ] , [] )-      [ 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" ] , [] )-      [ 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" ] , [] )-      [ 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" ] , [] )-      [ 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" ] , [] )-      [ 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" ] , [] )-      [ Header 1 ( "" , [] , [] ) [ Str "Links" ]-      , Div-          ( "explicit" , [ "section" ] , [] )-          [ Header 2 ( "" , [] , [] ) [ Str "Explicit" ]-          , Para-              [ Str "Just a "-              , Link ( "" , [] , [] ) [ Str "URL" ] ( "/url/" , "" )-              , Str "."-              ]-          , Para-              [ Link-                  ( "" , [] , [ ( "title" , "title" ) ] )-                  [ Str "URL and title" ]-                  ( "/url/" , "" )-              , Str "."-              ]-          , Para-              [ Link-                  ( ""-                  , []-                  , [ ( "title" , "title preceded by two spaces" ) ]-                  )-                  [ Str "URL and title" ]-                  ( "/url/" , "" )-              , Str "."-              ]-          , Para-              [ Link-                  ( ""-                  , []-                  , [ ( "title" , "title preceded by a tab" ) ]-                  )-                  [ Str "URL and title" ]-                  ( "/url/" , "" )-              , Str "."-              ]-          , Para-              [ Link-                  ( ""-                  , []-                  , [ ( "title" , "title with \"quotes\" in it" ) ]-                  )-                  [ Str "URL and title" ]-                  ( "/url/" , "" )-              ]-          , Para-              [ Link-                  ( ""-                  , []-                  , [ ( "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" ] , [] )-          [ 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-                  ( ""-                  , []-                  , [ ( "title" , "Title with \"quotes\" inside" ) ]-                  )-                  [ Str "bar" ]-                  ( "/url/" , "" )-              , Str "."-              ]-          , Para-              [ Str "Foo "-              , Link-                  ( ""-                  , []-                  , [ ( "title" , "Title with \"quote\" inside" ) ]-                  )-                  [ Str "biz" ]-                  ( "/url/" , "" )-              , Str "."-              ]-          ]-      , Div-          ( "with-ampersands" , [ "section" ] , [] )-          [ 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-                  ( "" , [] , [ ( "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" ] , [] )-          [ 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" ] , [] )-      [ Header 1 ( "" , [] , [] ) [ Str "Images" ]-      , Para-          [ Str "From "-          , Quoted DoubleQuote [ Str "Voyage dans la Lune" ]-          , Str " by Georges Melies (1902):"-          ]-      , Div-          ( "" , [] , [] )-          [ Para-              [ Image-                  ( "" , [] , [ ( "title" , "Voyage dans la Lune" ) ] )-                  [ Str "lalune" ]-                  ( "lalune.jpg" , "" )-              ]-          , Div ( "" , [ "caption" ] , [] ) [ Para [ Str "lalune" ] ]-          ]-      , Para-          [ Str "Here is a movie "-          , Image-              ( "" , [] , [] ) [ Str "movie" ] ( "movie.jpg" , "" )-          , Str " icon."-          ]-      , HorizontalRule-      ]-  , Div-      ( "footnotes" , [ "section" ] , [] )-      [ 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."+      [ 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>.@@ -1408,7 +1442,7 @@   <para>     Table with attributes   </para>-  <table xml:id="mytableid1" class="mytableclass1 mytableclass2" tabstyle="mytabstyle1">+  <table xml:id="mytableid1" class="mytableclass1 mytableclass2" tabstyle="mytabstyle1" role="tablerole1">     <title>       Attribute table caption     </title>@@ -1444,7 +1478,7 @@   <para>     Table with attributes, without caption   </para>-  <informaltable xml:id="mytableid2" class="mytableclass3 mytableclass4" tabstyle="mytabstyle2">+  <informaltable xml:id="mytableid2" class="mytableclass3 mytableclass4" tabstyle="mytabstyle2" role="tablerole2">     <tgroup>       <thead> 	<th>@@ -1624,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"@@ -2570,7 +2669,9 @@   , Table       ( "mytableid1"       , [ "mytableclass1" , "mytableclass2" ]-      , [ ( "custom-style" , "mytabstyle1" ) ]+      , [ ( "role" , "tablerole1" )+        , ( "custom-style" , "mytabstyle1" )+        ]       )       (Caption          Nothing@@ -2636,7 +2737,9 @@   , Table       ( "mytableid2"       , [ "mytableclass3" , "mytableclass4" ]-      , [ ( "custom-style" , "mytabstyle2" ) ]+      , [ ( "role" , "tablerole2" )+        , ( "custom-style" , "mytabstyle2" )+        ]       )       (Caption Nothing [])       [ ( AlignDefault , ColWidthDefault )@@ -3042,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/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/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/german-reference.docx view

binary file changed (absent → 10405 bytes)

test/docx/golden/block_quotes.docx view

binary file changed (10689 → 10692 bytes)

test/docx/golden/codeblock.docx view

binary file changed (10507 → 10510 bytes)

test/docx/golden/comments.docx view

binary file changed (10838 → 10824 bytes)

test/docx/golden/custom_style_no_reference.docx view

binary file changed (10609 → 10609 bytes)

test/docx/golden/custom_style_preserve.docx view

binary file changed (11235 → 11236 bytes)

test/docx/golden/definition_list.docx view

binary file changed (10498 → 10501 bytes)

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

binary file changed (10512 → 10515 bytes)

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

binary file changed (10997 → 11000 bytes)

test/docx/golden/headers.docx view

binary file changed (10652 → 10655 bytes)

test/docx/golden/image.docx view

binary file changed (27380 → 27383 bytes)

test/docx/golden/inline_code.docx view

binary file changed (10448 → 10451 bytes)

test/docx/golden/inline_formatting.docx view

binary file changed (10624 → 10627 bytes)

test/docx/golden/inline_images.docx view

binary file changed (27380 → 27383 bytes)

binary file changed (10661 → 10664 bytes)

test/docx/golden/links.docx view

binary file changed (10839 → 10842 bytes)

test/docx/golden/lists.docx view

binary file changed (11031 → 11034 bytes)

test/docx/golden/lists_9994.docx view

binary file changed (10785 → 10788 bytes)

test/docx/golden/lists_continuing.docx view

binary file changed (10699 → 10702 bytes)

test/docx/golden/lists_div_bullets.docx view

binary file changed (10682 → 10685 bytes)

test/docx/golden/lists_multiple_initial.docx view

binary file changed (10915 → 10918 bytes)

test/docx/golden/lists_restarting.docx view

binary file changed (10696 → 10699 bytes)

test/docx/golden/nested_anchors_in_header.docx view

binary file changed (10842 → 10845 bytes)

test/docx/golden/notes.docx view

binary file changed (10612 → 10615 bytes)

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

binary file changed (10541 → 10544 bytes)

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

binary file changed (10680 → 10683 bytes)

test/docx/golden/table_one_row.docx view

binary file changed (10519 → 10496 bytes)

test/docx/golden/table_with_list_cell.docx view

binary file changed (10969 → 10946 bytes)

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

binary file changed (10879 → 10882 bytes)

test/docx/golden/tables.docx view

binary file changed (10893 → 10870 bytes)

test/docx/golden/tables_separated_with_rawblock.docx view

binary file changed (10516 → 10519 bytes)

test/docx/golden/task_list.docx view

binary file changed (10780 → 10783 bytes)

test/docx/golden/track_changes_deletion.docx view

binary file changed (10489 → 10492 bytes)

test/docx/golden/track_changes_insertion.docx view

binary file changed (10473 → 10476 bytes)

test/docx/golden/track_changes_move.docx view

binary file changed (10503 → 10506 bytes)

test/docx/golden/track_changes_scrubbed_metadata.docx view

binary file changed (10614 → 10617 bytes)

test/docx/golden/unicode.docx view

binary file changed (10465 → 10468 bytes)

test/docx/golden/verbatim_subsuper.docx view

binary file changed (10476 → 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/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/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 ("",[],[]) AlignCenter (RowSpan 1) (ColSpan 1)-    [Plain [Strong [Str "col1Header"]]]-   ,Cell ("",[],[]) AlignCenter (RowSpan 1) (ColSpan 1)-    [Plain [Strong [Str "col2Header"]]]-   ,Cell ("",[],[]) AlignCenter (RowSpan 1) (ColSpan 1)-    [Plain [Strong [Str "col3Header"]]]]])- [(TableBody ("",[],[]) (RowHeadColumns 0)-  []-  [Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "col1",Space,Str "content"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "Body",Space,Str "copy"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "col3",Space,Str "content"]]]])]- (TableFoot ("",[],[])- [])]+[ Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidth 0.16167023554603854 )+    , ( AlignDefault , ColWidth 0.16167023554603854 )+    , ( AlignDefault , ColWidth 0.40920770877944324 )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignCenter+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Strong [ Str "col1Header" ] ] ]+           , Cell+               ( "" , [] , [] )+               AlignCenter+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Strong [ Str "col2Header" ] ] ]+           , Cell+               ( "" , [] , [] )+               AlignCenter+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Strong [ Str "col3Header" ] ] ]+           ]+       ])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "col1" , Space , Str "content" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "Body" , Space , Str "copy" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "col3" , Space , Str "content" ] ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+]
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- [])- [(AlignLeft,ColWidth 0.30701754385964913)- ,(AlignDefault,ColWidth 0.1364522417153996)- ,(AlignDefault,ColWidth 0.10009746588693957)- ,(AlignDefault,ColWidth 9.707602339181287e-2)- ,(AlignDefault,ColWidth 7.719298245614035e-2)- ,(AlignDefault,ColWidth 7.085769980506823e-2)- ,(AlignDefault,ColWidth 7.09551656920078e-2)- ,(AlignDefault,ColWidth 0.14035087719298245)]- (TableHead ("",[],[])-[Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 2) (ColSpan 1)-  [Plain [Str "A"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 2) (ColSpan 1)-  [Plain [Strong [Str "B"]]]- ,Cell ("",[],[]) AlignDefault (RowSpan 2) (ColSpan 1)-  [Plain [Strong [Str "C"]]]- ,Cell ("",[],[]) AlignDefault (RowSpan 2) (ColSpan 1)-  [Plain [Strong [Str "D"]]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 3)-  [Plain [Str "E"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 2) (ColSpan 1)-  [Plain [Str "F"]]]-,Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-  [Plain [Strong [Str "G"]]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-  [Plain [Strong [Str "H"]]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-  [Plain [Strong [Str "I"]]]]])- [(TableBody ("",[],[]) (RowHeadColumns 0)-  []-  [Row ("",[],[])-   [Cell ("",[],[]) AlignLeft (RowSpan 1) (ColSpan 1)-    [Plain [Str "1"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "2"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "3"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "4"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "5"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "6"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "7"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "8"]]]-  ,Row ("",[],[])-   [Cell ("",[],[]) AlignLeft (RowSpan 1) (ColSpan 1)-    [Plain [Str "1"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "2"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "3"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "4"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "5"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "6"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "7"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "8"]]]-  ,Row ("",[],[])-   [Cell ("",[],[]) AlignLeft (RowSpan 1) (ColSpan 1)-    [Plain [Str "1"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "2"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "3"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "4"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "5"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "6"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "7"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "8"]]]-  ,Row ("",[],[])-   [Cell ("",[],[]) AlignLeft (RowSpan 1) (ColSpan 1)-    [Plain [Str "1"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "2"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "3"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "4"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "5"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "6"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "7"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "8"]]]-  ,Row ("",[],[])-   [Cell ("",[],[]) AlignLeft (RowSpan 1) (ColSpan 1)-    [Plain [Str "1"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "2"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "3"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "4"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "5"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "6"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "7"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "8"]]]-  ,Row ("",[],[])-   [Cell ("",[],[]) AlignLeft (RowSpan 1) (ColSpan 1)-    [Plain [Str "1"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "2"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "3"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "4"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "5"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "6"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "7"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "8"]]]-  ,Row ("",[],[])-   [Cell ("",[],[]) AlignLeft (RowSpan 1) (ColSpan 1)-    [Plain [Str "1"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "2"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "3"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "4"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "5"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "6"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "7"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "8"]]]-  ,Row ("",[],[])-   [Cell ("",[],[]) AlignLeft (RowSpan 1) (ColSpan 1)-    [Plain [Str "1"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "2"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "3"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "4"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "5"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "6"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "7"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "8"]]]-  ,Row ("",[],[])-   [Cell ("",[],[]) AlignLeft (RowSpan 1) (ColSpan 1)-    [Plain [Str "1"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "2"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "3"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "4"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "5"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "6"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "7"]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)-    [Plain [Str "8"]]]-  ])]- (TableFoot ("",[],[])- [])]+[ Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignLeft , ColWidth 0.30701754385964913 )+    , ( AlignDefault , ColWidth 0.13645224171539963 )+    , ( AlignDefault , ColWidth 0.10009746588693959 )+    , ( AlignDefault , ColWidth 9.707602339181289e-2 )+    , ( AlignDefault , ColWidth 7.719298245614035e-2 )+    , ( AlignDefault , ColWidth 7.085769980506823e-2 )+    , ( AlignDefault , ColWidth 7.09551656920078e-2 )+    , ( AlignDefault , ColWidth 0.14035087719298248 )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 2)+               (ColSpan 1)+               [ Plain [ Str "A" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 2)+               (ColSpan 1)+               [ Plain [ Strong [ Str "B" ] ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 2)+               (ColSpan 1)+               [ Plain [ Strong [ Str "C" ] ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 2)+               (ColSpan 1)+               [ Plain [ Strong [ Str "D" ] ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 3)+               [ Plain [ Str "E" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 2)+               (ColSpan 1)+               [ Plain [ Str "F" ] ]+           ]+       , Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Strong [ Str "G" ] ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Strong [ Str "H" ] ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Strong [ Str "I" ] ] ]+           ]+       ])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignLeft+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "3" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "4" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "5" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "6" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "7" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "8" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignLeft+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "3" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "4" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "5" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "6" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "7" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "8" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignLeft+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "3" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "4" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "5" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "6" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "7" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "8" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignLeft+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "3" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "4" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "5" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "6" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "7" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "8" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignLeft+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "3" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "4" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "5" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "6" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "7" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "8" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignLeft+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "3" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "4" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "5" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "6" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "7" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "8" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignLeft+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "3" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "4" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "5" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "6" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "7" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "8" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignLeft+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "3" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "4" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "5" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "6" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "7" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "8" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignLeft+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "3" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "4" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "5" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "6" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "7" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "8" ] ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+]
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/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/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/odt/native/imageRelative.native view
@@ -0,0 +1,10 @@+[ Para+    [ Image+        ( ""+        , []+        , [ ( "width" , "5.292cm" ) , ( "height" , "5.292cm" ) ]+        )+        []+        ( "../../lalune.jpg" , "" )+    ]+]
+ 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/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/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/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.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: @@ -90,6 +92,7 @@  Multiline table without caption: +{\def\LTcaptype{none} % do not increment counter \begin{longtable}[]{@{}   >{\centering\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1500}}   >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1375}}@@ -112,9 +115,11 @@ First & row & 12.0 & Example of a row that spans multiple lines. \\ Second & row & 5.0 & Here's another one. Note the blank line between rows. \\ \end{longtable}+}  Table without column headers: +{\def\LTcaptype{none} % do not increment counter \begin{longtable}[]{@{}rlcr@{}} \toprule\noalign{} \endhead@@ -124,9 +129,11 @@ 123 & 123 & 123 & 123 \\ 1 & 1 & 1 & 1 \\ \end{longtable}+}  Multiline table without column headers: +{\def\LTcaptype{none} % do not increment counter \begin{longtable}[]{@{}   >{\centering\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1500}}   >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1375}}@@ -139,3 +146,4 @@ First & row & 12.0 & Example of a row that spans multiple lines. \\ Second & row & 5.0 & Here's another one. Note the blank line between rows. \\ \end{longtable}+}
+ 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.markdown view
@@ -1,18 +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-  -------------------------------------------------------------------------------++-----------------------+-----------------------+---------------+---------------++| 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}+: 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/students.markdown view
@@ -20,4 +20,4 @@ | 4100332                                 | Toyota, Hiroko                          | +-----------------------------------------+-----------------------------------------+ -: List of Students {#students}+: 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@@ -52,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) @@ -61,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@@ -82,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@@ -93,6 +97,8 @@           , 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
test/typst-reader.native view
@@ -528,8 +528,7 @@                       (RowSpan 1)                       (ColSpan 1)                       [ CodeBlock-                          ( "" , [] , [] )-                          "-- document body here --\n  "+                          ( "" , [] , [] ) "-- document body here --"                       ]                   ]               ]@@ -3208,7 +3207,7 @@                           [ Para                               [ Span                                   ( "" , [ "box" ] , [] )-                                  [ Math InlineMath "\\hslash"+                                  [ Math InlineMath "\295"                                   , Str "\8192"                                   , Code                                       ( "" , [] , [] ) "planck.reduce"@@ -3610,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"                                   ]                               ]                           ]@@ -4130,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%)"                           ]                       ]                   ]@@ -4197,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)"                           ]                       ]                   ]@@ -4272,8 +4273,7 @@                           AlignDefault                           (RowSpan 1)                           (ColSpan 1)-                          [ CodeBlock-                              ( "" , [] , [] ) "(1 / n^(alpha))\n  "+                          [ CodeBlock ( "" , [] , [] ) "(1 / n^(alpha))"                           ]                       ]                   , Row@@ -4295,7 +4295,7 @@                           (ColSpan 1)                           [ CodeBlock                               ( "" , [] , [] )-                              "paren.l 1 / n^(alpha) paren.r\n  "+                              "paren.l 1 / n^(alpha) paren.r"                           ]                       ]                   ]@@ -4360,7 +4360,7 @@                           (ColSpan 1)                           [ CodeBlock                               ( "" , [] , [] )-                              "lr(frac(dif f, dif x) |)_(x_0)\n  "+                              "lr(frac(dif f, dif x) |)_(x_0)"                           ]                       ]                   ]@@ -4429,7 +4429,7 @@                           (RowSpan 1)                           (ColSpan 1)                           [ CodeBlock-                              ( "" , [] , [] ) "$ mat(a, b; c, d) $\n  "+                              ( "" , [] , [] ) "$ mat(a, b; c, d) $"                           ]                       ]                   ]@@ -4574,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) $"                           ]                       ]                   ]@@ -4782,7 +4782,7 @@                           (RowSpan 1)                           (ColSpan 1)                           [ CodeBlock-                              ( "" , [] , [] ) "$ S = k dot lg W $\n  "+                              ( "" , [] , [] ) "$ S = k dot lg W $"                           ]                       ]                   ]@@ -4835,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 $"                           ]                       ]                   ]@@ -4884,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 $"                           ]                       ]                   ]@@ -4975,8 +4975,7 @@                           AlignDefault                           (RowSpan 1)                           (ColSpan 1)-                          [ CodeBlock ( "" , [] , [] ) "f: RR -> RR\n  "-                          ]+                          [ CodeBlock ( "" , [] , [] ) "f: RR -> RR" ]                       ]                   , Row                       ( "" , [] , [] )@@ -5025,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@@ -5048,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@@ -5071,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)"                           ]                       ]                   ]@@ -5223,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@@ -5246,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))"                           ]                       ]                   ]@@ -5301,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))"                       ]                   ]               ]
test/undergradmath.typ view
@@ -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/writer.asciidoc view
@@ -529,7 +529,7 @@  Greater-than: ++>++ -Hash: #+Hash: ++#++  Period: . 
test/writer.asciidoc_legacy view
@@ -528,7 +528,7 @@  Greater-than: ++>++ -Hash: #+Hash: ++#++  Period: . 
+ 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.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.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;@@ -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;@@ -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: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>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>+      <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: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>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>+      <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: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>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>+      <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
@@ -65,6 +65,10 @@ \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},
test/writer.man view
@@ -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
test/writer.markdown view
@@ -261,125 +261,115 @@ 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: @@ -397,11 +387,9 @@  Here's a simple block: -<div>-+::: {} foo--</div>+:::  This should be a code block, though: @@ -415,19 +403,13 @@  Now, nested: -<div>--<div>--<div>-+::::: {}+:::: {}+::: {} foo--</div>--</div>--</div>+:::+::::+:::::  This should just be an HTML comment: 
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.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
@@ -42,9 +42,9 @@   <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;&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;&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;&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 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>
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
@@ -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 
test/writer.typst view
@@ -1,13 +1,9 @@ #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,@@ -39,76 +35,107 @@   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 => content-to-string(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: pagenumbering,-    columns: cols,-    )-  set par(justify: true)+    columns: cols+  )++  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) -  place(top, float: true, scope: "parent", clearance: 4mm)[-  #if title != none {-    align(center)[#block(inset: 2em)[-      #text(weight: "bold", size: 1.5em)[#title]-      #(if subtitle != none {-        parbreak()-        text(weight: "bold", size: 1.25em)[#subtitle]-      })-    ]]+  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 date != none {+        align(center)[#block(inset: 1em)[+            #date+          ]]+      } -  #if abstract != none {-    block(inset: 2em)[-    #text(weight: "semibold")[Abstract] #h(1em) #abstract-    ]+      #if abstract != none {+        block(inset: 2em)[+          #text(weight: "semibold")[#abstract-title] #h(1em) #abstract+        ]+      }+    ])   }-  ]-   doc } #show: doc => conf(@@ -122,6 +149,7 @@       email: "" ),     ),   date: [July 17, 2006],+  abstract-title: [Abstract],   pagenumbering: "1",   cols: 1,   doc,@@ -167,8 +195,7 @@  Here's one with a bullet. \* criminey. -There should be a hard line break \-here.+There should be a hard line break \ here.  #horizontalrule @@ -459,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  ```@@ -597,27 +624,27 @@  = 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.@@ -635,7 +662,7 @@ '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. @@ -654,7 +681,7 @@ - $223$ - $p$-Tree - Here's some display math:-  $ frac(d, d x) f \( x \) = lim_(h arrow.r 0) frac(f \( x + h \) - f \( x \), h) $+  $ frac(d, d x) f\(x\)= lim_(h arrow.r 0) frac(f\(x + h\)- f\(x\), h) $ - Here's one that has a line break in it: $alpha + omega times x^2$.  These shouldn't be math:@@ -727,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] @@ -743,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. @@ -765,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];.+#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>@@ -806,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 
+ 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.latex view
@@ -43,9 +43,9 @@   \KOMAoptions{parskip=half}} \makeatother \ifLuaTeX-\usepackage[bidi=basic,shorthands=off,]{babel}+\usepackage[bidi=basic,shorthands=off]{babel} \else-\usepackage[bidi=default,shorthands=off,]{babel}+\usepackage[bidi=default,shorthands=off]{babel} \fi \ifLuaTeX   \usepackage{selnolig} % disable illegal ligatures@@ -60,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)