packages feed

pandoc 3.3 → 3.4

raw patch · 85 files changed

+1972/−475 lines, 85 filesdep ~doclayoutdep ~skylightingdep ~skylighting-core

Dependency ranges changed: doclayout, skylighting, skylighting-core, texmath, typst

Files

AUTHORS.md view
@@ -113,6 +113,7 @@ - Erik Rask - Ethan Riley - Étienne Bersac+- Evan Silberman - Even Brenden - Ezwal - Fabián Heredia Montiel@@ -203,6 +204,7 @@ - John Purnell - Jonas Scholl - Jonas Smedegaard+- Jonathan - Jonathan Daugherty - Jonathan Dönszelmann - Jose Luis Duran@@ -305,6 +307,7 @@ - Owen McGrath - Pablo Rodríguez - Pascal Wagler+- Pau RE - Paul Rivier - Paul Tilley - Paulo Tanimoto@@ -340,6 +343,7 @@ - Sascha Wilde - Scott Morrison - Sebastian Talmon+- Sebbones - Sergei Trofimovich - Sergey Astanin - Seth Speaks@@ -382,6 +386,7 @@ - Toni Dietze - Tristan Stenner - Tristan de Cacqueray+- Tristano Ajmone - Tuong Nguyen Manh - Uli Köhler - Urs Liska@@ -419,6 +424,7 @@ - bumper314 - chinapedia - cholonam+- closeobserve - csforste - d-dorazio - damon-sava-stanley@@ -468,6 +474,7 @@ - tecosaur - tgkokk - the-solipsist+- thomjur - thsutton - thron7 - timo-a
CONTRIBUTING.md view
@@ -422,6 +422,29 @@   - `Text.Pandoc.UUID` contains functions for generating UUIDs.   - `Text.Pandoc.XML` contains functions for formatting XML. +Adding a new command-line option+--------------------------------++To add a new command-line option, you'll need to make changes in several+places:++- `MANUAL.txt` -- documentation for new option, both in the list+  of options and in the section on defaults files.+- `Text.Pandoc.App.Opt` -- new constructor for Opt and default+  value+- `Text.Pandoc.App.CommandLineOptions` -- the option parser+- `Text.Pandoc.App` or `Text.Pandoc.App.OutputSettings` --+  handle the new option+- possibly in pandoc-server: `Text.Pandoc.Server` -- handle the+  new option++If your change requires a new field for ReaderOptions or+WriterOptions, you'll also need to++- `Text.Pandoc.Options` -- type change and default value+- in pandoc-lua-engine: Text.Pandoc.Lua.Marshal.WriterOptions+  and/or Text.Pandoc.Lua.Marshal.ReaderOptions+ Lua filters ----------- 
INSTALL.md view
@@ -7,9 +7,15 @@   Download the latest installer </a> -For alternative ways to install pandoc, see below-under the heading for your operating system.+For alternative ways to install pandoc, see below under the heading for+your operating system.  +**Note**: the statically linked Pandoc binaries provided by us (or those+available on Conda Forge) have a limitation. They are unable to utilise Lua+filters that rely on Lua modules written in C. If you require the+functionality offered by these filters, please consider an alternative+method of installation. + ## Windows  There is a package installer at pandoc's [download page].@@ -33,12 +39,14 @@ [MiKTeX] (to typeset PDFs with [LaTeX]):      choco install rsvg-convert python miktex-    + Or, you can install pandoc using [winget](https://github.com/microsoft/winget-pkgs):      winget install --source winget --exact --id JohnMacFarlane.Pandoc +Or, you can install Pandoc using [Conda forge].+ Using multiple installation methods can result in two separate installations of pandoc; it is recommended to properly uninstall pandoc before switching to an alternative installation method.@@ -70,6 +78,8 @@ Homebrew installs from source, which takes additional time and disk space for the `ghc` compiler and dependent Haskell libraries. +Or, you can install Pandoc using [Conda forge].+ We also provide a zip file containing the binaries and man pages, for those who prefer not to use the installer.  Simply unzip the file and move the binaries and man pages to@@ -97,9 +107,7 @@  The executable is statically linked and has no dynamic dependencies or dependencies on external-data files.  Note:  because of the static-linking, the pandoc binary from this package cannot use lua-filters that require external lua modules written in C.+data files.  Both a tarball and a deb installer are provided.  To install the deb: @@ -122,6 +130,8 @@      ar p $DEB data.tar.gz | tar xvz --strip-components 2 -C $DEST +Or, you can install Pandoc using [Conda forge].+ You can also install from source, using the instructions below under [Compiling from source]. Note that most distros have the Haskell platform in their@@ -149,6 +159,21 @@ ## BSD  Pandoc is in the [NetBSD], [FreeBSD], and [OpenBSD ports] repositories.++## Conda Forge++You can install Pandoc using a [Conda+Forge](https://anaconda.org/conda-forge/pandoc) tool, like+[Conda](https://conda.pydata.org/docs/intro.html),+[[Micro]Mamba](https://mamba.readthedocs.io/en/latest/index.html) or+[Pixi](https://prefix.dev). Conda forge also includes multiple LaTeX and+other relevant packages for Pandoc (including `pandoc-citeproc`,+`pandoc-plot`, `rsvg-convert` via `librsvg` etc.). **Note:** conda forge+installs a statically-linked executable.++    conda install -c conda-forge pandoc+    pixi global install pandoc+    micromamba install pandoc  ## Docker 
MANUAL.txt view
@@ -1,7 +1,7 @@ --- title: Pandoc User's Guide author: John MacFarlane-date: July 28, 2024+date: September 9, 2024 ---  # Synopsis@@ -144,7 +144,8 @@ [`soul`], [`geometry`] (with the `geometry` variable set), [`setspace`] (with `linestretch`), and [`babel`] (with `lang`).  If `CJKmainfont` is set, [`xeCJK`]-is needed. [`framed`] is required if code is highlighted in a+is needed if `xelatex` is used, else [`luatexja`] is needed if+`lualatex` is used. [`framed`] is required if code is highlighted in a scheme that use a colored background. The use of `xelatex` or `lualatex` as the PDF engine requires [`fontspec`]. `lualatex` uses [`selnolig`] and [`lua-ul`]. `xelatex` uses [`bidi`] (with@@ -186,6 +187,7 @@ [`listings`]: https://ctan.org/pkg/listings [`lm`]: https://ctan.org/pkg/lm [`lua-ul`]: https://ctan.org/pkg/lua-ul+[`luatexja`]: https://ctan.org/pkg/luatexja [`longtable`]: https://ctan.org/pkg/longtable [`mathspec`]: https://ctan.org/pkg/mathspec [`microtype`]: https://ctan.org/pkg/microtype@@ -289,6 +291,7 @@ :   Specify output format.  *FORMAT* can be:      ::: {#output-formats}+    - `ansi` (text with [ANSI escape codes], for terminal viewing)     - `asciidoc` (modern [AsciiDoc] as interpreted by [AsciiDoctor])     - `asciidoc_legacy` ([AsciiDoc] as interpreted by [`asciidoc-py`]).     - `asciidoctor` (deprecated synonym for `asciidoc`)@@ -466,6 +469,7 @@  :   Show usage message. +[ANSI escape codes]: https://en.wikipedia.org/wiki/ANSI_escape_code [Markdown]: https://daringfireball.net/projects/markdown/ [CommonMark]: https://commonmark.org [PHP Markdown Extra]: https://michelf.ca/projects/php-markdown/extra/@@ -511,7 +515,7 @@ [GNU Texinfo]: https://www.gnu.org/software/texinfo/ [RIS]: https://en.wikipedia.org/wiki/RIS_(file_format) [Emacs Org mode]: https://orgmode.org-[AsciiDoc]: https://www.methods.co.nz/asciidoc/+[AsciiDoc]: https://asciidoc.org/ [AsciiDoctor]: https://asciidoctor.org/ [`asciidoc-py`]: https://github.com/asciidoc-py/asciidoc-py [DZSlides]: https://paulrouget.com/dzslides/@@ -1054,6 +1058,18 @@     specifying `--reference-location=section` will cause notes     to be rendered at the bottom of a slide. +`--figure-caption-position=above`|`below`++:   Specify whether figure captions go above or below figures+    (default is `below`).  This option only affects HTML,+    LaTeX, Docx, ODT, and Typst output.++`--table-caption-position=above`|`below`++:   Specify whether table captions go above or below tables+    (default is `above`).  This option only affects HTML,+    LaTeX, Docx, ODT, and Typst output.+ `--markdown-headings=setext`|`atx`  :   Specify whether to use ATX-style (`#`-prefixed) or@@ -1091,14 +1107,17 @@  `--number-offset=`*NUMBER*[`,`*NUMBER*`,`*...*] -:   Offset for section headings in HTML output (ignored in other-    output formats).  The first number is added to the section number for-    top-level headings, the second for second-level headings, and so on.-    So, for example, if you want the first top-level heading in your-    document to be numbered "6", specify `--number-offset=5`.-    If your document starts with a level-2 heading which you want to-    be numbered "1.5", specify `--number-offset=1,4`.-    Offsets are 0 by default.  Implies `--number-sections`.+:   Offsets for section heading numbers. The first number is added+    to the section number for level-1 headings, the second for+    level-2 headings, and so on. So, for example, if you+    want the first level-1 heading in your document to be+    numbered "6" instead of "1", specify `--number-offset=5`.+    If your document starts with a level-2 heading which you want+    to be numbered "1.5", specify `--number-offset=1,4`.+    `--number-offset` only directly affects the number of the+    first section heading in a document; subsequent numbers+    increment in the normal way. Implies `--number-sections`.+    Currently this feature only affects HTML and Docx output.  `--listings[=true|false]` @@ -1417,7 +1436,7 @@     - `-t latex` or none: `pdflatex` (other options: `xelatex`, `lualatex`,         `tectonic`, `latexmk`)     - `-t context`: `context`-    - `-t html`:  `wkhtmltopdf` (other options: `prince`, `weasyprint`,+    - `-t html`:  `weasyprint` (other options: `prince`, `wkhtmltopdf`,         `pagedjs-cli`;         see [print-css.rocks](https://print-css.rocks) for a good         introduction to PDF generation from HTML/CSS)@@ -1457,6 +1476,12 @@     order they appear on the command line.  For more     information, see the section on [Citations]. +    Note: if your target format is `markdown`, `org`, or `typst`,+    you will need to disable the `citations` extension (e.g., `-t+    markdown-citations`) to see the rendered citations and+    bibliography. Otherwise the format's own citation syntax will+    be used.+ `--bibliography=`*FILE*  :   Set the `bibliography` field in the document's metadata to *FILE*,@@ -1949,6 +1974,10 @@ | ```                              | ```                               | +----------------------------------+-----------------------------------+ | ```                              | ``` yaml                          |+| --link-images                    | link-images: true                 |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          | | --html-q-tags                    | html-q-tags: true                 | | ```                              | ```                               | +----------------------------------+-----------------------------------+@@ -1965,6 +1994,14 @@ | ```                              | ```                               | +----------------------------------+-----------------------------------+ | ```                              | ``` yaml                          |+| --figure-caption-position=above  | figure-caption-position: above    |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          |+| --table-caption-position=below   | table-caption-position: below     |+| ```                              | ```                               |++----------------------------------+-----------------------------------++| ```                              | ``` yaml                          | | --markdown-headings atx          | markdown-headings: atx            | | ```                              | ```                               | +----------------------------------+-----------------------------------+@@ -2974,9 +3011,10 @@ `mainfont`, `sansfont`, `monofont`, `mathfont`, `CJKmainfont`, `CJKsansfont`, `CJKmonofont` :   font families for use with `xelatex` or     `lualatex`: take the name of any system font, using the-    [`fontspec`] package.  `CJKmainfont` uses the [`xecjk`] package.+    [`fontspec`] package.  `CJKmainfont` uses the [`xecjk`] package if `xelatex` is used,+    or the [`luatexja`] package if `lualatex` is used. -`mainfontoptions`, `sansfontoptions`, `monofontoptions`, `mathfontoptions`, `CJKoptions`+`mainfontoptions`, `sansfontoptions`, `monofontoptions`, `mathfontoptions`, `CJKoptions`, `luatexjapresetoptions` :   options to use with `mainfont`, `sansfont`, `monofont`, `mathfont`,     `CJKmainfont` in `xelatex` and `lualatex`.  Allow for any     choices available through [`fontspec`]; repeat for multiple@@ -3680,11 +3718,19 @@ when you are targeting `ipynb` or a Markdown-based output format. +### Extension: `citations` (typst) {#typst-citations}++When the `citations` extension is enabled in `typst`+(as it is by default), `typst` citations will+be parsed as native pandoc citations, and native+pandoc citations will be rendered as `typst` citations.+ ### Extension: `citations` (org) {#org-citations}  When the `citations` extension is enabled in `org`, org-cite and org-ref style citations will be parsed as-native pandoc citations.+native pandoc citations, and org-cite citations will+be used to render native pandoc citations.    [org-cite]: https://orgmode.org/manual/Citations.html   [org-ref]:  https://github.com/jkitchin/org-ref@@ -5723,7 +5769,7 @@  [CSL user documentation]: https://citationstyles.org/authors/ [CSL]: https://docs.citationstyles.org/en/stable/specification.html-[CSL markup specs]: https://docs.citationstyles.org/en/1.0/release-notes.html#rich-text-markup-within-fields+[CSL markup specs]: https://citeproc-js.readthedocs.io/en/latest/csl-json/markup.html#html-like-formatting-tags [Chicago Manual of Style]: https://chicagomanualofstyle.org [Citation Style Language]: https://citationstyles.org [Zotero Style Repository]: https://www.zotero.org/styles
README.md view
@@ -111,10 +111,12 @@  <div id="output-formats"> -- `asciidoc` (modern [AsciiDoc](https://www.methods.co.nz/asciidoc/) as-  interpreted by [AsciiDoctor](https://asciidoctor.org/))-- `asciidoc_legacy` ([AsciiDoc](https://www.methods.co.nz/asciidoc/) as-  interpreted by+- `ansi` (text with [ANSI escape+  codes](https://en.wikipedia.org/wiki/ANSI_escape_code), for terminal+  viewing)+- `asciidoc` (modern [AsciiDoc](https://asciidoc.org/) as interpreted by+  [AsciiDoctor](https://asciidoctor.org/))+- `asciidoc_legacy` ([AsciiDoc](https://asciidoc.org/) as interpreted by   [`asciidoc-py`](https://github.com/asciidoc-py/asciidoc-py)). - `asciidoctor` (deprecated synonym for `asciidoc`) - `beamer` ([LaTeX beamer](https://ctan.org/pkg/beamer) slide show)
changelog.md view
@@ -1,5 +1,212 @@ # Revision history for pandoc +## 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`.++  * New module: Text.Pandoc.Writers.ANSI [API change] (Evan Silberman).++  * Docx writer:++    + Add "SuppressAuthor" and "AuthorOnly" to citationMode+      when `+citations` is used (thomjur).+    + 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
data/odt/styles.xml view
@@ -148,6 +148,9 @@       style:font-size-complex="12pt"       style:font-style-complex="italic" />     </style:style>+    <style:style style:name="TableCaption" style:family="paragraph"+    style:parent-style-name="Caption" style:class="extra">+    </style:style>     <style:style style:name="Table" style:family="paragraph"     style:parent-style-name="Caption" style:class="extra">     </style:style>
+ data/templates/default.ansi view
@@ -0,0 +1,21 @@+$if(titleblock)$+$titleblock$++$endif$+$for(header-includes)$+$header-includes$++$endfor$+$for(include-before)$+$include-before$++$endfor$+$if(toc)$+$table-of-contents$++$endif$+$body$+$for(include-after)$++$include-after$+$endfor$
data/templates/default.latex view
@@ -60,13 +60,13 @@ } \setbeamertemplate{section page}{   \centering-  \begin{beamercolorbox}[sep=12pt,center]{part title}+  \begin{beamercolorbox}[sep=12pt,center]{section title}     \usebeamerfont{section title}\insertsection\par   \end{beamercolorbox} } \setbeamertemplate{subsection page}{   \centering-  \begin{beamercolorbox}[sep=8pt,center]{part title}+  \begin{beamercolorbox}[sep=8pt,center]{subsection title}     \usebeamerfont{subsection title}\insertsubsection\par   \end{beamercolorbox} }
data/templates/default.typst view
@@ -14,12 +14,24 @@   stroke: none ) +#show figure.where(+  kind: table+): set figure.caption(position: $if(table-caption-position)$$table-caption-position$$else$top$endif$)++#show figure.where(+  kind: image+): set figure.caption(position: $if(figure-caption-position)$$figure-caption-position$$else$bottom$endif$)+ $if(template)$ #import "$template$": conf $else$ $template.typst()$ $endif$ +$for(header-includes)$+$header-includes$++$endfor$ #show: doc => conf( $if(title)$   title: [$title$],@@ -76,10 +88,6 @@   doc, ) -$for(header-includes)$-$header-includes$--$endfor$ $for(include-before)$ $include-before$ 
data/templates/styles.html view
@@ -144,7 +144,12 @@   font-variant-numeric: lining-nums tabular-nums; } table caption {+$if(table-caption-below)$+  caption-side: bottom;+  margin-top: 0.75em;+$else$   margin-bottom: 0.75em;+$endif$ } tbody {   margin-top: 0.5em;
pandoc.cabal view
@@ -1,6 +1,6 @@ cabal-version:   2.4 name:            pandoc-version:         3.3+version:         3.4 build-type:      Simple license:         GPL-2.0-or-later license-file:    COPYING.md@@ -96,6 +96,7 @@                  data/templates/default.org                  data/templates/default.epub2                  data/templates/default.epub3+                 data/templates/default.ansi                  data/templates/article.jats_publishing                  data/templates/affiliations.jats                  data/templates/default.markua@@ -334,6 +335,7 @@                  test/tables/*.mediawiki                  test/tables/*.jats_archiving                  test/testsuite.txt+                 test/ansi-test.txt                  test/writer.latex                  test/writer.context                  test/writer.djot@@ -369,6 +371,7 @@                  test/writer.zimwiki                  test/writer.xwiki                  test/writer.muse+                 test/ansi-test.ansi                  test/writers-lang-and-dir.latex                  test/writers-lang-and-dir.context                  test/dokuwiki_inline_formatting.dokuwiki@@ -489,7 +492,7 @@                  data-default          >= 0.4      && < 0.8,                  deepseq               >= 1.3      && < 1.6,                  directory             >= 1.2.3    && < 1.4,-                 doclayout             >= 0.4.0.1  && < 0.5,+                 doclayout             >= 0.5      && < 0.6,                  doctemplates          >= 0.11     && < 0.12,                  emojis                >= 0.1.4.1  && < 0.2,                  exceptions            >= 0.8      && < 0.11,@@ -514,13 +517,13 @@                  random                >= 1        && < 1.3,                  safe                  >= 0.3.18   && < 0.4,                  scientific            >= 0.3      && < 0.4,-                 skylighting           >= 0.14.2   && < 0.15,-                 skylighting-core      >= 0.14.2   && < 0.15,+                 skylighting           >= 0.14.3   && < 0.15,+                 skylighting-core      >= 0.14.3   && < 0.15,                  split                 >= 0.2      && < 0.3,                  syb                   >= 0.1      && < 0.8,                  tagsoup               >= 0.14.6   && < 0.15,                  temporary             >= 1.1      && < 1.4,-                 texmath               >= 0.12.8.9 && < 0.13,+                 texmath               >= 0.12.8.10 && < 0.13,                  text                  >= 1.1.1.0  && < 2.2,                  text-conversions      >= 0.3      && < 0.4,                  time                  >= 1.5      && < 1.15,@@ -530,7 +533,7 @@                  zip-archive           >= 0.4.3.1  && < 0.5,                  zlib                  >= 0.5      && < 0.8,                  xml                   >= 1.3.12   && < 1.4,-                 typst                 >= 0.5.0.5  && < 0.5.1,+                 typst                 >= 0.6      && < 0.6.1,                  vector                >= 0.12     && < 0.14,                  djot                  >= 0.1.2.1  && < 0.2,                  tls                   >= 2.0.1    && < 2.2,@@ -635,6 +638,7 @@                    Text.Pandoc.Writers.OOXML,                    Text.Pandoc.Writers.AnnotatedTable,                    Text.Pandoc.Writers.BibTeX,+                   Text.Pandoc.Writers.ANSI,                    Text.Pandoc.PDF,                    Text.Pandoc.UTF8,                    Text.Pandoc.Scripting,
src/Text/Pandoc/App.hs view
@@ -67,7 +67,6 @@ import Text.Pandoc.Scripting (ScriptingEngine (..), CustomComponents(..)) import Text.Pandoc.SelfContained (makeSelfContained) import Text.Pandoc.Shared (tshow)-import Text.Pandoc.URI (isURI) import Text.Pandoc.Writers.Shared (lookupMetaString) import Text.Pandoc.Readers.Markdown (yamlToMeta) import qualified Text.Pandoc.UTF8 as UTF8@@ -150,7 +149,6 @@       Nothing -> case Format.formatFromFilePaths sources of         Just f' -> return f'         Nothing | sources == ["-"] -> return $ defFlavor "markdown"-                | any (isURI . T.pack) sources -> return $ defFlavor "html"                 | otherwise -> do                     report $ CouldNotDeduceFormat                       (map (T.pack . takeExtension) sources) "markdown"
src/Text/Pandoc/App/CommandLineOptions.hs view
@@ -214,7 +214,7 @@ -- | Supported HTML PDF engines; the first item is used as default -- engine when going through HTML. htmlEngines :: [String]-htmlEngines  = ["wkhtmltopdf", "weasyprint", "pagedjs-cli", "prince"]+htmlEngines  = ["weasyprint", "wkhtmltopdf", "pagedjs-cli", "prince"]  engines :: [(Text, String)] engines = map ("html",) htmlEngines ++@@ -728,7 +728,31 @@                                "Argument of --reference-location must be block, section, or document"                      return opt { optReferenceLocation = action })                   "block|section|document")-                 "" -- "Accepting or reject MS Word track-changes.""+                 "" -- "Specify where reference links and footnotes go"++    , Option "" ["figure-caption-position"]+                 (ReqArg+                  (\arg opt -> do+                     pos <- case arg of+                            "above"  -> return CaptionAbove+                            "below"  -> return CaptionBelow+                            _        -> optError $ PandocOptionError $ T.pack+                               "Argument of --figure-caption-position must be above or below"+                     return opt { optFigureCaptionPosition = pos })+                  "above|below")+                 "" -- "Specify where figure captions go"++    , Option "" ["table-caption-position"]+                 (ReqArg+                  (\arg opt -> do+                     pos <- case arg of+                            "above"  -> return CaptionAbove+                            "below"  -> return CaptionBelow+                            _        -> optError $ PandocOptionError $ T.pack+                               "Argument of --table-caption-position must be above or below"+                     return opt { optTableCaptionPosition = pos })+                  "above|below")+                 "" -- "Specify where table captions go"      , Option "" ["markdown-headings"]                   (ReqArg
src/Text/Pandoc/App/Opt.hs view
@@ -41,6 +41,7 @@                             TrackChanges (AcceptChanges),                             WrapOption (WrapAuto), HTMLMathMethod (PlainMath),                             ReferenceLocation (EndOfDocument),+                            CaptionPosition (..),                             ObfuscationMethod (NoObfuscation),                             CiteMethod (Citeproc)) import Text.Pandoc.Class (readFileStrict, fileExists, setVerbosity, report,@@ -143,6 +144,8 @@     , optFailIfWarnings        :: Bool    -- ^ Fail on warnings     , optReferenceLinks        :: Bool    -- ^ Use reference links in writing markdown, rst     , optReferenceLocation     :: ReferenceLocation -- ^ location for footnotes and link references in markdown output+    , optFigureCaptionPosition :: CaptionPosition -- ^ position for figure caption+    , optTableCaptionPosition  :: CaptionPosition -- ^ position for table caption     , optDpi                   :: Int     -- ^ Dpi     , optWrap                  :: WrapOption  -- ^ Options for wrapping text     , optColumns               :: Int     -- ^ Line length in characters@@ -227,6 +230,8 @@        <*> o .:? "fail-if-warnings" .!= optFailIfWarnings defaultOpts        <*> o .:? "reference-links" .!= optReferenceLinks defaultOpts        <*> o .:? "reference-location" .!= optReferenceLocation defaultOpts+       <*> o .:? "figure-caption-position" .!= optFigureCaptionPosition defaultOpts+       <*> o .:? "table-caption-position" .!= optTableCaptionPosition defaultOpts        <*> o .:? "dpi" .!= optDpi defaultOpts        <*> o .:? "wrap" .!= optWrap defaultOpts        <*> o .:? "columns" .!= optColumns defaultOpts@@ -594,6 +599,10 @@       parseJSON v >>= \x -> return (\o -> o{ optReferenceLinks = x })     "reference-location" ->       parseJSON v >>= \x -> return (\o -> o{ optReferenceLocation = x })+    "figure-caption-position" ->+      parseJSON v >>= \x -> return (\o -> o{ optFigureCaptionPosition = x })+    "table-caption-position" ->+      parseJSON v >>= \x -> return (\o -> o{ optTableCaptionPosition = x })     "dpi" ->       parseJSON v >>= \x -> return (\o -> o{ optDpi = x })     "wrap" ->@@ -737,7 +746,7 @@     , optOutputFile            = Nothing     , optInputFiles            = Nothing     , optNumberSections        = False-    , optNumberOffset          = [0,0,0,0,0,0]+    , optNumberOffset          = []     , optSectionDivs           = False     , optIncremental           = False     , optSelfContained         = False@@ -766,6 +775,8 @@     , optFailIfWarnings        = False     , optReferenceLinks        = False     , optReferenceLocation     = EndOfDocument+    , optFigureCaptionPosition = CaptionBelow+    , optTableCaptionPosition  = CaptionAbove     , optDpi                   = 96     , optWrap                  = WrapAuto     , optColumns               = 72
src/Text/Pandoc/App/OutputSettings.hs view
@@ -224,8 +224,8 @@                       setVariableM "dzslides-core" dzcore vars                   else return vars) -  let writerOpts = def {-          writerTemplate         = mtemplate+  let writerOpts = WriterOptions+        { writerTemplate         = mtemplate         , writerVariables        = variables         , writerTabStop          = optTabStop opts         , writerTableOfContents  = optTableOfContents opts@@ -238,6 +238,8 @@         , writerExtensions       = writerExts         , writerReferenceLinks   = optReferenceLinks opts         , writerReferenceLocation = optReferenceLocation opts+        , writerFigureCaptionPosition = optFigureCaptionPosition opts+        , writerTableCaptionPosition = optTableCaptionPosition opts         , writerDpi              = optDpi opts         , writerWrapText         = optWrap opts         , writerColumns          = optColumns opts
src/Text/Pandoc/Chunks.hs view
@@ -99,7 +99,7 @@ addUp [] = []  addNext :: [Chunk] -> [Chunk]-addNext cs = zipWith go cs (map Just (tail cs) ++ [Nothing])+addNext cs = zipWith go cs (map Just (drop 1 cs) ++ [Nothing])  where   go c nxt = c{ chunkNext = nxt } 
src/Text/Pandoc/Format.hs view
@@ -38,6 +38,7 @@   , showExtension   , readExtension   )+import Network.URI (URI (..), parseURI) import Text.Pandoc.Parsing import qualified Data.Text as T @@ -170,7 +171,7 @@ -- | Determines format based on file extension. formatFromFilePath :: FilePath -> Maybe FlavoredFormat formatFromFilePath x =-  case takeExtension (map toLower x) of+  case takeExtension (map toLower fpath) of     ".Rmd"      -> defFlavor "markdown"     ".adoc"     -> defFlavor "asciidoc"     ".asciidoc" -> defFlavor "asciidoc"@@ -233,3 +234,8 @@   withExtension Nothing _ = Nothing   withExtension (Just (FlavoredFormat f ed)) ext = Just $     FlavoredFormat f (ed <> ExtensionsDiff (extensionsFromList [ext]) mempty)+  fpath = case parseURI x of+            Nothing -> x+            Just URI{ uriPath = "" } -> "index.html"+            Just URI{ uriPath = "/" } -> "index.html"+            Just URI{ uriPath = up } -> up
src/Text/Pandoc/Highlighting.hs view
@@ -29,6 +29,7 @@                                 , formatConTeXtInline                                 , formatConTeXtBlock                                 , styleToConTeXt+                                , formatANSI                                 -- * Styles                                 , pygments                                 , espresso
src/Text/Pandoc/Options.hs view
@@ -28,6 +28,7 @@                            , WriterOptions (..)                            , TrackChanges (..)                            , ReferenceLocation (..)+                           , CaptionPosition (..)                            , def                            , isEnabled                            , defaultMathJaxURL@@ -286,6 +287,22 @@    toJSON EndOfSection = "end-of-section"    toJSON EndOfDocument = "end-of-document" +-- | Positions for figure and table captions+data CaptionPosition = CaptionAbove -- ^ above figure or table+                     | CaptionBelow -- ^ below figure or table+                     deriving (Show, Read, Eq, Data, Typeable, Generic)++instance FromJSON CaptionPosition where+  parseJSON v =+    case v of+      String "above" -> return CaptionAbove+      String "below" -> return CaptionBelow+      _ -> fail $ "Unknown caption position " <> toStringLazy (encode v)++instance ToJSON CaptionPosition where+   toJSON CaptionAbove = "above"+   toJSON CaptionBelow = "below"+ -- | Options for writers data WriterOptions = WriterOptions   { writerTemplate          :: Maybe (Template Text) -- ^ Template to use@@ -323,6 +340,8 @@   , writerTOCDepth          :: Int            -- ^ Number of levels to include in TOC   , writerReferenceDoc      :: Maybe FilePath -- ^ Path to reference document if specified   , writerReferenceLocation :: ReferenceLocation    -- ^ Location of footnotes and references for writing markdown+  , writerFigureCaptionPosition :: CaptionPosition -- ^ Position of figure caption+  , writerTableCaptionPosition :: CaptionPosition -- ^ Position of table caption   , writerSyntaxMap         :: SyntaxMap   , writerPreferAscii       :: Bool           -- ^ Prefer ASCII representations of characters when possible   , writerLinkImages        :: Bool           -- ^ Use links rather than embedding ODT images@@ -362,6 +381,8 @@                       , writerTOCDepth         = 3                       , writerReferenceDoc     = Nothing                       , writerReferenceLocation = EndOfDocument+                      , writerFigureCaptionPosition = CaptionBelow+                      , writerTableCaptionPosition  = CaptionAbove                       , writerSyntaxMap        = defaultSyntaxMap                       , writerPreferAscii      = False                       , writerLinkImages       = False
src/Text/Pandoc/Parsing/GridTable.hs view
@@ -248,4 +248,4 @@                    then fromIntegral totLength                    else fromIntegral numColumns       fracs = map (\l -> fromIntegral l / quotient) lengths in-  tail fracs+  drop 1 fracs
src/Text/Pandoc/Readers/Docx.hs view
@@ -510,6 +510,13 @@          else smushInlines <$> mapM parPartToInlines' children     _ -> smushInlines <$> mapM parPartToInlines' children +-- Helper function to convert CitationItemType to CitationMode+convertCitationMode :: Citeproc.CitationItemType -> CitationMode+convertCitationMode itemType = case itemType of+                                 Citeproc.NormalCite -> NormalCitation+                                 Citeproc.SuppressAuthor -> SuppressAuthor+                                 Citeproc.AuthorOnly -> AuthorInText+ -- Turn a 'Citeproc.Citation' into a list of 'Text.Pandoc.Definition.Citation', -- and store the embedded bibliographic data in state. handleCitation :: PandocMonad m@@ -526,7 +533,7 @@                          <> x <> " ")                      (Citeproc.citationItemLocator item)                     <> fromMaybe mempty (Citeproc.citationItemSuffix item)-                , citationMode = NormalCitation -- TODO for now+                , citationMode = convertCitationMode (Citeproc.citationItemType item)                 , citationNoteNum = 0                 , citationHash = 0 }   let items = Citeproc.citationItems citation@@ -539,7 +546,6 @@           (docxReferences st)           refs }   return cs-  isAnchorSpan :: Inline -> Bool isAnchorSpan (Span (_, ["anchor"], []) _) = True
src/Text/Pandoc/Readers/Docx/Parse.hs view
@@ -1170,7 +1170,7 @@   | isElem ns "w" "r" element   , Just altCont <- findChildByName ns "mc" "AlternateContent" element =     do let choices = findChildrenByName ns "mc" "Choice" altCont-           choiceChildren = map head $ filter (not . null) $ map elChildren choices+           choiceChildren = concatMap (take 1 . elChildren) choices        outputs <- mapD (childElemToRun ns) choiceChildren        case outputs of          r : _ -> return r
src/Text/Pandoc/Readers/DokuWiki.hs view
@@ -483,7 +483,7 @@   rows <- tableRows   let firstRow = fromMaybe [] . Safe.headMay $ rows   let (headerRow, body) = if firstSeparator == '^'-                            then (firstRow, tail rows)+                            then (firstRow, drop 1 rows)                             else ([], rows)   -- Since Pandoc only has column level alignment, we have to make an arbitrary   -- choice of how to reconcile potentially different alignments in the row.
src/Text/Pandoc/Readers/HTML.hs view
@@ -85,7 +85,7 @@         meta <- stateMeta . parserState <$> getState         bs' <- replaceNotes (B.toList blocks)         reportLogMessages-        return $ Pandoc meta bs'+        return $ Pandoc meta $ extractMain bs'       getError (errorMessages -> ms) = case ms of                                          []    -> ""                                          (m:_) -> messageString m@@ -98,6 +98,20 @@     Right doc -> return doc     Left  err -> throwError $ PandocParseError $ T.pack $ getError err +-- Extract contents of main element if exactly one is present; otherwise+-- return all blocks.+extractMain :: [Block] -> [Block]+extractMain bs =+  case query getMain bs of+    [] -> bs+    [Div ("",[],_) bs'] -> bs'+    bs' -> bs'+ where+   getMain :: Block -> [Block]+   getMain b@(Div (_,_,kvs) _)+     | Just "main" <- lookup "role" kvs = [b]+   getMain _ = []+ -- Strip namespace prefixes on tags (not attributes) stripPrefixes :: [Tag Text] -> [Tag Text] stripPrefixes = map stripPrefix@@ -512,7 +526,7 @@                | "image/" `T.isPrefixOf` mt -> do                     return $ B.divWith ("",["iframe"],[]) $                       B.plain $ B.image url "" mempty-             _ -> return $ B.divWith ("",["iframe"],[("src", url)]) $ mempty)+             _ -> return $ B.divWith ("",["iframe"],[("src", url)]) mempty)        (\e -> do          logMessage $ CouldNotFetchResource url (renderError e)          ignore $ renderTags' [tag, TagClose "iframe"])@@ -852,23 +866,25 @@ pSpan = do   (TagOpen _ attr') <- lookAhead (pSatisfy $ tagOpen (=="span") (const True))   exts <- getOption readerExtensions-  if extensionEnabled Ext_native_spans exts-     then do-       contents <- pInTags "span" inline-       let attr = toAttr attr'-       let classes = maybe [] T.words $ lookup "class" attr'-       let styleAttr   = fromMaybe "" $ lookup "style" attr'-       let fontVariant = fromMaybe "" $-                          pickStyleAttrProps ["font-variant"] styleAttr-       let isSmallCaps = fontVariant == "small-caps" ||-                           "smallcaps" `elem` classes-       let tag = if isSmallCaps then B.smallcaps else B.spanWith attr-       return $ tag contents-     else if extensionEnabled Ext_raw_html exts-             then do-               tag <- pSatisfy $ tagOpen (=="span") (const True)-               return $ B.rawInline "html" $ renderTags' [tag]-             else pInTags "span" inline -- just contents+  let attr = toAttr attr'+  case attr of+     (_,["katex-html"],_) -> mempty <$ pInTags "span" inline+       -- skip HTML generated by KaTeX, since we get+       -- the math by parsing mathml (#9971)+     _ | extensionEnabled Ext_native_spans exts -> do+           contents <- pInTags "span" inline+           let classes = maybe [] T.words $ lookup "class" attr'+           let styleAttr   = fromMaybe "" $ lookup "style" attr'+           let fontVariant = fromMaybe "" $+                              pickStyleAttrProps ["font-variant"] styleAttr+           let isSmallCaps = fontVariant == "small-caps" ||+                               "smallcaps" `elem` classes+           let tag = if isSmallCaps then B.smallcaps else B.spanWith attr+           return $ tag contents+       | extensionEnabled Ext_raw_html exts -> do+            tag <- pSatisfy $ tagOpen (=="span") (const True)+            return $ B.rawInline "html" $ renderTags' [tag]+       | otherwise  -> pInTags "span" inline -- just contents  pRawHtmlInline :: PandocMonad m => TagParser m Inlines pRawHtmlInline = do@@ -904,15 +920,33 @@   let attr = toStringAttr attr'   unless inCase $     guard (maybe True (== mathMLNamespace) (lookup "xmlns" attr))+  let isDisplay = case lookup "display" attr of+                     Just "block" -> True+                     _ -> False   contents <- manyTill pAny (pSatisfy (matchTagClose "math"))-  case mathMLToTeXMath (renderTags $-          [open] <> contents <> [TagClose "math"]) of-       Left _   -> return $ B.spanWith ("",["math"],attr) $ B.text $-                             innerText contents-       Right "" -> return mempty-       Right x  -> return $ case lookup "display" attr of-                                 Just "block" -> B.displayMath x-                                 _            -> B.math x+  -- KaTeX and others include original TeX in annotation tag;+  -- just use this if present rather than parsing MathML:+  case extractTeXAnnotation contents of+    Just x -> return $ if isDisplay+                          then B.displayMath x+                          else B.math x+    Nothing ->+      case mathMLToTeXMath (renderTags $+              [open] <> contents <> [TagClose "math"]) of+           Left _   -> return $ B.spanWith ("",["math"],attr) $ B.text $+                                 innerText contents+           Right "" -> return mempty+           Right x  -> return $ if isDisplay+                                   then B.displayMath x+                                   else B.math x++extractTeXAnnotation :: [Tag Text] -> Maybe Text+extractTeXAnnotation [] = Nothing+extractTeXAnnotation (TagOpen "annotation" [("encoding","application/x-tex")]+                       : ts) =+  Just $ innerText $ takeWhile (~/= TagClose ("annotation" :: Text)) ts+extractTeXAnnotation (_:ts) = extractTeXAnnotation ts+  pInlinesInTags :: PandocMonad m => Text -> (Inlines -> Inlines)                -> TagParser m Inlines
src/Text/Pandoc/Readers/LaTeX.hs view
@@ -1007,7 +1007,7 @@     skipMany $ infile (sourceName pos)  environments :: PandocMonad m => M.Map Text (LP m Blocks)-environments = M.union (tableEnvironments blocks inline) $+environments = M.union (tableEnvironments block inline) $    M.fromList    [ ("document", env "document" blocks <* skipMany anyTok)    , ("abstract", mempty <$ (env "abstract" blocks >>= addMeta "abstract"))
src/Text/Pandoc/Readers/LaTeX/Math.hs view
@@ -70,7 +70,6 @@  mathEnv :: PandocMonad m => Text -> LP m Text mathEnv name = do-  skipopts   optional blankline   res <- manyTill anyTok (end_ name)   return $ stripTrailingNewlines $ untokenize res
src/Text/Pandoc/Readers/LaTeX/Table.hs view
@@ -25,17 +25,19 @@                   => LP m Blocks                   -> LP m Inlines                   -> M.Map Text (LP m Blocks)-tableEnvironments blocks inline =+tableEnvironments block inline =   M.fromList   [ ("longtable",  env "longtable" $           resetCaption *>-            simpTable blocks inline "longtable" False >>= addTableCaption)+            simpTable block inline "longtable" False >>= addTableCaption)   , ("table",  env "table" $           skipopts *> resetCaption *> blocks >>= addTableCaption)-  , ("tabular*", env "tabular*" $ simpTable blocks inline "tabular*" True)-  , ("tabularx", env "tabularx" $ simpTable blocks inline "tabularx" True)-  , ("tabular", env "tabular"  $ simpTable blocks inline "tabular" False)+  , ("tabular*", env "tabular*" $ simpTable block inline "tabular*" True)+  , ("tabularx", env "tabularx" $ simpTable block inline "tabularx" True)+  , ("tabular", env "tabular"  $ simpTable block inline "tabular" False)   ]+ where+   blocks = mconcat <$> many block  hline :: PandocMonad m => LP m () hline = try $ do@@ -137,7 +139,7 @@               -> Text   -- ^ table environment name               -> [([Tok], [Tok])] -- ^ pref/suffixes               -> LP m Row-parseTableRow blocks inline envname prefsufs = do+parseTableRow block inline envname prefsufs = do   notFollowedBy (spaces *> end_ envname)   -- contexts that can contain & that is not colsep:   let canContainAmp (Tok _ (CtrlSeq "begin") _) = True@@ -150,10 +152,13 @@         contents <- mconcat <$>             many ( snd <$> withRaw                      ((lookAhead (controlSeq "parbox") >>-                       void blocks) -- #5711+                       void block) -- #5711                       <|>                       (lookAhead (satisfyTok canContainAmp) >> void inline)                       <|>+                      (lookAhead (controlSeq "begin") >>+                       void block) -- #4746+                      <|>                       (lookAhead (symbol '$') >> void inline))                   <|>                    (do notFollowedBy@@ -164,16 +169,16 @@         option [] (count 1 amp)         return $ map (setpos prefpos) pref ++ contents ++ map (setpos suffpos) suff   rawcells <- mapM celltoks prefsufs-  cells <- mapM (parseFromToks (parseTableCell blocks)) rawcells+  cells <- mapM (parseFromToks (parseTableCell block)) rawcells   spaces   return $ Row nullAttr cells  parseTableCell :: PandocMonad m => LP m Blocks -> LP m Cell-parseTableCell blocks = do+parseTableCell block = do   spaces   updateState $ \st -> st{ sInTableCell = True }-  cell' <-   multicolumnCell blocks-         <|> multirowCell blocks+  cell' <-   multicolumnCell block+         <|> multirowCell block          <|> parseSimpleCell          <|> parseEmptyCell   updateState $ \st -> st{ sInTableCell = False }@@ -183,7 +188,7 @@     -- The parsing of empty cells is important in LaTeX, especially when dealing     -- with multirow/multicolumn. See #6603.     parseEmptyCell = spaces $> emptyCell-    parseSimpleCell = simpleCell <$> (plainify <$> blocks)+    parseSimpleCell = simpleCell <$> (plainify . mconcat <$> many block)   cellAlignment :: PandocMonad m => LP m Alignment@@ -204,7 +209,7 @@                 _          -> bs  multirowCell :: PandocMonad m => LP m Blocks -> LP m Cell-multirowCell blocks = controlSeq "multirow" >> do+multirowCell block = controlSeq "multirow" >> do   -- Full prototype for \multirow macro is:   --     \multirow[vpos]{nrows}[bigstruts]{width}[vmove]{text}   -- However, everything except `nrows` and `text` make@@ -214,16 +219,16 @@   _ <- optional $ symbol '[' *> manyTill anyTok (symbol ']')  -- bigstrut-related   _ <- symbol '{' *> manyTill anyTok (symbol '}')             -- Cell width   _ <- optional $ symbol '[' *> manyTill anyTok (symbol ']')  -- Length used for fine-tuning-  content <- symbol '{' *> (plainify <$> blocks) <* symbol '}'+  content <- symbol '{' *> (plainify . mconcat <$> many block) <* symbol '}'   return $ cell AlignDefault (RowSpan nrows) (ColSpan 1) content  multicolumnCell :: PandocMonad m => LP m Blocks -> LP m Cell-multicolumnCell blocks = controlSeq "multicolumn" >> do+multicolumnCell block = controlSeq "multicolumn" >> do   span' <- fmap (fromMaybe 1 . safeRead . untokenize) braced   alignment <- symbol '{' *> cellAlignment <* symbol '}'    let singleCell = do-        content <- plainify <$> blocks+        content <- plainify . mconcat <$> many block         return $ cell alignment (RowSpan 1) (ColSpan span') content    -- Two possible contents: either a \multirow cell, or content.@@ -231,7 +236,7 @@   -- Note that a \multirow cell can be nested in a \multicolumn,   -- but not the other way around. See #6603   let nestedCell = do-        (Cell _ _ (RowSpan rs) _ bs) <- multirowCell blocks+        (Cell _ _ (RowSpan rs) _ bs) <- multirowCell block         return $ cell                   alignment                   (RowSpan rs)@@ -320,7 +325,7 @@           -> Text           -> Bool           -> LP m Blocks-simpTable blocks inline envname hasWidthParameter = try $ do+simpTable block inline envname hasWidthParameter = try $ do   when hasWidthParameter $ () <$ tokWith inline   skipopts   colspecs <- parseAligns@@ -334,10 +339,10 @@   skipMany hline   spaces   header' <- option [] . try . fmap (:[]) $-             parseTableRow blocks inline envname prefsufs <*+             parseTableRow block inline envname prefsufs <*                lbreak <* many1 hline   spaces-  rows <- sepEndBy (parseTableRow blocks inline envname prefsufs)+  rows <- sepEndBy (parseTableRow block inline envname prefsufs)                     (lbreak <* optional (skipMany hline))   spaces   optional $ controlSeq "caption" *> setCaption inline
src/Text/Pandoc/Readers/Markdown.hs view
@@ -1248,7 +1248,7 @@   let (lengths, lines') = unzip dashes   let indices  = scanl (+) (T.length initSp) lines'   -- If no header, calculate alignment on basis of first row of text-  rawHeads <- fmap (tail . splitTextByIndices (init indices)) $+  rawHeads <- fmap (drop 1 . splitTextByIndices (init indices)) $               if headless                  then lookAhead anyLine                  else return rawContent@@ -1295,8 +1295,7 @@ rawTableLine indices = do   notFollowedBy' (blanklines' <|> tableFooter)   line <- anyLine-  return $ map trim $ tail $-           splitTextByIndices (init indices) line+  return $ map trim $ drop 1 $ splitTextByIndices (init indices) line  -- Parse a table line and return a list of lists of blocks (columns). tableLine :: PandocMonad m@@ -1372,10 +1371,10 @@                       []     -> []                       (x:xs) -> reverse (x+1:xs)   rawHeadsList <- if headless-                     then map (:[]) . tail . splitTextByIndices (init indices')+                     then map (:[]) . drop 1 . splitTextByIndices (init indices')                           <$> lookAhead anyLine                      else return $ transpose $ map-                           (tail . splitTextByIndices (init indices'))+                           (drop 1 . splitTextByIndices (init indices'))                            rawContent   let aligns   = zipWith alignType rawHeadsList lengths   let rawHeads = if headless
src/Text/Pandoc/Readers/ODT/Generic/XMLConverter.hs view
@@ -65,6 +65,8 @@ import           Data.Default import           Data.Maybe import           Data.List (foldl')+import qualified Data.List.NonEmpty as NonEmpty+import           Data.List.NonEmpty (NonEmpty(..))  import qualified Text.Pandoc.XML.Light as XML @@ -101,7 +103,7 @@          -- Arguably, a real Zipper would be better. But that is an          -- optimization that can be made at a later time, e.g. when          -- replacing Text.XML.Light.-         parentElements    :: [XML.Element]+         parentElements    :: NonEmpty XML.Element          -- | A map from internal namespace IDs to the namespace prefixes          -- used in XML elements        , namespacePrefixes :: NameSpacePrefixes nsID@@ -126,7 +128,7 @@                     -> XMLConverterState nsID extraState createStartState element extraState =   XMLConverterState-       { parentElements    = [element]+       { parentElements    = element :| []        , namespacePrefixes = M.empty        , namespaceIRIs     = getInitialIRImap        , moreState         = extraState@@ -147,13 +149,14 @@ -- currentElement      :: XMLConverterState nsID extraState                     -> XML.Element-currentElement state = head (parentElements state)+currentElement state = NonEmpty.head (parentElements state)  -- | Replace the current position by another, modifying the extra state -- in the process swapStack'          :: XMLConverterState nsID extraState-                    -> [XML.Element]-                    -> ( XMLConverterState nsID extraState , [XML.Element] )+                    -> NonEmpty XML.Element+                    -> ( XMLConverterState nsID extraState+                       , NonEmpty XML.Element ) swapStack' state stack                      = ( state { parentElements = stack }                        , parentElements state@@ -163,14 +166,16 @@ pushElement         :: XML.Element                     -> XMLConverterState nsID extraState                     -> XMLConverterState nsID extraState-pushElement e state  = state { parentElements = e:parentElements state }+pushElement e state  = state { parentElements =+                                 NonEmpty.cons e (parentElements state) }  -- | Pop the top element from the call stack, unless it is the last one. popElement          :: XMLConverterState nsID extraState                     -> Maybe (XMLConverterState nsID extraState) popElement state-  | _:es@(_:_) <- parentElements state = Just $ state { parentElements = es }-  | otherwise                          = Nothing+  | _ :| (e:es) <- parentElements state+                = Just $ state { parentElements = e :| es }+  | otherwise   = Nothing  -------------------------------------------------------------------------------- -- Main type@@ -544,7 +549,8 @@                                    )  ---swapStack             :: XMLConverter nsID extraState [XML.Element] [XML.Element]+swapStack             :: XMLConverter nsID extraState (NonEmpty XML.Element)+                                                      (NonEmpty XML.Element) swapStack             = withState swapStack'  --@@ -559,7 +565,7 @@ -- accessible to the converter. switchingTheStack      :: XMLConverter nsID moreState a b                        -> XMLConverter nsID moreState (a, XML.Element) b-switchingTheStack a    =     second ( (:[]) ^>> swapStack )+switchingTheStack a    =     second ( (:| []) ^>> swapStack )                          >>> first  a                          >>> second swapStack                          >>^ fst
src/Text/Pandoc/Readers/Org/Blocks.hs view
@@ -33,6 +33,7 @@ import Text.Pandoc.Shared (compactify, compactifyDL, safeRead)  import Control.Monad (foldM, guard, mzero, void)+import Data.Bifunctor (bimap) import Data.Char (isSpace) import Data.Default (Default) import Data.Functor (($>))@@ -243,13 +244,20 @@ rawBlockContent :: Monad m => Text -> OrgParser m Text rawBlockContent blockType = try $ do   blkLines <- manyTill rawLine blockEnder-  tabLen <- getOption readerTabStop+  tabStop <- getOption readerTabStop   trimP <- orgStateTrimLeadBlkIndent <$> getState-  let stripIndent strs = if trimP then map (T.drop (shortestIndent strs)) strs else strs-  (T.unlines-   . stripIndent-   . map (tabsToSpaces tabLen . commaEscaped)-   $ blkLines)+  -- split lines into indentation/contents tuples+  let splitLines = map (T.span (\c -> c == ' ' || c == '\t')) blkLines+  let countSpaces = T.foldr (\case {'\t' -> (tabStop +); _ -> (1 +)}) 0+  let shortestIndent = foldr (min . countSpaces . fst) maxBound+                     . filter (not . T.null . snd) -- ignore empty lines+                     $ splitLines+  let tabsToSpaces = T.replace "\t" (T.replicate tabStop " ")+  let reIndent = if trimP+                 then (T.drop shortestIndent . tabsToSpaces)+                 else id++  T.unlines (map (uncurry T.append . bimap reIndent commaEscaped) splitLines)    <$ updateState (\s -> s { orgStateTrimLeadBlkIndent = True })  where    rawLine :: Monad m => OrgParser m Text@@ -258,24 +266,11 @@    blockEnder :: Monad m => OrgParser m ()    blockEnder = try $ skipSpaces <* stringAnyCase ("#+end_" <> blockType) -   shortestIndent :: [Text] -> Int-   shortestIndent = foldr (min . T.length . T.takeWhile isSpace) maxBound-                    . filter (not . T.null)--   tabsToSpaces :: Int -> Text -> Text-   tabsToSpaces tabStop t =-     let (ind, suff) = T.span (\c -> c == ' ' || c == '\t') t-         tabNum      = T.length $ T.filter (== '\n') ind-         spaceNum    = T.length ind - tabNum-     in  T.replicate (spaceNum + tabStop * tabNum) " " <> suff--   commaEscaped t =-     let (ind, suff) = T.span (\c -> c == ' ' || c == '\t') t-     in  case T.uncons suff of-           Just (',', cs)-             | "*"  <- T.take 1 cs -> ind <> cs-             | "#+" <- T.take 2 cs -> ind <> cs-           _                       -> t+   commaEscaped suff = case T.uncons suff of+     Just (',', cs)+       | "*"  <- T.take 1 cs -> cs+       | "#+" <- T.take 2 cs -> cs+     _                       -> suff  -- | Read but ignore all remaining block headers. ignHeaders :: Monad m => OrgParser m ()
src/Text/Pandoc/Readers/RST.hs view
@@ -884,12 +884,6 @@        Left e  ->          throwError $ fromParsecError (toSources rawcsv') e        Right rawrows -> do-         let singleParaToPlain bs =-               case B.toList bs of-                 [Para ils] -> B.fromList [Plain ils]-                 _          -> bs-         let parseCell t = singleParaToPlain-                <$> parseFromString' parseBlocks (t <> "\n\n")          let parseRow = mapM parseCell          rows <- mapM parseRow rawrows          let (headerRow,bodyRows,numOfCols) =@@ -918,6 +912,17 @@                           [TableBody nullAttr 0 [] $ map toRow bodyRows]                           (TableFoot nullAttr []) +singleParaToPlain :: Blocks -> Blocks+singleParaToPlain bs =+  case B.toList bs of+    [Para ils] -> B.fromList [Plain ils]+    _          -> bs++parseCell :: PandocMonad m => Text -> RSTParser m Blocks+parseCell t = singleParaToPlain+   <$> parseFromString' parseBlocks (t <> "\n\n")++ -- TODO: --  - Only supports :format: fields with a single format for :raw: roles, --    change Text.Pandoc.Definition.Format to fix@@ -1285,23 +1290,24 @@ simpleTableRawLine :: Monad m => [Int] -> RSTParser m [Text] simpleTableRawLine indices = simpleTableSplitLine indices <$> anyLine -simpleTableRawLineWithEmptyCell :: Monad m => [Int] -> RSTParser m [Text]-simpleTableRawLineWithEmptyCell indices = try $ do+simpleTableRawLineWithInitialEmptyCell :: Monad m => [Int] -> RSTParser m [Text]+simpleTableRawLineWithInitialEmptyCell indices = try $ do   cs <- simpleTableRawLine indices   let isEmptyCell = T.all (\c -> c == ' ' || c == '\t')-  guard $ any isEmptyCell cs-  return cs+  case cs of+    c:_ | isEmptyCell c -> return cs+    _ -> mzero  -- Parse a table row and return a list of blocks (columns). simpleTableRow :: PandocMonad m => [Int] -> RSTParser m [Blocks] simpleTableRow indices = do   notFollowedBy' simpleTableFooter   firstLine <- simpleTableRawLine indices-  conLines  <- many $ simpleTableRawLineWithEmptyCell indices+  conLines  <- many $ simpleTableRawLineWithInitialEmptyCell indices   let cols = map T.unlines . transpose $ firstLine : conLines ++                                   [replicate (length indices) ""                                     | not (null conLines)]-  mapM (parseFromString' parseBlocks) cols+  mapM parseCell cols  simpleTableSplitLine :: [Int] -> Text -> [Text] simpleTableSplitLine indices line =
src/Text/Pandoc/Readers/RTF.hs view
@@ -431,9 +431,20 @@     Grouped (Tok _ (ControlSymbol '*') : toks@(firsttok:_)) ->       case firsttok of         Tok _ (ControlWord "shppict" _) -> inGroup (foldM processTok bs toks)+        Tok _ (ControlWord "shpinst" _) -> inGroup (foldM processTok bs toks)         _ -> bs <$ (do oldTextContent <- sTextContent <$> getState                        processTok mempty (Tok pos (Grouped toks))                        updateState $ \st -> st{ sTextContent = oldTextContent })+    Grouped (Tok _ (ControlWord "shp" _) : toks) ->+      inGroup (foldM processTok bs toks)+    Grouped [ Tok _ (ControlWord "sp" _)+            , Tok _ (Grouped [Tok _ (ControlWord "sn" _),+                      Tok _ (UnformattedText sn)])+            , Tok _ (Grouped (Tok _ (ControlWord "sv" _) : svtoks))+            ] ->+      case sn of+        "pib" -> inGroup (foldM processTok bs svtoks)+        _ -> pure bs     Grouped (Tok _ (ControlWord "fonttbl" _) : toks) -> inGroup $ do       updateState $ \s -> s{ sFontTable = processFontTable toks }       pure bs
src/Text/Pandoc/Readers/TikiWiki.hs view
@@ -157,8 +157,9 @@   return $ B.simpleTable (headers rows) rows   where     -- The headers are as many empty strings as the number of columns-    -- in the first row-    headers rows = replicate (length $ head rows) ((B.plain . B.str) "")+-- in the first row+    headers [] = []+    headers (r:_) = replicate (length r) ((B.plain . B.str) "")  para :: PandocMonad m => TikiWikiParser m B.Blocks para =  fmap (result . mconcat) ( many1Till inline endOfParaElement)@@ -226,10 +227,9 @@ -- fixListNesting nestall | trace ("\n\nfixListNesting: " ++ (show nestall)) False = undefined -- fixListNesting nestall@(first:second:rest) = fixListNesting (first:second:rest) =-  let secondBlock = head $ B.toList second in-    case secondBlock of-      BulletList _ -> fixListNesting $ mappend (recurseOnList first) (recurseOnList second) : rest-      OrderedList _ _ -> fixListNesting $ mappend (recurseOnList first) (recurseOnList second) : rest+    case B.toList second of+      (BulletList _ : _) -> fixListNesting $ mappend (recurseOnList first) (recurseOnList second) : rest+      (OrderedList _ _ : _) -> fixListNesting $ mappend (recurseOnList first) (recurseOnList second) : rest       _ -> recurseOnList first : fixListNesting (second:rest)  -- This function walks the Block structure for fixListNesting,@@ -239,10 +239,9 @@ -- recurseOnList item | trace ("rOL: " ++ (show $ length $ B.toList item) ++ ", " ++ (show $ B.toList item)) False = undefined recurseOnList items   | length (B.toList items) == 1 =-    let itemBlock = head $ B.toList items in-      case itemBlock of-        BulletList listItems -> B.bulletList $ fixListNesting $ map B.fromList listItems-        OrderedList _ listItems -> B.orderedList $ fixListNesting $ map B.fromList listItems+      case B.toList items of+        (BulletList listItems : _) -> B.bulletList $ fixListNesting $ map B.fromList listItems+        (OrderedList _ listItems : _) -> B.orderedList $ fixListNesting $ map B.fromList listItems         _ -> items    -- The otherwise works because we constructed the blocks, and we
src/Text/Pandoc/Readers/Typst.hs view
@@ -294,7 +294,7 @@       pure $ B.codeBlockWith attr txt)   ,("parbreak", \_ _ -> pure mempty)   ,("block", \mbident fields ->-      B.divWith (fromMaybe "" mbident, [], [])+      maybe id (\ident -> B.divWith (ident, [], [])) mbident         <$> (getField "body" fields >>= pWithContents pBlocks))   ,("place", \_ fields -> do       ignored "parameters of place"@@ -503,6 +503,9 @@       (if display then B.displayMath else B.math) . writeTeX <$> pMathMany body)   ,("pad", \_ fields ->  -- ignore paddingy       getField "body" fields >>= pWithContents pInlines)+  ,("block", \mbident fields ->+      maybe id (\ident -> B.spanWith (ident, [], [])) mbident+        <$> (getField "body" fields >>= pWithContents pInlines))   ]  getInlineBody :: PandocMonad m => M.Map Identifier Val -> P m (Seq Content)
src/Text/Pandoc/Readers/Vimwiki.hs view
@@ -249,14 +249,13 @@  nameValue :: Text -> Maybe (Text, Text) nameValue s =-  let t = splitTextBy (== '=') s in-    if length t /= 2-      then Nothing-      else let (a, b) = (head t, last t) in-             if (T.length b < 2) || ((T.head b, T.last b) /= ('"', '"'))-               then Nothing-               else Just (a, stripFirstAndLast b)-+  case splitTextBy (== '=') s of+    [a,b]+      | T.length b >= 2+      , "\"" `T.isPrefixOf` b+      , "\"" `T.isSuffixOf` b+      -> Just (a, stripFirstAndLast b)+    _ -> Nothing  displayMath :: PandocMonad m => VwParser m Blocks displayMath = try $ do@@ -291,8 +290,8 @@  mixedList :: PandocMonad m => VwParser m Blocks mixedList = try $ do-  (bl, _) <- mixedList' (-1)-  return $ head bl+  ((bl:_), _) <- mixedList' (-1)+  return bl  mixedList' :: PandocMonad m => Int -> VwParser m ([Blocks], Int) mixedList' prevInd = do@@ -407,8 +406,8 @@ -- headerless table table2 :: PandocMonad m => VwParser m ([Blocks], [[Blocks]]) table2 = try $ do-  trs <- many1 tableRow-  return (replicate (length $ head trs) mempty, trs)+  trs@(firstrow:_) <- many1 tableRow+  return (replicate (length firstrow) mempty, trs)  tableHeaderSeparator :: PandocMonad m => VwParser m () tableHeaderSeparator = try $ do@@ -507,26 +506,27 @@  strong :: PandocMonad m => VwParser m Inlines strong = try $ do-  s <- lookAhead $ char '*' *> many1 (noneOf "*") <* char '*'-  guard $ (head s `notElem` spaceChars)-             && (last s `notElem` spaceChars)   char '*'-  contents <- mconcat <$>manyTill inline' (char '*'-    >> notFollowedBy alphaNum)-  return $ B.spanWith (makeId contents, [], []) mempty-    <> B.strong contents+  notFollowedBy (oneOf spaceChars)+  contents <- mconcat <$> many1Till inline'+                           (try (char '*' *> notFollowedBy alphaNum))+  guard $ case reverse (toList contents) of+             Space:_ -> False+             _ -> True+  return $ B.spanWith (makeId contents, [], []) mempty <> B.strong contents  makeId :: Inlines -> Text makeId i = T.concat (stringify <$> toList i)  emph :: PandocMonad m => VwParser m Inlines emph = try $ do-  s <- lookAhead $ char '_' *> many1 (noneOf "_") <* char '_'-  guard $ (head s `notElem` spaceChars)-          && (last s `notElem` spaceChars)   char '_'-  contents <- mconcat <$>manyTill inline' (char '_'-    >> notFollowedBy alphaNum)+  notFollowedBy (oneOf spaceChars)+  contents <- mconcat <$> many1Till inline'+                           (try (char '_' *> notFollowedBy alphaNum))+  guard $ case reverse (toList contents) of+             Space:_ -> False+             _ -> True   return $ B.emph contents  strikeout :: PandocMonad m => VwParser m Inlines@@ -601,8 +601,8 @@ procLink' s   | T.take 6 s == "local:" = "file" <> T.drop 5 s   | T.take 6 s == "diary:" = "diary/" <> T.drop 6 s-  | or ((`T.isPrefixOf` s) <$> [ "http:", "https:", "ftp:", "file:", "mailto:",-                              "news:", "telnet:" ])+  | any (`T.isPrefixOf` s) [ "http:", "https:", "ftp:", "file:", "mailto:",+                             "news:", "telnet:" ]                              = s   | s == ""                  = ""   | T.last s == '/'          = s@@ -624,8 +624,9 @@   char ':'   s <- manyTillChar (noneOf spaceChars) (try (char ':' >> lookAhead space))   guard $ not $ "::" `T.isInfixOf` (":" <> s <> ":")-  let ss = splitTextBy (==':') s-  return $ mconcat $ makeTagSpan' (head ss):(makeTagSpan <$> tail ss)+  case splitTextBy (==':') s of+    [] -> fail "tag doesn't contain :"+    (x:xs) -> return $ mconcat $ makeTagSpan' x : (makeTagSpan <$> xs)  todoMark :: PandocMonad m => VwParser m Inlines todoMark = try $ do
src/Text/Pandoc/Shared.hs view
@@ -50,12 +50,12 @@                      linesToPara,                      figureDiv,                      makeSections,+                     makeSectionsWithOffsets,                      combineAttr,                      uniqueIdent,                      inlineListToIdentifier,                      textToIdentifier,                      isHeaderBlock,-                     stripEmptyParagraphs,                      onlySimpleTableCells,                      isTightList,                      taskListItemFromAscii,@@ -512,12 +512,20 @@ -- adjusted so that the lowest header level is n. -- (There may still be gaps in header level if the author leaves them.) makeSections :: Bool -> Maybe Int -> [Block] -> [Block]-makeSections numbering mbBaseLevel bs =-  S.evalState (go bs) []+makeSections = makeSectionsWithOffsets []++-- | Like 'makeSections', but with a parameter for number offsets+-- (a list of 'Int's, the first of which is added to the level 1+-- section number, the second to the level 2, and so on).+makeSectionsWithOffsets :: [Int] -> Bool -> Maybe Int -> [Block] -> [Block]+makeSectionsWithOffsets numoffsets numbering mbBaseLevel bs =+  S.evalState (go bs) numoffsets  where   getLevel (Header level _ _) = Min level   getLevel _ = Min 99-  minLevel = getMin $ query getLevel bs+  minLevel = if null numoffsets || all (== 0) numoffsets+                then getMin $ query getLevel bs+                else 1 -- see #5071, for backwards compatibility   go :: [Block] -> S.State [Int] [Block]   go (Header level (ident,classes,kvs) title':xs) = do     lastnum <- S.get@@ -598,14 +606,6 @@ isHeaderBlock :: Block -> Bool isHeaderBlock Header{} = True isHeaderBlock _        = False---- | Remove empty paragraphs.-stripEmptyParagraphs :: Pandoc -> Pandoc-stripEmptyParagraphs = walk go-  where go :: [Block] -> [Block]-        go = filter (not . isEmptyParagraph)-        isEmptyParagraph (Para []) = True-        isEmptyParagraph _         = False  -- | Detect if table rows contain only cells consisting of a single -- paragraph that has no @LineBreak@.
src/Text/Pandoc/URI.hs view
@@ -84,7 +84,7 @@   , "xmlrpc.beep", "xmlrpc.beeps", "xmpp", "xri", "ymsgr", "z39.50", "z39.50r"   , "z39.50s"   -- Unofficial schemes-  , "doi", "isbn", "javascript", "pmid"+  , "doi", "gemini", "isbn", "javascript", "pmid"   ]  -- | Check if the string is a valid URL with a IANA or frequently used but
src/Text/Pandoc/Writers.hs view
@@ -19,6 +19,7 @@     -- * Writers: converting /from/ Pandoc format       Writer(..)     , writers+    , writeANSI     , writeAsciiDoc     , writeAsciiDocLegacy     , writeAsciiDoctor@@ -90,6 +91,7 @@ import Text.Pandoc.Options import qualified Text.Pandoc.UTF8 as UTF8 import Text.Pandoc.Error+import Text.Pandoc.Writers.ANSI import Text.Pandoc.Writers.AsciiDoc import Text.Pandoc.Writers.BibTeX import Text.Pandoc.Writers.ChunkedHTML@@ -200,6 +202,7 @@   ,("markua"       , TextWriter writeMarkua)   ,("chunkedhtml"  , ByteStringWriter writeChunkedHTML)   ,("djot"         , TextWriter writeDjot)+  ,("ansi"         , TextWriter writeANSI)   ]  -- | Retrieve writer, extensions based on formatSpec (format+extensions).
+ src/Text/Pandoc/Writers/ANSI.hs view
@@ -0,0 +1,354 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+   Module      : Text.Pandoc.Writers.ANSI+   Copyright   : Copyright (C) 2024 Evan Silberman+   License     : GNU GPL, version 2 or above++   Maintainer  : John MacFarlane <jgm@berkeley.edu>+   Stability   : alpha+   Portability : portable++Conversion of 'Pandoc' documents to Ansi terminal output.+-}+module Text.Pandoc.Writers.ANSI ( writeANSI ) where+import Control.Monad.State.Strict ( StateT, gets, modify, evalStateT )+import Control.Monad (foldM)+import Data.List (intersperse)+import Data.Maybe (fromMaybe)+import Data.Text (Text)+import Text.DocLayout ((<+>), ($$), ($+$))+import Text.DocTemplates (Context(..))+import Text.Pandoc.Class.PandocMonad (PandocMonad, report)+import Text.Pandoc.Definition+import Text.Pandoc.Highlighting (highlight, formatANSI)+import Text.Pandoc.Logging+import Text.Pandoc.Options+import Text.Pandoc.Shared+import Text.Pandoc.Templates (renderTemplate)+import Text.Pandoc.Writers.Math(texMathToInlines)+import Text.Pandoc.Writers.Shared+import qualified Data.Text as T+import Data.Text.Lazy (toStrict)+import qualified Text.DocLayout as D++hr :: D.HasChars a => D.Doc a+hr = rule 20++rule :: D.HasChars a => Int -> D.Doc a+rule n = D.literal $ D.replicateChar n '─'++data WriterState = WriterState {+    stNotes     :: [D.Doc Text]        -- Footnotes+  , stColumns   :: Int         -- Width of the rendered text block+  , stInner     :: Bool    -- Are we at the document's top-level or in a nested construct?+  , stNextFigureNum :: Int+  , stInFigure :: Bool+  , stInTable :: Bool+  }++type TW = StateT WriterState++withFewerColumns :: PandocMonad m => Int -> TW m a -> TW m a+withFewerColumns n a = do+  cols <- gets stColumns+  inner <- gets stInner+  modify $ \s -> s{stColumns = max (cols - n) 4, stInner = True}+  result <- a+  modify $ \s -> s{stColumns = cols, stInner = inner}+  return result++-- | Convert Pandoc to ANSI+writeANSI :: PandocMonad m => WriterOptions -> Pandoc -> m Text+writeANSI opts document =+  evalStateT (pandocToANSI opts document)+            WriterState { stNotes = [],+                          stColumns = (writerColumns opts),+                          stInner = False,+                          stNextFigureNum = 1,+                          stInFigure = False,+                          stInTable = False+                        }++-- | Return ANSI-styled verison of document+pandocToANSI :: PandocMonad m+                => WriterOptions -> Pandoc -> TW m Text+pandocToANSI opts (Pandoc meta blocks) = do+  metadata <- metaToContext opts+                 (blockListToANSI opts)+                 (inlineListToANSI opts) meta+  width <- gets stColumns+  let title = titleBlock width 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 = take (length notes) $ map notemark [1..]+  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 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++titleBlock :: Int -> Context Text -> D.Doc Text+titleBlock width meta = if null most then D.empty else D.cblock width $ most $+$ hr+  where+    title = D.bold (fromMaybe D.empty $ getField "title" meta)+    subtitle = fromMaybe D.empty $ getField "subtitle" meta+    author =  D.vcat $ fromMaybe [] $ getField "author" meta+    date = D.italic (fromMaybe D.empty $ getField "date" meta)+    most = (title $$ subtitle) $+$ author $+$ date++hangMarks :: Int -> [D.Doc Text] -> [D.Doc Text] -> D.Doc Text+hangMarks width markers contents =+  D.vsep (zipWith hangMark markers contents) where+    hangMark m d = D.rblock width m <+> D.nest (width + 1) d++stackMarks :: [D.Doc Text] -> [D.Doc Text] -> D.Doc Text+stackMarks markers contents = D.vsep (zipWith stack markers contents)+  where stack m d = m $$ D.nest 4 d++-- | Convert Pandoc block element to ANSI+blockToANSI :: PandocMonad m+               => WriterOptions -- ^ Options+               -> Block         -- ^ Block element+               -> TW m (D.Doc Text)++blockToANSI opts (Div _ bs) = blockListToANSI opts bs++blockToANSI opts (Plain inlines) = inlineListToANSI opts inlines++blockToANSI opts (Para inlines) = inlineListToANSI opts inlines++blockToANSI opts (LineBlock lns) = blockToANSI opts $ linesToPara lns++blockToANSI _ b@(RawBlock _ _) = do+    report $ BlockNotRendered b+    return D.empty++blockToANSI _ HorizontalRule = return $ D.blankline $$ hr $$ D.blankline++blockToANSI opts (Header level (_, classes, kvs) inlines) = do+  contents <- inlineListToANSI opts inlines+  let secnum = fromMaybe mempty $ lookup "number" kvs+  let doNumber = writerNumberSections opts && not (T.null secnum) && "unnumbered" `notElem` classes+  let number | doNumber = D.hang (D.realLength secnum + 1) (header level (D.literal secnum) <> D.space)+             | otherwise = id+  return $ number (header level contents) $$ D.blankline where+    header 1 = (fmap T.toUpper) . D.bold+    header 2 = D.bold+    header _ = D.italic++-- The approach to code blocks and highlighting here is a best-effort with+-- existing tools. The Skylighting formatANSI function produces fully-rendered+-- results, and its line numbers are followed by a tab character, which can+-- produce less-than-ideal results depending on your terminal's tab stops. (See+-- tabs(1)). A more ambitious approach here could process SourceLines into a+-- Doc Text.+blockToANSI opts (CodeBlock attr str) = do+  table <- gets stInTable+  inner <- case (table, writerHighlightStyle opts) of+    (_, Nothing) -> 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+  return $ nest table inner+  where defaultStyle = (D.fg D.red) . D.literal+        nest False = D.nest 4+        nest True = id++blockToANSI opts (BlockQuote blocks) = do+  contents <- withFewerColumns 2 $ blockListToANSI opts blocks+  return ( D.prefixed "│ " contents $$ D.blankline)++-- TODO: Row spans don't work+blockToANSI opts (Table _ (Caption _ caption) colSpecs (TableHead _ thead) tbody (TableFoot _ tfoot)) = do+  let captionInlines = blocksToInlines caption+  captionMarkup <-+    if null captionInlines+       then return mempty+       else D.nest 2 <$> inlineListToANSI opts (blocksToInlines caption)+  wasTable <- gets stInTable+  modify $ \s -> s{stInTable = True}+  let tw = writerColumns opts+  let ncol = length colSpecs+  let inWidths = map snd colSpecs+  let spaceForColumns = tw - ncol + 1  -- reserve a 1-char gutter between tcols+  let claimWidth ColWidthDefault = 0+      claimWidth (ColWidth n) = floor (n * fromIntegral spaceForColumns)+  let usedSpace = sum (map claimWidth inWidths)+  let remaining = spaceForColumns - usedSpace+  let defWidth = remaining `div` length (filter (== ColWidthDefault) inWidths)+  let maxWidth ColWidthDefault = defWidth+      maxWidth k = claimWidth k+  let widths = map maxWidth inWidths+  let decor = [D.hsep $ map rule widths]+  head' <- mapM (goRow widths . unRow) thead+  body' <- mapM (goRow widths . unRow) (unBodies tbody)+  foot' <- mapM (goRow widths . 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+      let (ws', render) = next ws aln cspan+      innerDoc <- blockListToANSI opts inner+      return ((render innerDoc):r, ws')+    tcell AlignLeft    = D.lblock+    tcell AlignRight   = D.rblock+    tcell AlignCenter  = D.cblock+    tcell AlignDefault = D.lblock+    next ws aln cspan =+      let (this, ws') = splitAt cspan ws+          w = sum this + cspan - 1+          cell = (tcell aln) w+       in (ws', cell)++blockToANSI opts (BulletList items) = do+  contents <- withFewerColumns 2 $ mapM (blockListToANSI opts) items+  return $ D.vsep (fmap hangMark contents) where+    hangMark d = D.hang 2 (D.literal "• ") d++blockToANSI opts (OrderedList attribs items) = do+  let markers = fmap D.literal $ take (length items) $ orderedListMarkers attribs+  let hangWidth = foldr (max . D.offset) 0 markers+  contents <- withFewerColumns hangWidth $ mapM (blockListToANSI opts) items+  return $ hangMarks hangWidth markers contents <> D.cr++blockToANSI opts (DefinitionList items) = do+  labels <- mapM (inlineListToANSI opts . fst) items+  columns <- gets stColumns+  let hangWidth = foldr (max . D.offset) 0 labels+  if hangWidth > floor (toRational columns / 10 * 3)+     then do+       contents <- withFewerColumns 4 $ mapM ((mapM (blockListToANSI opts)) . snd) items+       return $ stackMarks (D.bold <$> labels) (D.vsep <$> contents) <> D.cr+     else do+       contents <- withFewerColumns hangWidth $ mapM ((mapM (blockListToANSI opts)) . snd) items+       return $ hangMarks hangWidth (D.bold <$> labels) (D.vsep <$> contents) <> D.cr++blockToANSI opts (Figure _ (Caption _ caption)  body) = do+  let captionInlines = blocksToInlines caption+  figState <- gets stInFigure+  captionMarkup <-+    if null captionInlines+       then return mempty+       else D.nest 2 <$> inlineListToANSI opts (blocksToInlines caption)+  modify $ \s -> s{stInFigure = True}+  contents <- blockListToANSI opts body+  modify $ \s -> s{stInFigure = figState}+  return $ contents $+$ captionMarkup++-- Auxiliary functions for lists:++-- | Convert list of Pandoc block elements to ANSI+blockListToANSI :: PandocMonad m+                   => WriterOptions -- ^ Options+                   -> [Block]       -- ^ List of block elements+                   -> TW m (D.Doc Text)+blockListToANSI opts blocks =+  D.vsep <$> mapM (blockToANSI opts) blocks++-- | Convert list of Pandoc inline elements to ANSI+inlineListToANSI :: PandocMonad m+                    => WriterOptions -> [Inline] -> TW m (D.Doc Text)+inlineListToANSI opts lst =+  D.hcat <$> mapM (inlineToANSI opts) lst++-- | Convert Pandoc inline element to ANSI+inlineToANSI :: PandocMonad m => WriterOptions -> Inline -> TW m (D.Doc Text)++inlineToANSI opts (Span _ lst) =+  inlineListToANSI opts lst++inlineToANSI opts (Emph lst) = do+  contents <- inlineListToANSI opts lst+  return $ D.italic contents++inlineToANSI opts (Underline lst) = do+  contents <- inlineListToANSI opts lst+  return $ D.underlined contents++inlineToANSI opts (Strong lst) = do+  contents <- inlineListToANSI opts lst+  return $ D.bold contents++inlineToANSI opts (Strikeout lst) = do+  contents <- inlineListToANSI opts lst+  return $ D.strikeout contents++inlineToANSI opts (Superscript lst) = do+  case traverse toSuperscriptInline lst of+    Just xs -> inlineListToANSI opts xs+    Nothing -> inlineListToANSI opts lst >>= return . D.parens++inlineToANSI opts (Subscript lst) = do+  case traverse toSuperscriptInline lst of+    Just xs -> inlineListToANSI opts xs+    Nothing -> inlineListToANSI opts lst >>= return . D.parens++inlineToANSI opts (SmallCaps lst) = inlineListToANSI opts lst++inlineToANSI opts (Quoted SingleQuote lst) = do+  contents <- inlineListToANSI opts lst+  return $ "‘" <> contents <> "’"++inlineToANSI opts (Quoted DoubleQuote lst) = do+  contents <- inlineListToANSI opts lst+  return $ "“" <> contents <> "”"++inlineToANSI opts (Cite _  lst) = inlineListToANSI opts lst++-- Making a judgment call here that for ANSI-formatted output+-- intended for reading, we want to reflow inline Code on spaces+inlineToANSI _ (Code _ str) =+  return $ D.bg D.white $ D.fg D.red $ " " <> D.hcat flow <> " "+    where flow = intersperse D.space (D.literal <$> T.words str)++inlineToANSI _ (Str str) = return $ D.literal str++inlineToANSI opts (Math t str) = texMathToInlines t str >>= inlineListToANSI opts++inlineToANSI _ il@RawInline{} = do+  report $ InlineNotRendered il+  return ""++inlineToANSI _ LineBreak = return D.cr++inlineToANSI _ SoftBreak = return D.space++inlineToANSI _ Space = return D.space++inlineToANSI opts (Link (_, _, _) txt (src, _)) = do+  label <- inlineListToANSI opts txt+  return $ D.underlined $ D.fg D.cyan $ D.link src label++inlineToANSI opts (Image _ alt _) = do+  infig <- gets stInFigure+  if not infig then do+    alt' <- inlineListToANSI opts alt+    return $ D.brackets $ "image: " <> alt'+  else return $ D.brackets "image"++-- by construction, we should never be lacking in superscript characters+-- for the footnote number, but we'll fall back to square brackets anyway+inlineToANSI opts (Note contents) = do+  curNotes <- gets stNotes+  let newnum = tshow $ length curNotes + 1+  contents' <- blockListToANSI opts contents+  modify $ \s -> s { stNotes = contents' : curNotes }+  let super = T.pack <$> (traverse toSuperscript (T.unpack newnum))+  return $ D.literal $ fromMaybe ("[" <> newnum <> "]") super
src/Text/Pandoc/Writers/AsciiDoc.hs view
@@ -34,6 +34,7 @@ import qualified Data.Set as Set import qualified Data.Text as T import Data.Text (Text)+import Network.URI (parseURI, URI(uriScheme)) import System.FilePath (dropExtension) import Text.Pandoc.Class.PandocMonad (PandocMonad, report) import Text.Pandoc.Definition@@ -104,7 +105,7 @@               (blockListToAsciiDoc opts)               (fmap chomp . inlineListToAsciiDoc opts)               meta-  main <- blockListToAsciiDoc opts $ makeSections False (Just 1) blocks+  main <- blockListToAsciiDoc opts $ makeSections False Nothing blocks   st <- get   let context  = defField "body" main                $ defField "toc"@@ -204,7 +205,10 @@ blockToAsciiDoc opts (Figure attr (Caption _ longcapt) body) = do   -- Images in figures all get rendered as individual block-level images   -- with the given caption. Non-image elements are rendered unchanged.-  capt <- inlineListToAsciiDoc opts (blocksToInlines longcapt)+  capt <- if null longcapt+             then pure mempty+             else ("." <>) . nowrap <$>+                   inlineListToAsciiDoc opts (blocksToInlines longcapt)   let renderFigElement = \case         Plain [Image imgAttr alternate (src, tit)] -> do           args <- imageArguments opts imgAttr alternate src tit@@ -213,7 +217,8 @@                 (ident, _, _) -> literal $ "[#" <> ident <> "]"           -- .Figure caption           -- image::images/logo.png[Company logo, title="blah"]-          return $ "." <> nowrap capt $$+          return $+            capt $$             figAttributes $$             "image::" <> args <> blankline         blk -> blockToAsciiDoc opts blk@@ -599,9 +604,13 @@       fixCommas x = [x]    linktext <- inlineListToAsciiDoc opts $ walk (concatMap fixCommas) txt-  let isRelative = T.all (/= ':') src+  let needsLinkPrefix = case parseURI (T.unpack src) of+                          Just u -> uriScheme u `notElem` ["http:","https:",+                                                           "ftp:", "irc:",+                                                            "mailto:"]+                          _ -> True   let needsPassthrough = "--" `T.isInfixOf` src-  let prefix = if isRelative+  let prefix = if needsLinkPrefix                   then text "link:"                   else empty   let srcSuffix = fromMaybe src (T.stripPrefix "mailto:" src)
src/Text/Pandoc/Writers/ConTeXt.hs view
@@ -696,9 +696,9 @@       dims = if null dimList                 then empty                 else brackets $ mconcat (intersperse "," dimList)-      clas = if null cls-                then empty-                else brackets $ literal $ toLabel $ head cls+      clas = case cls of+               [] -> empty+               (cl:_) -> brackets $ literal $ toLabel cl       -- Use / for path separators on Windows; see #4918       fixPathSeparators = T.map $ \c -> case c of                                           '\\' -> '/'
src/Text/Pandoc/Writers/Docx.hs view
@@ -94,7 +94,8 @@ writeDocx opts doc = do   let Pandoc meta blocks = walk fixDisplayMath doc   setupTranslations meta-  let blocks' = makeSections True Nothing blocks+  let blocks' = makeSectionsWithOffsets (writerNumberOffset opts)+                   True Nothing blocks   let doc' = Pandoc meta blocks'    username <- P.lookupEnv "USERNAME"
src/Text/Pandoc/Writers/Docx/OpenXML.hs view
@@ -455,7 +455,10 @@     (Para xs  : bs) -> imageCaption (fstCaptionPara xs : bs)     (Plain xs : bs) -> imageCaption (fstCaptionPara xs : bs)     _               -> imageCaption longcapt-  wrapBookmark ident $ contentsNode : captionNode+  wrapBookmark ident $+    case writerFigureCaptionPosition opts of+      CaptionBelow -> contentsNode : captionNode+      CaptionAbove -> captionNode ++ [contentsNode]  toFigureTable :: PandocMonad m               => WriterOptions -> [Block] -> WS m Content
src/Text/Pandoc/Writers/Docx/Table.hs view
@@ -22,7 +22,7 @@ import Control.Monad.Except ( throwError ) import Data.Array ( elems, (!), assocs, indices ) import Data.Text (Text)-import Data.Maybe (catMaybes)+import Data.Maybe (catMaybes, fromMaybe) import Text.Pandoc.Definition     ( ColSpec,       Caption(Caption),@@ -46,7 +46,7 @@       withParaPropM ) import Control.Monad.Reader (asks) import Text.Pandoc.Shared ( tshow, stringify )-import Text.Pandoc.Options (WriterOptions, isEnabled)+import Text.Pandoc.Options (WriterOptions(..), isEnabled, CaptionPosition(..)) import Text.Pandoc.Extensions (Extension(Ext_native_numbering)) import Text.Pandoc.Error (PandocError(PandocSomeError)) import Text.Printf (printf)@@ -71,7 +71,7 @@                -> WS m [Content] tableToOpenXML opts blocksToOpenXML gridTable = do   setFirstPara-  let (Grid.Table (ident,_,_) caption colspecs _rowheads thead tbodies tfoot) =+  let (Grid.Table (ident,_,tableAttr) caption colspecs _rowheads thead tbodies tfoot) =         gridTable   let (Caption _maybeShortCaption captionBlocks) = caption   tablenum <- gets stNextTableNum@@ -109,11 +109,12 @@   let tblLookVal = if hasHeader then (0x20 :: Int) else 0   let (gridCols, tblWattr) = tableLayout (elems colspecs)   listLevel <- asks envListLevel+  let tblStyle =  fromMaybe "Table" (lookup "custom-style" tableAttr)   let indent = (listLevel + 1) * 720   let hasWidths = not $ all ((== ColWidthDefault) . snd) colspecs   let tbl = mknode "w:tbl" []         ( mknode "w:tblPr" []-          ( [ mknode "w:tblStyle" [("w:val","Table")] (),+          ( [ mknode "w:tblStyle" [("w:val",tblStyle)] (),               mknode "w:tblW" tblWattr () ] ++             [ mknode "w:jc" [("w:val","left")] () | indent > 0 ] ++             [ mknode "w:tblInd" [("w:w", tshow indent),("w:type","dxa")] ()@@ -134,7 +135,10 @@           : head' ++ mconcat bodies ++ foot'         )   modify $ \s -> s { stInTable = False }-  return $ captionXml ++ [Elem tbl]+  return $+    case writerTableCaptionPosition opts of+      CaptionAbove -> captionXml ++ [Elem tbl]+      CaptionBelow -> Elem tbl : captionXml  addLabel :: Text -> Text -> Int -> [Block] -> [Block] addLabel tableid tablename tablenum bs =
src/Text/Pandoc/Writers/HTML.hs view
@@ -289,8 +289,8 @@                           lookupMetaString "description" meta   slideVariant <- gets stSlideVariant   abstractTitle <- translateTerm Abstract-  let sects = adjustNumbers opts $-              makeSections (writerNumberSections opts) Nothing $+  let sects = makeSectionsWithOffsets+                (writerNumberOffset opts) (writerNumberSections opts) Nothing $               if slideVariant == NoSlides                  then blocks                  else prepSlides slideLevel blocks@@ -446,6 +446,8 @@                   defField "slideous-url" ("slideous" :: Doc Text) .                   defField "revealjs-url" ("https://unpkg.com/reveal.js@^4/" :: Doc Text) $                   defField "s5-url" ("s5/default" :: Doc Text) .+                  defField "table-caption-below"+                     (writerTableCaptionPosition opts == CaptionBelow) .                   defField "html5" (stHtml5 st) $                   metadata   return (thebody, context)@@ -678,7 +680,8 @@   addAttr html5 mbEpubVersion x y     | T.null x = id  -- see #7546     | html5-      = if x `Set.member` (html5Attributes <> rdfaAttributes)+      = if (x `Set.member` (html5Attributes <> rdfaAttributes)+            && x /= "label") -- #10048              || T.any (== ':') x -- e.g. epub: namespace              || "data-" `T.isPrefixOf` x              || "aria-" `T.isPrefixOf` x@@ -726,30 +729,6 @@                (Just x)         -> [("style", tshow dir <> ":" <> tshow x)]                Nothing          -> [] -adjustNumbers :: WriterOptions -> [Block] -> [Block]-adjustNumbers opts doc =-  if all (==0) (writerNumberOffset opts)-     then doc-     else walk go doc-  where-   go (Div (ident,"section":classes,kvs) lst@(Header level _ _ : _)) =-     Div (ident,"section":classes,map (fixnum level) kvs) lst-   go (Header level (ident,classes,kvs) lst) =-     Header level (ident,classes,map (fixnum level) kvs) lst-   go x = x-   fixnum level ("number",num) = ("number",-                               showSecNum $ zipWith (+)-                               (writerNumberOffset opts ++ repeat 0)-                               (padTo level $-                                map (fromMaybe 0 . safeRead) $-                                T.split (=='.') num))-   fixnum _ x = x-   padTo n xs =-     case n - length xs of-       x | x > 0 -> replicate x 0 ++ xs-         | otherwise -> xs-   showSecNum = T.intercalate "." . map tshow- blockToHtmlInner :: PandocMonad m => WriterOptions -> Block -> StateT WriterState m Html blockToHtmlInner opts (Plain lst) = inlineListToHtml opts lst blockToHtmlInner opts (Para lst) = do@@ -1055,24 +1034,26 @@    figAttrs <- attrsToHtml opts attrs   contents <- blockListToHtml opts body-  figCaption <- if null captBody-                then return mempty-                else do-                  captCont <- blockListToHtml opts captBody-                  return . mconcat $+  captCont <- blockListToHtml opts captBody+  let figCaption = mconcat $                     if html5                     then let fcattr = if captionIsAlt captBody body                                       then H5.customAttribute                                            (textTag "aria-hidden")                                            (toValue @Text "true")                                       else mempty-                         in [ H5.figcaption ! fcattr $ captCont, nl ]-                    else [ (H.div ! A.class_ "figcaption") captCont, nl ]+                         in [ H5.figcaption ! fcattr $ captCont ]+                    else [ (H.div ! A.class_ "figcaption") captCont ]+  let innards = mconcat $+                if null captBody+                   then [nl, contents, nl]+                   else case writerFigureCaptionPosition opts of+                         CaptionAbove -> [nl, figCaption, nl, contents, nl]+                         CaptionBelow -> [nl, contents, nl, figCaption, nl]   return $     if html5-    then foldl (!) H5.figure figAttrs $ mconcat [nl, contents, nl, figCaption]-    else foldl (!) H.div (A.class_ "float" : figAttrs) $ mconcat-           [nl, contents, nl, figCaption]+    then foldl (!) H5.figure figAttrs innards+    else foldl (!) H.div (A.class_ "float" : figAttrs) innards  where   captionIsAlt capt [Plain [Image (_, _, kv) desc _]] =     let alt = fromMaybe (stringify desc) $ lookup "alt" kv@@ -1620,7 +1601,7 @@                                       _          -> link     (Cite cits il)-> do contents <- inlineListToHtml opts                                       (if html5-                                          then walk addRoleToLink il+                                          then walk addBibliorefRole il                                           else il)                         let citationIds = T.unwords $ map citationId cits                         let result = H.span ! A.class_ "citation" $ contents@@ -1628,10 +1609,11 @@                                     then result ! customAttribute "data-cites" (toValue citationIds)                                     else result -addRoleToLink :: Inline -> Inline-addRoleToLink (Link (id',classes,kvs) ils (src,tit)) =+addBibliorefRole :: Inline -> Inline+addBibliorefRole (Link (id',classes,kvs) ils (src,tit))+   | "#ref-" `T.isPrefixOf` src =   Link (id',classes,("role","doc-biblioref"):kvs) ils (src,tit)-addRoleToLink x = x+addBibliorefRole x = x  blockListToNote :: PandocMonad m                 => WriterOptions -> Text -> [Block]
src/Text/Pandoc/Writers/ICML.hs view
@@ -30,7 +30,7 @@ import Text.Pandoc.ImageSize import Text.Pandoc.Logging import Text.Pandoc.Options-import Text.DocLayout+import Text.DocLayout hiding (link) import Text.Pandoc.Shared import Text.Pandoc.URI (isURI) import Text.Pandoc.Templates (renderTemplate)@@ -345,9 +345,9 @@                      then "0"                      else "1"       nrRows = length rows-      nrCols = if null rows-                  then 0-                  else length $ head rows+      nrCols = case rows of+                   [] -> 0+                   (r:_) -> length r       rowsToICML [] _ = return empty       rowsToICML (col:rest) rowNr =         liftM2 ($$) (colsToICML col aligns rowNr (0::Int)) $ rowsToICML rest (rowNr+1)@@ -430,14 +430,15 @@                then firstListItemName:style                else style       stl' = makeNumbStart attribs ++ stl-  in  if length item > 1-         then do-           let insertTab (Para lst) = blockToICML opts (subListParName:style) $ Para $ Str "\t":lst-               insertTab block      = blockToICML opts style block-           f <- blockToICML opts stl' $ head item-           r <- mapM insertTab $ tail item-           return $ intersperseBrs (f : r)-         else blocksToICML opts stl' item+  in  case item of+          (i:rest@(_:_)) -> do+             let insertTab (Para lst) = blockToICML opts (subListParName:style)+                                         (Para (Str "\t":lst))+                 insertTab block      = blockToICML opts style block+             f <- blockToICML opts stl' i+             r <- mapM insertTab rest+             return $ intersperseBrs (f : r)+          _ -> blocksToICML opts stl' item  definitionListItemToICML :: PandocMonad m => WriterOptions -> Style -> ([Inline],[[Block]]) -> WS m (Doc Text) definitionListItemToICML opts style (term,defs) = do@@ -484,9 +485,9 @@ inlineToICML opts style ident (Link _ lst (url, title)) = do   content <- inlinesToICML opts (linkName:style) ident lst   state $ \st ->-            let link_id = if null $ links st-                            then 1::Int-                            else 1 + fst (head $ links st)+            let link_id = case links st of+                              [] -> 1 :: Int+                              ((n,_):_) -> 1 + n                 newst = st{ links = (link_id, url):links st }                 cont  = inTags True "HyperlinkTextSource"                          [("Self","htss-"<>tshow link_id), ("Name",title), ("Hidden","false")] content@@ -545,11 +546,12 @@       attrs' =  if firstListItemName `elem` style                    then let ats = attrs : [("NumberingContinue", "false")]                             begins = filter (Text.isPrefixOf beginsWithName) style-                        in  if null begins-                               then ats-                               else let i = fromMaybe "" $ Text.stripPrefix beginsWithName-                                                         $ head begins-                                    in  ("NumberingStartAt", i) : ats+                        in  case begins of+                                [] -> ats+                                (b:_) ->+                                   let i = fromMaybe ""+                                             (Text.stripPrefix beginsWithName b)+                                   in  ("NumberingStartAt", i) : ats                    else [attrs]   in  do       content <- inlinesToICML opts [] ident lst
src/Text/Pandoc/Writers/LaTeX.hs view
@@ -605,6 +605,7 @@   tableToLaTeX inlineListToLaTeX blockListToLaTeX                (Ann.toTable attr blkCapt specs thead tbodies tfoot) blockToLaTeX (Figure (ident, _, _) captnode body) = do+  opts <- gets stOptions   (capt, captForLof, footnotes) <- getCaption inlineListToLaTeX True captnode   lab <- labelFor ident   let caption = "\\caption" <> captForLof <> braces capt <> lab@@ -615,7 +616,10 @@     [b] -> blockToLaTeX b     bs  -> mconcat . intersperse (cr <> "\\hfill") <$>            mapM (toSubfigure (length bs)) bs-  let innards = "\\centering" $$ contents $$ caption <> cr+  let innards = "\\centering" $$+                (case writerFigureCaptionPosition opts of+                  CaptionBelow -> contents $$ caption+                  CaptionAbove -> caption $$ contents) <> cr   modify $ \st ->     st{ stInFigure = isSubfigure       , stSubfigure = stSubfigure st || isSubfigure
src/Text/Pandoc/Writers/LaTeX/Citation.hs view
@@ -18,17 +18,19 @@ import Control.Monad.State (gets) import Data.Maybe (fromMaybe) import qualified Data.Text as T+import Text.Pandoc.Options import Text.Pandoc.Class.PandocMonad (PandocMonad) import Text.Pandoc.Definition import Data.List (foldl') import Text.DocLayout (Doc, brackets, empty, (<+>), text, isEmpty, literal,                        braces) import Text.Pandoc.Walk-import Text.Pandoc.Writers.LaTeX.Types ( LW, WriterState(stLang) )+import Text.Pandoc.Writers.LaTeX.Types ( LW, WriterState(stLang, stOptions) ) import Text.Pandoc.Citeproc.Locator (parseLocator, LocatorInfo(..),                                      toLocatorMap) import Citeproc.Types (Lang(..)) import Citeproc.Locale (getLocale)+import Safe (headMay, lastMay)  citationsToNatbib :: PandocMonad m                   => ([Inline] -> LW m (Doc Text))@@ -49,16 +51,17 @@              NormalCitation -> "citep"  citationsToNatbib inlineListToLaTeX cits-  | noPrefix (tail cits) && noSuffix (init cits) && ismode NormalCitation cits+  | noInnerPrefix cits && noInnerSuffix cits && ismode NormalCitation cits   = citeCommand inlineListToLaTeX "citep" p s ks   where-     noPrefix  = all (null . citationPrefix)-     noSuffix  = all (null . citationSuffix)+     noInnerPrefix []     = True+     noInnerPrefix (_:xs) = all (null . citationPrefix) xs+     noInnerSuffix []     = True+     noInnerSuffix [_]    = True+     noInnerSuffix (x:xs) = null (citationSuffix x) && noInnerSuffix xs      ismode m  = all ((==) m  . citationMode)-     p         = citationPrefix  $-                 head cits-     s         = citationSuffix  $-                 last cits+     p         = maybe mempty citationPrefix $ headMay cits+     s         = maybe mempty citationSuffix $ lastMay cits      ks        = T.intercalate ", " $ map citationId cits  citationsToNatbib inlineListToLaTeX (c:cs)@@ -107,8 +110,13 @@               -> LW m (Doc Text) citeArgumentsList _inlineListToLaTeX (CiteGroup _ _ []) = return empty citeArgumentsList inlineListToLaTeX (CiteGroup pfxs sfxs ids) = do+      opts <- gets stOptions       mblang <- gets stLang-      let sfxs' = removePageLabel mblang $+      let sfxs' = (case writerCiteMethod opts of+                     -- In biblatex, the label p. or pp. can be omitted;+                     -- ranges are treated as page ranges by default. See #9275.+                     Biblatex -> removePageLabel mblang+                     _ -> id) $               stripLocatorBraces $ case sfxs of                 (Str t : r) -> case T.uncons t of                   Just (x, xs)@@ -189,9 +197,6 @@  citationsToBiblatex _ _ = return empty --- | In natbib and biblatex, the label p. or pp. can be--- omitted; ranges will be treated as page ranges by default.--- See #9275. removePageLabel :: Maybe Lang -> [Inline] -> [Inline] removePageLabel mblang ils =   case mbLocinfo of
src/Text/Pandoc/Writers/LaTeX/Table.hs view
@@ -33,11 +33,12 @@ import Text.Pandoc.Writers.LaTeX.Notes (notesToLaTeX) import Text.Pandoc.Writers.LaTeX.Types   ( LW, WriterState (stBeamer, stExternalNotes, stInMinipage, stMultiRow-                    , stNotes, stTable) )+                    , stNotes, stTable, stOptions) ) import Text.Pandoc.Writers.LaTeX.Util (labelFor) import Text.Printf (printf) import qualified Text.Pandoc.Builder as B import qualified Text.Pandoc.Writers.AnnotatedTable as Ann+import Text.Pandoc.Options (CaptionPosition(..), WriterOptions(..))  tableToLaTeX :: PandocMonad m              => ([Inline] -> LW m (Doc Text))@@ -45,8 +46,13 @@              -> Ann.Table              -> LW m (Doc Text) tableToLaTeX inlnsToLaTeX blksToLaTeX tbl = do+  opts <- gets stOptions   let (Ann.Table (ident, _, _) caption specs thead tbodies tfoot) = tbl   CaptionDocs capt captNotes <- captionToLaTeX inlnsToLaTeX caption ident+  let hasTopCaption = not (isEmpty capt) &&+                        writerTableCaptionPosition opts == CaptionAbove+  let hasBottomCaption = not (isEmpty capt) &&+                          writerTableCaptionPosition opts == CaptionBelow   let isSimpleTable =         all ((== ColWidthDefault) . snd) specs &&         all (all isSimpleCell)@@ -64,24 +70,31 @@   -- duplicate the header rows for this.   head' <- do     let mkHead = headToLaTeX blksToLaTeX isSimpleTable colCount-    case (not $ isEmpty capt, not $ isEmptyHead thead) of-      (False, False) -> return "\\toprule\\noalign{}"-      (False, True)  -> mkHead thead-      (True, False)  -> return (capt $$ "\\toprule\\noalign{}" $$ "\\endfirsthead")-      (True, True)   -> do+    case (hasTopCaption, isEmptyHead thead) of+      (False, True) -> return "\\toprule\\noalign{}"+      (False, False)  -> mkHead thead+      (True, True)  -> return (capt <> "\\tabularnewline"+                                $$ "\\toprule\\noalign{}"+                                $$ "\\endfirsthead")+      (True, False)   -> do         -- avoid duplicate notes in head and firsthead:         firsthead <- mkHead thead         repeated  <- mkHead (walk removeNote thead)-        return $ capt $$ firsthead $$ "\\endfirsthead" $$ repeated+        return $ capt <> "\\tabularnewline"+                 $$ firsthead+                 $$ "\\endfirsthead"+                 $$ repeated   rows' <- mapM (rowToLaTeX blksToLaTeX isSimpleTable colCount BodyCell) $                 mconcat (map bodyRows tbodies)-  foot' <- if isEmptyFoot tfoot-           then pure empty-           else do-             lastfoot <- mapM-                (rowToLaTeX blksToLaTeX isSimpleTable colCount BodyCell) $-                footRows tfoot-             pure $ "\\midrule\\noalign{}" $$ vcat lastfoot+  lastfoot <- mapM (rowToLaTeX blksToLaTeX isSimpleTable colCount BodyCell) $+                    footRows tfoot+  let foot' = (if isEmptyFoot tfoot+                  then mempty+                  else "\\midrule\\noalign{}" $$ vcat lastfoot)+              $$ "\\bottomrule\\noalign{}"+              $$ (if hasBottomCaption+                     then "\\tabularnewline" $$ capt+                     else mempty)   modify $ \s -> s{ stTable = True }   notes <- notesToLaTeX <$> gets stNotes   beamer <- gets stBeamer@@ -99,10 +112,8 @@        (if beamer              then [ vcat rows'                   , foot'-                  , "\\bottomrule\\noalign{}"                   ]              else [ foot'-                  , "\\bottomrule\\noalign{}"                   , "\\endlastfoot"                   ,  vcat rows'                   ])@@ -192,7 +203,6 @@                        else "\\caption" <> captForLot <>                             braces captionText                             <> label-                            <> "\\tabularnewline"     }  type BlocksWriter m = [Block] -> LW m (Doc Text)
src/Text/Pandoc/Writers/Markdown.hs view
@@ -610,7 +610,7 @@   let isSimple = hasSimpleCells && all (==0) widths   let isPlainBlock (Plain _) = True       isPlainBlock _         = False-  let hasBlocks = not (all isPlainBlock $ concat . concat $ headers:rows)+  let hasBlocks = not (all (all (all isPlainBlock)) $ headers:rows)   let padRow r = case numcols - length r of                        x | x > 0 -> r ++ replicate x empty                          | otherwise -> r@@ -620,45 +620,51 @@   let widths' = case numcols - length widths of                      x | x > 0 -> widths ++ replicate x 0.0                        | otherwise -> widths-  (nst,tbl) <--     case True of-          _ | isSimple &&-              isEnabled Ext_simple_tables opts -> do-                rawHeaders <- padRow <$> mapM (blockListToMarkdown opts) headers-                rawRows <- mapM (fmap padRow . mapM (blockListToMarkdown opts))-                           rows-                (nest 2,) <$> pandocTable opts False (all null headers)-                                aligns' widths' rawHeaders rawRows-            | isSimple &&-              isEnabled Ext_pipe_tables opts -> do-                rawHeaders <- padRow <$> mapM (blockListToMarkdown opts) headers-                rawRows <- mapM (fmap padRow . mapM (blockListToMarkdown opts))-                           rows-                (id,) <$> pipeTable opts (all null headers) aligns' widths'-                            rawHeaders rawRows-            | not hasBlocks &&-              isEnabled Ext_multiline_tables opts -> do-                rawHeaders <- padRow <$> mapM (blockListToMarkdown opts) headers-                rawRows <- mapM (fmap padRow . mapM (blockListToMarkdown opts))-                           rows-                (nest 2,) <$> pandocTable opts True (all null headers)-                                aligns' widths' rawHeaders rawRows-            | isEnabled Ext_grid_tables opts &&-               writerColumns opts >= 8 * numcols -> (id,) <$>-                gridTable opts blockListToMarkdown-                  (all null headers) aligns' widths' headers rows-            | hasSimpleCells &&-              isEnabled Ext_pipe_tables opts -> do-                rawHeaders <- padRow <$> mapM (blockListToMarkdown opts) headers-                rawRows <- mapM (fmap padRow . mapM (blockListToMarkdown opts))-                           rows-                (id,) <$> pipeTable opts (all null headers) aligns' widths'-                           rawHeaders rawRows-            | isEnabled Ext_raw_html opts -> fmap (id,) $-                   literal . removeBlankLinesInHTML <$>-                   writeHtml5String opts{ writerTemplate = Nothing } (Pandoc nullMeta [t])-            | otherwise -> return (id, literal "[TABLE]")-  return $ nst (tbl $$ caption''') $$ blankline+  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+           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+           return $ (tbl $$ caption''') $$ blankline+       | not hasBlocks &&+         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+           return $ nest 2 (tbl $$ caption''') $$ blankline+       | isEnabled Ext_grid_tables opts &&+          writerColumns opts >= 8 * numcols -> do+           tbl <- gridTable opts blockListToMarkdown+             (all null headers) aligns' widths' headers rows+           return $ (tbl $$ caption''') $$ blankline+       | hasSimpleCells &&+         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+           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+       | otherwise+         -> return $ (literal "[TABLE]" $$ caption''') $$ blankline blockToMarkdown' opts (BulletList items) = do   contents <- inList $ mapM (bulletListItemToMarkdown opts) items   return $ (if isTightList items then vcat else vsep)
src/Text/Pandoc/Writers/Markdown/Inline.hs view
@@ -506,7 +506,9 @@             let str' = T.strip str              in inlineToMarkdown opts                   (Image nullAttr [Str str'] (url <> urlEncode str', str'))-          _ | isEnabled Ext_tex_math_dollars opts ->+          _ | isEnabled Ext_tex_math_gfm opts ->+                return $ "$`" <> literal str <> "`$"+            | isEnabled Ext_tex_math_dollars opts ->                 return $ "$" <> literal str <> "$"             | isEnabled Ext_tex_math_single_backslash opts ->                 return $ "\\(" <> literal str <> "\\)"@@ -531,7 +533,11 @@              in (\x -> blankline <> x <> blankline) `fmap`                  inlineToMarkdown opts (Image nullAttr [Str str']                         (url <> urlEncode str', str'))-          _ | isEnabled Ext_tex_math_dollars opts ->+          _ | isEnabled Ext_tex_math_gfm opts ->+                return $ cr <> (literal "``` math"+                             $$ literal str+                             $$ literal "```") <> cr+            | isEnabled Ext_tex_math_dollars opts ->                 return $ "$$" <> literal str <> "$$"             | isEnabled Ext_tex_math_single_backslash opts ->                 return $ "\\[" <> literal str <> "\\]"@@ -724,19 +730,3 @@   where   go (Emph xs) = Span nullAttr xs   go x         = x--toSubscriptInline :: Inline -> Maybe Inline-toSubscriptInline Space = Just Space-toSubscriptInline (Span attr ils) = Span attr <$> traverse toSubscriptInline ils-toSubscriptInline (Str s) = Str . T.pack <$> traverse toSubscript (T.unpack s)-toSubscriptInline LineBreak = Just LineBreak-toSubscriptInline SoftBreak = Just SoftBreak-toSubscriptInline _ = Nothing--toSuperscriptInline :: Inline -> Maybe Inline-toSuperscriptInline Space = Just Space-toSuperscriptInline (Span attr ils) = Span attr <$> traverse toSuperscriptInline ils-toSuperscriptInline (Str s) = Str . T.pack <$> traverse toSuperscript (T.unpack s)-toSuperscriptInline LineBreak = Just LineBreak-toSuperscriptInline SoftBreak = Just SoftBreak-toSuperscriptInline _ = Nothing
src/Text/Pandoc/Writers/Ms.hs view
@@ -41,7 +41,7 @@ import Text.Pandoc.ImageSize import Text.Pandoc.Logging import Text.Pandoc.Options-import Text.DocLayout+import Text.DocLayout hiding (Color) import Text.Pandoc.Shared import Text.Pandoc.Templates (renderTemplate) import Text.Pandoc.Writers.Math
src/Text/Pandoc/Writers/Muse.hs view
@@ -719,7 +719,11 @@                      then mempty                      else literal ("#" <> anchor) <> space   modify $ \st -> st { stUseTags = False }-  return $ anchorDoc <> (if null inlines && not (T.null anchor)-                         then mempty-                         else (if null names then (if hasDir then contents' else "<class>" <> contents' <> "</class>")-                               else "<class name=\"" <> literal (head names) <> "\">" <> contents' <> "</class>"))+  return $ anchorDoc <>+   if null inlines && not (T.null anchor)+      then mempty+      else case names of+             [] | hasDir -> contents'+                | otherwise -> "<class>" <> contents' <> "</class>"+             (n:_) -> "<class name=\"" <> literal n <> "\">" <>+                         contents' <> "</class>"
src/Text/Pandoc/Writers/OpenDocument.hs view
@@ -33,7 +33,7 @@ import qualified Text.Pandoc.Builder as B import Text.Pandoc.Logging import Text.Pandoc.Options-import Text.DocLayout+import Text.DocLayout hiding (link) import Text.Pandoc.Shared (linesToPara, tshow, blocksToInlines) import Text.Pandoc.Templates (renderTemplate) import qualified Text.Pandoc.Translations as Term (Term(Figure, Table))@@ -305,7 +305,10 @@        go b                 = blockToOpenDocument o b        newLevel a l = do          nn <- length <$> gets stParaStyles-         ls <- head   <$> gets stListStyles+         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@@ -396,13 +399,14 @@                 Left msg -> do                   unless (T.null msg) $ report $ CouldNotHighlight msg                   unhighlighted s-    Table a bc s th tb tf -> setFirstPara >> table (Ann.toTable a bc s th tb tf)+    Table a bc s th tb tf -> setFirstPara >>+                              table o (Ann.toTable a bc s th tb tf)     HorizontalRule   -> setFirstPara >> return (selfClosingTag "text:p"                          [ ("text:style-name", "Horizontal_20_Line") ])     b@(RawBlock f s) -> if f == Format "opendocument"                         then return $ text $ T.unpack s                         else empty <$ report (BlockNotRendered b)-    Figure a capt b  -> figure a capt b+    Figure a capt b  -> figure o a capt b     where       defList       b = do setInDefinitionList True                            r <- vcat  <$> mapM (deflistItemToOpenDocument o) b@@ -427,8 +431,9 @@       orderedList a b = do (ln,pn) <- newOrderedListStyle (isTightList b) a                            inTags True "text:list" [ ("text:style-name", "L" <> tshow ln)]                                       <$> orderedListToOpenDocument o pn b-      table :: PandocMonad m => Ann.Table -> OD m (Doc Text)-      table (Ann.Table (ident, _, _) (Caption _ c) colspecs thead tbodies _) = do+      table :: PandocMonad m => WriterOptions -> Ann.Table -> OD m (Doc Text)+      table opts+          (Ann.Table (ident, _, _) (Caption _ c) colspecs thead tbodies _) = do         tn <- length <$> gets stTableStyles         pn <- length <$> gets stParaStyles         let  genIds      = map chr [65..]@@ -458,8 +463,11 @@                             ("table:name"      , name)                           , ("table:style-name", name)                           ] (vcat columns $$ th $$ vcat tr)-        return $ captionDoc $$ tableDoc-      figure (ident, _, _) (Caption _ longcapt) body =+        return $+          case writerTableCaptionPosition opts of+            CaptionAbove -> captionDoc $$ tableDoc+            CaptionBelow -> tableDoc $$ captionDoc+      figure opts (ident, _, _) (Caption _ longcapt) body =         case blocksToInlines longcapt of           [] ->             withParagraphStyle o "Figure" body@@ -470,7 +478,10 @@                           if isEnabled Ext_native_numbering o                           then numberedFigureCaption ident                           else unNumberedCaption "FigureCaption"-            return $ imageDoc $$ captionDoc+            return $+              case writerFigureCaptionPosition opts of+                CaptionAbove -> captionDoc $$ imageDoc+                CaptionBelow -> imageDoc $$ captionDoc   numberedTableCaption :: PandocMonad m => Text -> Doc Text -> OD m (Doc Text)
src/Text/Pandoc/Writers/RTF.hs view
@@ -281,8 +281,9 @@                  else sizes'   columns <- T.concat <$>      zipWithM (tableItemToRTF indent) aligns cols-  let rightEdges = tail $ scanl (\sofar new -> sofar + floor (new * totalTwips))-                                (0 :: Integer) sizes+  let rightEdges = drop 1 $+                    scanl (\sofar new -> sofar + floor (new * totalTwips))+                          (0 :: Integer) sizes   let cellDefs = map (\edge -> (if header                                    then "\\clbrdrb\\brdrs"                                    else "") <> "\\cellx" <> tshow edge)
src/Text/Pandoc/Writers/Shared.hs view
@@ -38,6 +38,8 @@                      , stripLeadingTrailingSpace                      , toSubscript                      , toSuperscript+                     , toSubscriptInline+                     , toSuperscriptInline                      , toTableOfContents                      , endsWithPlain                      , toLegacyTable@@ -469,6 +471,22 @@                  Just $ chr (0x2080 + (ord c - 48))   | isSpace c = Just c   | otherwise = Nothing++toSubscriptInline :: Inline -> Maybe Inline+toSubscriptInline Space = Just Space+toSubscriptInline (Span attr ils) = Span attr <$> traverse toSubscriptInline ils+toSubscriptInline (Str s) = Str . T.pack <$> traverse toSubscript (T.unpack s)+toSubscriptInline LineBreak = Just LineBreak+toSubscriptInline SoftBreak = Just SoftBreak+toSubscriptInline _ = Nothing++toSuperscriptInline :: Inline -> Maybe Inline+toSuperscriptInline Space = Just Space+toSuperscriptInline (Span attr ils) = Span attr <$> traverse toSuperscriptInline ils+toSuperscriptInline (Str s) = Str . T.pack <$> traverse toSuperscript (T.unpack s)+toSuperscriptInline LineBreak = Just LineBreak+toSuperscriptInline SoftBreak = Just SoftBreak+toSuperscriptInline _ = Nothing  -- | Construct table of contents (as a bullet list) from document body. toTableOfContents :: WriterOptions
src/Text/Pandoc/Writers/TEI.hs view
@@ -138,9 +138,9 @@ blockToTEI opts (CodeBlock (_,classes,_) str) =   return $ literal ("<ab type='codeblock " <> lang <> "'>") <> cr <>      flush (literal (escapeStringForXML str) <> cr <> text "</ab>")-    where lang  = if null langs-                     then ""-                     else escapeStringForXML (head langs)+    where lang  = case langs of+                    [] -> ""+                    (l:_) -> escapeStringForXML l           syntaxMap = writerSyntaxMap opts           isLang l    = T.toLower l `elem` map T.toLower (languages syntaxMap)           langsFrom s = if isLang s
src/Text/Pandoc/Writers/Typst.hs view
@@ -18,7 +18,8 @@   ) where import Text.Pandoc.Definition import Text.Pandoc.Class ( PandocMonad)-import Text.Pandoc.Options ( WriterOptions(..), WrapOption(..), isEnabled )+import Text.Pandoc.Options ( WriterOptions(..), WrapOption(..), isEnabled,+                             CaptionPosition(..) ) import Data.Text (Text) import Data.List (intercalate, intersperse) import Data.Bifunctor (first, second)@@ -67,6 +68,9 @@               (fmap chomp . inlinesToTypst)               meta   main <- blocksToTypst blocks+  let toPosition :: CaptionPosition -> Text+      toPosition CaptionAbove = "top"+      toPosition CaptionBelow = "bottom"   let context = defField "body" main               $ defField "toc" (writerTableOfContents options)               $ (if isEnabled Ext_citations options@@ -81,6 +85,10 @@                           resetField "lang" (langLanguage l) .                           maybe id (resetField "region") (langRegion l))               $ defField "toc-depth" (tshow $ writerTOCDepth options)+              $ defField "figure-caption-position"+                   (toPosition $ writerFigureCaptionPosition options)+              $ defField "table-caption-position"+                   (toPosition $ writerTableCaptionPosition options)               $ (if writerNumberSections options                     then defField "numbering" ("1.1.1.1.1" :: Text)                     else id)@@ -177,8 +185,9 @@                                   parens (                                     "numbering: " <>                                     doubleQuoted-                                      (head (orderedListMarkers-                                             (1, sty, delim))) <>+                                     (case orderedListMarkers (1, sty, delim) of+                                          (m:_) -> m+                                          [] -> "1.") <>                                     ", start: " <>                                       text (show start) )) $$                                x $$@@ -517,8 +526,7 @@      then do        suppl <- case citationSuffix cite of                   [] -> pure mempty-                  suff -> (<> endCode) . brackets-                            <$> inlinesToTypst (eatComma suff)+                  suff -> brackets <$> inlinesToTypst (eatComma suff)        pure $ "@" <> literal ident' <> suppl      else do        let label = if T.all isIdentChar ident'
src/Text/Pandoc/Writers/ZimWiki.hs view
@@ -128,7 +128,9 @@                       c <- inlineListToZimWiki opts capt                       return $ "" <> c <> "\n"   headers' <- if all null headers-                 then zipWithM (tableItemToZimWiki opts) aligns (head rows)+                 then case rows of+                        [] -> pure mempty+                        (r:_) -> zipWithM (tableItemToZimWiki opts) aligns r                  else mapM (inlineListToZimWiki opts . removeFormatting)headers  -- emphasis, links etc. are not allowed in table headers   rows' <- mapM (zipWithM (tableItemToZimWiki opts) aligns) rows   let widths = map (maybe 0 maximum . nonEmpty . map T.length) $
test/Tests/Old.hs view
@@ -242,6 +242,10 @@       "ipynb/rank.ipynb" "ipynb/rank.out.html"     ]   , testGroup "markua" [ testGroup "writer" $ writerTests' "markua"]+  , testGroup "ansi"+      [ test' "ansi" ["-f", "markdown", "-t", "ansi"]+        "ansi-test.txt" "ansi-test.ansi"+      ]   ]  where     test'           = test pandocPath
test/Tests/Readers/HTML.hs view
@@ -87,16 +87,16 @@             setMeta "lang" (text "es") (doc (plain (text "hola")))           ]         , testGroup "main"-          [ test htmlNativeDivs "<main> becomes <div role=main>" $ "<main>hello</main>" =?>-            doc (divWith ("", [], [("role", "main")]) (plain (text "hello")))+          [ test htmlNativeDivs "<main> contents are parsed" $ "<header>ignore me</header><nav><p>ignore me</p><main>hello</main><footer>ignore me</footer>" =?>+            doc (plain (text "hello"))           , test htmlNativeDivs "<main role=X> becomes <div role=X>" $ "<main role=foobar>hello</main>" =?>             doc (divWith ("", [], [("role", "foobar")]) (plain (text "hello")))           , test htmlNativeDivs "<main> has attributes preserved" $ "<main id=foo class=bar data-baz=qux>hello</main>" =?>             doc (divWith ("foo", ["bar"], [("role", "main"), ("baz", "qux")]) (plain (text "hello")))           , test htmlNativeDivs "<main> closes <p>" $ "<p>hello<main>main content</main>" =?>-            doc (para (text "hello") <> divWith ("", [], [("role", "main")]) (plain (text "main content")))+            doc (plain (text "main content"))           , test htmlNativeDivs "<main> followed by text" $ "<main>main content</main>non-main content" =?>-            doc (divWith ("", [], [("role", "main")]) (plain (text "main content")) <> plain (text "non-main content"))+            doc (plain (text "main content"))           ]         , testGroup "code"           [
test/Tests/Readers/Markdown.hs view
@@ -208,17 +208,17 @@              | lsts <- [ [i, j, k] | i <- lists, j <- lists, k <- lists]              ]           <> [ "lists with newlines and indent in backticks" =:-               T.intercalate ("\n" <> T.replicate 4 " ") (zipWith (\i (_, lt, _) -> lt <> i) lis lsts)-               =?> let (_, _, f) = head lsts-                   in f [plain $ code $ T.intercalate (T.replicate 5 " ") $ head lis' : zipWith (\i (_, lt, _) -> lt <> i) (tail lis') (tail lsts)]-             | lsts <- [ [i, j, k] | i <- lists, j <- lists, k <- lists]+               T.intercalate ("\n" <> T.replicate 4 " ") (zipWith (\i (_, lt, _) -> lt <> i) lis (l:ls))+               =?> let (_, _, f) = l+                   in f [plain $ code $ T.intercalate (T.replicate 5 " ") $ "text" : zipWith (\i (_, lt, _) -> lt <> i) (drop 1 lis') ls]+             | (l:ls) <- [ [i, j, k] | i <- lists, j <- lists, k <- lists]              ]           <> [ "lists with blank lines and indent in backticks" =:-               T.intercalate ("\n\n" <> T.replicate 4 " ") (zipWith (\i (_, lt, _) -> lt <> i) lis lsts)+               T.intercalate ("\n\n" <> T.replicate 4 " ") (zipWith (\i (_, lt, _) -> lt <> i) lis (l:ls))                <> "\n"-               =?> let (_, _, f) = head lsts-                   in f . pure $ (para . text $ head lis) <> bldLsts para (tail lsts) (tail lis)-             | lsts <- [ [i, j, k] | i <- lists, j <- lists, k <- lists]+               =?> let (_, _, f) = l+                   in f . pure $ (para . text $ "`text") <> bldLsts para ls (drop 1 lis)+             | (l:ls) <- [ [i, j, k] | i <- lists, j <- lists, k <- lists]              ]         , testGroup "emph and strong"           [ "two strongs in emph" =:
test/Tests/Shared.hs view
@@ -51,7 +51,8 @@    in d' == makeSections False Nothing d'  givesTOC :: String -> (Blocks, Blocks) -> TestTree-givesTOC desc (blocks, toc) = test (toTableOfContents def) desc (toList blocks, head . toList $ toc)+givesTOC desc (blocks, toc) =+  test (singleton . toTableOfContents def) desc (toList blocks, toc)  linkId :: T.Text -> T.Text -> T.Text -> Inlines -> Inlines linkId lId = linkWith (lId,[],[])
+ test/ansi-test.ansi view
@@ -0,0 +1,116 @@+[1m[23m[39m[49m[24m[29mLEVEL 1 HEADING[0m++Text++[1m[23m[39m[49m[24m[29mLevel 2 heading[0m++Text++[22m[3m[39m[49m[24m[29mLevel 3 heading[0m++Text++[22m[3m[39m[49m[24m[29mLevel 4 heading[0m++Text++[22m[3m[39m[49m[24m[29mLevel 5 heading[0m++Text++• list++  • nested++    1) numbered++       continuation paragraph++[22m[23m[36m[49m[4m[29m]8;;http://example.com\link[0m]8;;\++[22m[23m[36m[49m[4m[29m]8;;mailto:mail@example.com\mail@example.com[0m]8;;\++│ Block quote+│+│ │ Nested block quote++Multiline table with caption:++Centered    Left       Right        Default aligned+Header      Aligned    Aligned      +─────────── ────────── ──────────── ──────────────────────────+First       row        12.0         Example of a row that+                                    spans multiple lines.+Second      row        5.0          Here’s another one. Note+                                    the blank line between+                                    rows.+─────────── ────────── ──────────── ──────────────────────────++  Here’s the caption. It may span multiple lines.++Multiline table without caption:++Centered    Left       Right        Default aligned+Header      Aligned    Aligned      +─────────── ────────── ──────────── ──────────────────────────+First       row        12.0         Example of a row that+                                    spans multiple lines.+Second      row        5.0          Here’s another one. Note+                                    the blank line between+                                    rows.+─────────── ────────── ──────────── ──────────────────────────++Table without column headers:++───────────────── ───────────────── ───────────────── ─────────────────+12                12                12                12+123               123               123               123+1                 1                 1                 1+───────────────── ───────────────── ───────────────── ─────────────────++Footnote¹++Multiple blocks in a cell++────────────────── ─────────── ────────────+[1m[23m[39m[49m[24m[29mCOL 1[0m              [1m[23m[39m[49m[24m[29mCOL 2[0m       [1m[23m[39m[49m[24m[29mCOL 3[0m+                               +col 1              col 2       col 3+r1 a               • b         c c 2 c 2+                               +r1 bis             • b 2       +                               +                   • b 2       +────────────────── ─────────── ────────────++East Asian characters have double width++── ────+魚 fish+── ────++This is inline code: [22m[23m[31m[47m[24m[29m x >>= y ++ 3 [0m.++    [22m[23m[31m[49m[24m[29mcode block[0m+    [22m[23m[31m[49m[24m[29m   >>> ## ``[0m++Highlighted:++    [0m[0m[22;23;24m[31;22;23;24m<[0m[22;23;24m[32;1;23;24mp[0m[22;23;24m[31;22;23;24m><[0m[22;23;24m[32;1;23;24ma[0m[22;23;24m[32;22;23;24m href[0m[22;23;24m[90;22;23;24m=[0m[22;23;24m[36;22;23;24m"foobar"[0m[22;23;24m[32;22;23;24m title[0m[22;23;24m[90;22;23;24m=[0m[22;23;24m[36;22;23;24m"title"[0m[22;23;24m[31;22;23;24m>[0m[22;23;24m[0m[22;23;24mThis is a link[0m[22;23;24m[31;22;23;24m</[0m[22;23;24m[32;1;23;24ma[0m[22;23;24m[31;22;23;24m></[0m[22;23;24m[32;1;23;24mp[0m[22;23;24m[31;22;23;24m>[0m[22;23;24m+    [90;22;3;24m<!-- comment -->[0m[22;23;24m[0m++Math: $\pi^2 = \frac{1}{2}$++[22m[3m[39m[49m[24m[29me[0m = [22m[3m[39m[49m[24m[29mmc[0m²++────────────────────++More text.++[1m[23m[39m[49m[24m[29mboldface text[0m, [22m[23m[39m[49m[4m[29munderlined text[0m, [22m[3m[39m[49m[24m[29memphasized text[0m.++small caps++                          ────────────────────++  1. Here’s the note.[0m]8;;\
+ test/ansi-test.txt view
@@ -0,0 +1,122 @@+---+title: My Document+author: John Doe+date: July 25, 1933+...++# Level 1 heading++Text++## Level 2 heading++Text++### Level 3 heading++Text++#### Level 4 heading++Text++##### Level 5 heading++Text++- list+  - nested+    1) numbered++       continuation paragraph++[link](http://example.com)++<mail@example.com>++> Block quote+>+> > Nested block quote++Multiline table with caption:++:  Here's the caption.+It may span multiple lines.++---------------------------------------------------------------+ Centered   Left             Right+  Header    Aligned        Aligned  Default aligned+----------  ---------  -----------  ---------------------------+   First    row               12.0  Example of a row that spans+                                    multiple lines.++   Second   row                5.0  Here's another one.  Note+                                    the blank line between rows.+---------------------------------------------------------------++Multiline table without caption:++---------------------------------------------------------------+ Centered   Left             Right+  Header    Aligned        Aligned  Default aligned+----------  ---------  -----------  ---------------------------+   First    row               12.0  Example of a row that spans+                                    multiple lines.++   Second   row                5.0  Here's another one.  Note+                                    the blank line between rows.+---------------------------------------------------------------++Table without column headers:++-------     ------ ----------   -------+     12     12        12             12+    123     123       123           123+      1     1          1              1+-------     ------ ----------   -------++Footnote^[Here's the note.]++Multiple blocks in a cell+++------------------+-----------+------------++| # col 1          | # col 2   | # col 3    |+| col 1            | col 2     | col 3      |++------------------+-----------+------------++| r1 a             | - b       | c          |+|                  | - b 2     | c 2        |+| r1 bis           | - b 2     | c 2        |++------------------+-----------+------------+++East Asian characters have double width+++--+----++|魚|fish|++--+----+++This is inline code: `x >>= y ++ 3`.++```+code block+   >>> ## ``+```++Highlighted:++```html+<p><a href="foobar" title="title">This is a link</a></p>+<!-- comment -->+```++Math: $\pi^2 = \frac{1}{2}$++$$e = mc^2$$++----++More text.++**boldface text**, [underlined text]{.underline}, *emphasized text*.++[small caps]{.smallcaps}+
+ test/command/10057.md view
@@ -0,0 +1,6 @@+```+% pandoc --natbib -t latex+We all love the famous proof by @BenjaminHornigold [p. 42].+^D+We all love the famous proof by \citet[p.~42]{BenjaminHornigold}.+```
+ test/command/10062.md view
@@ -0,0 +1,10 @@+```+% pandoc -t asciidoc+### section++##### five+^D+==== section++====== five+```
+ test/command/10071.md view
@@ -0,0 +1,15 @@+Leading tabs must be preserved in org mode *src* blocks with the `-i`+flag when pandoc is called with `-p`/`--preserve-tabs`.++```+% pandoc -f org -t native --preserve-tabs+#+begin_src makefile -i+%.o: %.cpp+	$(CXX)	-o	$@	$<+#+end_src+^D+[ CodeBlock+    ( "" , [ "makefile" ] , [] )+    "%.o: %.cpp\n\t$(CXX)\t-o\t$@\t$<\n"+]+```
+ test/command/10093.md view
@@ -0,0 +1,53 @@+```+% pandoc -f rst+========== ====+Function   1   +========== ====+a          yes +b              +========== ====+^D+<table>+<thead>+<tr>+<th>Function</th>+<th>1</th>+</tr>+</thead>+<tbody>+<tr>+<td>a</td>+<td>yes</td>+</tr>+<tr>+<td>b</td>+<td></td>+</tr>+</tbody>+</table>+```++```+% pandoc -f rst+========== ====+Function   1   +========== ====+a          yes +           & no+========== ====+^D+<table>+<thead>+<tr>+<th>Function</th>+<th>1</th>+</tr>+</thead>+<tbody>+<tr>+<td>a</td>+<td>yes &amp; no</td>+</tr>+</tbody>+</table>+```
+ test/command/10094.md view
@@ -0,0 +1,47 @@+```+% pandoc -f rst -t markdown_strict+.. table:: Test Table++   ================================== ====+   Functions for tests                1   +   ================================== ====+   a                                  yes +   b                                      +   c                                      +   d                                  yes+   e                                      +   ================================== ====+^D+<table>+<caption>Test Table</caption>+<thead>+<tr>+<th>Functions for tests</th>+<th>1</th>+</tr>+</thead>+<tbody>+<tr>+<td>a</td>+<td>yes</td>+</tr>+<tr>+<td>b</td>+<td></td>+</tr>+<tr>+<td>c</td>+<td></td>+</tr>+<tr>+<td>d</td>+<td>yes</td>+</tr>+<tr>+<td>e</td>+<td></td>+</tr>+</tbody>+</table>++```
+ test/command/10105.md view
@@ -0,0 +1,8 @@+```+% pandoc -t asciidoc --wrap=preserve+[link](https://example.com)+[link](ftps://example.com)+^D+https://example.com[link]+link:ftps://example.com[link]+```
+ test/command/10145.md view
@@ -0,0 +1,24 @@+```+% pandoc -f rtf -t native+{\rtf1\ansi\deff0{\fonttbl{\f0 \fswiss Helvetica;}{\f1 \fmodern Courier;}}+{\colortbl;\red255\green0\blue0;\red0\green0\blue255;}+\widowctrl\hyphauto++{\pard \ql \f0 \sa0 \li0 \fi0 {\shp{\*\shpinst\shpwr2\shpwrk3\shpbypara\shpbyignore\shptop1320\shpbottom7745\shpbxcolumn\shpbxignore\shpleft0\shpright9638{\sp{\sn shapeType}{\sv 75}}{\sp{\sn wzDescription}{\sv }}{\sp{\sn wzName}{\sv }}{\sp{\sn pib}{\sv {\pict\jpegblip\picw20\pich22\picwgoal400\pichgoal440 ffd8ffe000104a46494600010101004800480000fffe0050546869732061727420697320696e20746865207075626c696320646f6d61696e2e204b6576696e204875676865732c206b6576696e68406569742e636f6d2c2053657074656d6265722031393935ffdb00430001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101ffdb00430101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101ffc00011080016001403012200021101031101ffc4001a000100020301000000000000000000000000080905060a07ffc400231000010501000300010500000000000000060304050708020001090a11153976b7ffc400160101010100000000000000000000000000060800ffc400261101000102050109000000000000000000010200030405061121b33134365154717475b4ffda000c03010002110311003f00a90cf388f366a62aa720ed6ae07f96901f3831d973452b8cf36fe3570fc908e46d466433e5dd954f2e96992d9e498c7753faa44916e016ca91cc7d88b38fe60a5b97737defcbcc539c98d336a57f4fc2ca9a486bf07ab575ad9a3af4df221d8215e36df86c4504ff0024574551b3d687ee0575757b3ad64e311ee62bd94158d37e24198c43973099f1fc0c41614d950246513a081abf76cfe7061f6863281e6352fd1670949c148dd6dfb0d25f5b3689b1d5c965b0eacbf4e0932ad28e22ab9ae945633f4744bd3c8cee0a7fdf085b9000f449c5f7afa30b83e0b6fd7b0c8429c9467ff9715347c891e25fa24a205861aa715e6a09bd0488237dc2723414d9891381524e8ca7c0894664f835653631ab55ee7e3de433e4ff001b30949124e4c10c8b6ad0a479b3f9c937b2cf5bc0095ad600a0a41a0e9faee174a1c605e161c6c7a313539650b0113190f1a8368e60d5b24f30ff008ea7f0bf867fa6595feeb6978f1fe0f9c26177f4d63a51a9235184750e7d18811339cd000000c75f000e00380380ae390c350def826ed42ad051fa6f501c50f9b699c3b69cbeb76476d202bf3ac985b6e0e968be66572893e6a744540bd9722e5c87956848629bc2559306bd113e8653d3b6aff651dfad7a3ac8b02958cba02a93ccf525757039bae6cff090e1d90688e8aa233ee86a4c4a3e0586d6b2340522e47dcb7d0046d8a5acb05a123ee25d2b230b2ada6e2e2f9ede3c05202520ec2487b0d56562529d8b3393bca76adca4ec1bca508abb001babc007915d84fe3dd14e207e3c62f8379da2a3b861fb6629d28dba53b6ea388ebfed866bf6dfb553455e91ed547ae92e9445253a4fdf3efb4f8ebdfbe7d3c78f1ee0bb9e13e358e942a4ed49e22cff00eeb35fdd7ebfffd9}}}}}\par}+{\pard \ql \f0 \sa0 \li0 \fi0 moon\par}+}+^D+[ Para+    [ Image+        ( ""+        , []+        , [ ( "width" , "0.2777777777777778in" )+          , ( "height" , "0.3055555555555556in" )+          ]+        )+        [ Str "image" ]+        ( "9ea9761885249909bcd8a610706eef51b54dc351.jpg" , "" )+    ]+, Para [ Str "moon" ]+]+```
+ test/command/10148.md view
@@ -0,0 +1,18 @@+```+% pandoc -t typst+See [@MyPaper].++See [@MyPaper, Equation 1] for details.++See [@MyPaper, Equation 1].++See [@MyPaper, Equation 1; @Other, Figure 1].+^D+See @MyPaper.++See @MyPaper[Equation 1] for details.++See @MyPaper[Equation 1].++See @MyPaper[Equation 1]@Other[Figure 1].+```
+ test/command/10160.md view
@@ -0,0 +1,11 @@+```+% pandoc -f latex -t native+\begin{equation}+  [0,1)+\end{equation}++\begin{table}[h]+\end{table}+^D+[ Para [ Math DisplayMath "[0,1)" ] ]+```
test/command/1166.md view
@@ -28,11 +28,11 @@ <td>Second column of row 1.</td> </tr> <tr>-<td><p>2</p></td>-<td><p>Second column of row 2. Second line of paragraph.</p></td>+<td>2</td>+<td>Second column of row 2. Second line of paragraph.</td> </tr> <tr>-<td><p>3</p></td>+<td>3</td> <td><ul> <li>Second column of row 3.</li> <li>Second item in bullet list (row 3, column 2).</li>
+ test/command/4746.md view
@@ -0,0 +1,56 @@+```+% pandoc -f latex -t native+\begin{tabular}{c c}+  \begin{tabular}{c} a \\ \end{tabular}+  &+  \\+\end{tabular}+^D+[ Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignCenter , ColWidthDefault )+    , ( AlignCenter , ColWidthDefault )+    ]+    (TableHead ( "" , [] , [] ) [])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Table+                    ( "" , [] , [] )+                    (Caption Nothing [])+                    [ ( AlignCenter , ColWidthDefault ) ]+                    (TableHead ( "" , [] , [] ) [])+                    [ TableBody+                        ( "" , [] , [] )+                        (RowHeadColumns 0)+                        []+                        [ Row+                            ( "" , [] , [] )+                            [ Cell+                                ( "" , [] , [] )+                                AlignDefault+                                (RowSpan 1)+                                (ColSpan 1)+                                [ Plain [ Str "a" ] ]+                            ]+                        ]+                    ]+                    (TableFoot ( "" , [] , [] ) [])+                ]+            , Cell+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+]+```
test/command/5071.md view
@@ -49,8 +49,8 @@ ^D <h2 data-number="2.3" id="first-section"><span class="header-section-number">2.3</span> First section</h2>-<h3 data-number="2.3.3" id="subhead"><span-class="header-section-number">2.3.3</span> Subhead</h3>+<h3 data-number="2.3.1" id="subhead"><span+class="header-section-number">2.3.1</span> Subhead</h3>  ``` @@ -62,7 +62,7 @@ ^D <h2 data-number="0.3" id="first-section"><span class="header-section-number">0.3</span> First section</h2>-<h3 data-number="0.3.3" id="subhead"><span-class="header-section-number">0.3.3</span> Subhead</h3>+<h3 data-number="0.3.1" id="subhead"><span+class="header-section-number">0.3.1</span> Subhead</h3>  ```
+ test/command/5116.md view
@@ -0,0 +1,107 @@+```+% pandoc -t latex+![This is a figure.](img.jpg)++  Right     Left     Center     Default+-------     ------ ----------   -------+     12     12        12            12+    123     123       123          123+      1     1          1             1++  :  Demonstration of simple table syntax.+^D+\begin{figure}+\centering+\pandocbounded{\includegraphics[keepaspectratio]{img.jpg}}+\caption{This is a figure.}+\end{figure}++\begin{longtable}[]{@{}rlcl@{}}+\caption{Demonstration of simple table syntax.}\tabularnewline+\toprule\noalign{}+Right & Left & Center & Default \\+\midrule\noalign{}+\endfirsthead+\toprule\noalign{}+Right & Left & Center & Default \\+\midrule\noalign{}+\endhead+\bottomrule\noalign{}+\endlastfoot+12 & 12 & 12 & 12 \\+123 & 123 & 123 & 123 \\+1 & 1 & 1 & 1 \\+\end{longtable}++```++```+% pandoc -t latex --figure-caption-position=above --table-caption-position=above+![This is a figure.](img.jpg)++  Right     Left     Center     Default+-------     ------ ----------   -------+     12     12        12            12+    123     123       123          123+      1     1          1             1++  :  Demonstration of simple table syntax.+^D+\begin{figure}+\centering+\caption{This is a figure.}+\pandocbounded{\includegraphics[keepaspectratio]{img.jpg}}+\end{figure}++\begin{longtable}[]{@{}rlcl@{}}+\caption{Demonstration of simple table syntax.}\tabularnewline+\toprule\noalign{}+Right & Left & Center & Default \\+\midrule\noalign{}+\endfirsthead+\toprule\noalign{}+Right & Left & Center & Default \\+\midrule\noalign{}+\endhead+\bottomrule\noalign{}+\endlastfoot+12 & 12 & 12 & 12 \\+123 & 123 & 123 & 123 \\+1 & 1 & 1 & 1 \\+\end{longtable}++```++```+% pandoc -t latex --figure-caption-position=below --table-caption-position=below+![This is a figure.](img.jpg)++  Right     Left     Center     Default+-------     ------ ----------   -------+     12     12        12            12+    123     123       123          123+      1     1          1             1++  :  Demonstration of simple table syntax.+^D+\begin{figure}+\centering+\pandocbounded{\includegraphics[keepaspectratio]{img.jpg}}+\caption{This is a figure.}+\end{figure}++\begin{longtable}[]{@{}rlcl@{}}+\toprule\noalign{}+Right & Left & Center & Default \\+\midrule\noalign{}+\endhead+\bottomrule\noalign{}+\tabularnewline+\caption{Demonstration of simple table syntax.}+\endlastfoot+12 & 12 & 12 & 12 \\+123 & 123 & 123 & 123 \\+1 & 1 & 1 & 1 \\+\end{longtable}++```
+ test/command/9121.md view
@@ -0,0 +1,17 @@+````+% pandoc -t gfm+a $$x=y$$ b+^D+a+``` math+x=y+```+b+````++````+% pandoc -t gfm+a $x=y$ b+^D+a $`x=y`$ b+````
test/command/9452.md view
@@ -12,7 +12,7 @@  Here is a sentence @something2024. -With supplement @something2024[p.~3];.+With supplement @something2024[p.~3].  And just the year #cite(<something2024>, form: "year");. 
test/typst-reader.native view
@@ -4980,13 +4980,10 @@                           AlignDefault                           (RowSpan 1)                           (ColSpan 1)-                          [ Div-                              ( "" , [] , [] )-                              [ Para-                                  [ Math-                                      InlineMath-                                      "f:{\\mathbb{R}} \\rightarrow {\\mathbb{R}}"-                                  ]+                          [ Para+                              [ Math+                                  InlineMath+                                  "f:{\\mathbb{R}} \\rightarrow {\\mathbb{R}}"                               ]                           ]                       , Cell@@ -5004,13 +5001,8 @@                           AlignDefault                           (RowSpan 1)                           (ColSpan 1)-                          [ Div-                              ( "" , [] , [] )-                              [ Para-                                  [ Math-                                      InlineMath-                                      "9.8\\ \\text{ m/s}^{2}"-                                  ]+                          [ Para+                              [ Math InlineMath "9.8\\ \\text{ m/s}^{2}"                               ]                           ]                       , Cell@@ -5018,18 +5010,14 @@                           AlignDefault                           (RowSpan 1)                           (ColSpan 1)-                          [ Div-                              ( "" , [] , [] )-                              [ Para-                                  [ Code-                                      ( "" , [] , [] )-                                      "\"9.8\" \"m/s\"^2"-                                  , Space-                                  , Link-                                      ( "" , [ "ref" ] , [] )-                                      [ Str "[tricky]" ]-                                      ( "#tricky" , "" )-                                  ]+                          [ Para+                              [ Code+                                  ( "" , [] , [] ) "\"9.8\" \"m/s\"^2"+                              , Space+                              , Link+                                  ( "" , [ "ref" ] , [] )+                                  [ Str "[tricky]" ]+                                  ( "#tricky" , "" )                               ]                           ]                       ]@@ -5238,13 +5226,10 @@                           AlignDefault                           (RowSpan 1)                           (ColSpan 1)-                          [ Div-                              ( "" , [] , [] )-                              [ Para-                                  [ Math-                                      InlineMath-                                      "\\sigma^{2} = \\sqrt{{\\sum(x_{i} - \\mu)}^{2}/N}"-                                  ]+                          [ Para+                              [ Math+                                  InlineMath+                                  "\\sigma^{2} = \\sqrt{{\\sum(x_{i} - \\mu)}^{2}/N}"                               ]                           ]                       , Cell@@ -5264,13 +5249,10 @@                           AlignDefault                           (RowSpan 1)                           (ColSpan 1)-                          [ Div-                              ( "" , [] , [] )-                              [ Para-                                  [ Math-                                      InlineMath-                                      "E(X) = \\mu_{X} = \\sum(x_{i} - P\\left( x_{i} \\right))"-                                  ]+                          [ Para+                              [ Math+                                  InlineMath+                                  "E(X) = \\mu_{X} = \\sum(x_{i} - P\\left( x_{i} \\right))"                               ]                           ]                       , Cell@@ -5366,29 +5348,26 @@           , Str "."           ]       , Para []-      , Div-          ( "" , [] , [] )-          [ HorizontalRule-          , Para-              [ Str "johanvx"-              , Space-              , Str "("-              , Underline+      , HorizontalRule+      , Para+          [ Str "johanvx"+          , Space+          , Str "("+          , Underline+              [ Underline                   [ Underline-                      [ Underline-                          [ Link-                              ( "" , [] , [] )-                              [ Str "https://github.com/johanvx" ]-                              ( "https://github.com/johanvx" , "" )-                          ]+                      [ Link+                          ( "" , [] , [] )+                          [ Str "https://github.com/johanvx" ]+                          ( "https://github.com/johanvx" , "" )                       ]                   ]-              , Str ")"-              , Space-              , Str "\8202\8193"-              , Space-              , Str "2023-05-22"               ]+          , Str ")"+          , Space+          , Str "\8202\8193"+          , Space+          , Str "2023-05-22"           ]       ]   ]
test/writer.djot view
@@ -533,7 +533,7 @@ {#latex} # LaTeX -- +- - $`2+2=4` - $`x \in y` - $`\alpha \wedge \omega`
test/writer.typst view
@@ -20,6 +20,14 @@   stroke: none ) +#show figure.where(+  kind: table+): set figure.caption(position: top)++#show figure.where(+  kind: image+): set figure.caption(position: bottom)+ #let content-to-string(content) = {   if content.has("text") {     content.text
xml-light/Text/Pandoc/XML/Light/Output.hs view
@@ -35,7 +35,7 @@ import Text.Pandoc.XML.Light.Types  ----- duplicates functinos from Text.XML.Output+-- duplicates functions from Text.XML.Output --  -- | The XML 1.0 header