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 +7/−0
- CONTRIBUTING.md +23/−0
- INSTALL.md +31/−6
- MANUAL.txt +62/−16
- README.md +6/−4
- changelog.md +207/−0
- data/odt/styles.xml +3/−0
- data/templates/default.ansi +21/−0
- data/templates/default.latex +2/−2
- data/templates/default.typst +12/−4
- data/templates/styles.html +5/−0
- pandoc.cabal +10/−6
- src/Text/Pandoc/App.hs +0/−2
- src/Text/Pandoc/App/CommandLineOptions.hs +26/−2
- src/Text/Pandoc/App/Opt.hs +12/−1
- src/Text/Pandoc/App/OutputSettings.hs +4/−2
- src/Text/Pandoc/Chunks.hs +1/−1
- src/Text/Pandoc/Format.hs +7/−1
- src/Text/Pandoc/Highlighting.hs +1/−0
- src/Text/Pandoc/Options.hs +21/−0
- src/Text/Pandoc/Parsing/GridTable.hs +1/−1
- src/Text/Pandoc/Readers/Docx.hs +8/−2
- src/Text/Pandoc/Readers/Docx/Parse.hs +1/−1
- src/Text/Pandoc/Readers/DokuWiki.hs +1/−1
- src/Text/Pandoc/Readers/HTML.hs +61/−27
- src/Text/Pandoc/Readers/LaTeX.hs +1/−1
- src/Text/Pandoc/Readers/LaTeX/Math.hs +0/−1
- src/Text/Pandoc/Readers/LaTeX/Table.hs +25/−20
- src/Text/Pandoc/Readers/Markdown.hs +4/−5
- src/Text/Pandoc/Readers/ODT/Generic/XMLConverter.hs +16/−10
- src/Text/Pandoc/Readers/Org/Blocks.hs +19/−24
- src/Text/Pandoc/Readers/RST.hs +18/−12
- src/Text/Pandoc/Readers/RTF.hs +11/−0
- src/Text/Pandoc/Readers/TikiWiki.hs +9/−10
- src/Text/Pandoc/Readers/Typst.hs +4/−1
- src/Text/Pandoc/Readers/Vimwiki.hs +29/−28
- src/Text/Pandoc/Shared.hs +12/−12
- src/Text/Pandoc/URI.hs +1/−1
- src/Text/Pandoc/Writers.hs +3/−0
- src/Text/Pandoc/Writers/ANSI.hs +354/−0
- src/Text/Pandoc/Writers/AsciiDoc.hs +14/−5
- src/Text/Pandoc/Writers/ConTeXt.hs +3/−3
- src/Text/Pandoc/Writers/Docx.hs +2/−1
- src/Text/Pandoc/Writers/Docx/OpenXML.hs +4/−1
- src/Text/Pandoc/Writers/Docx/Table.hs +9/−5
- src/Text/Pandoc/Writers/HTML.hs +23/−41
- src/Text/Pandoc/Writers/ICML.hs +22/−20
- src/Text/Pandoc/Writers/LaTeX.hs +5/−1
- src/Text/Pandoc/Writers/LaTeX/Citation.hs +17/−12
- src/Text/Pandoc/Writers/LaTeX/Table.hs +27/−17
- src/Text/Pandoc/Writers/Markdown.hs +46/−40
- src/Text/Pandoc/Writers/Markdown/Inline.hs +8/−18
- src/Text/Pandoc/Writers/Ms.hs +1/−1
- src/Text/Pandoc/Writers/Muse.hs +8/−4
- src/Text/Pandoc/Writers/OpenDocument.hs +20/−9
- src/Text/Pandoc/Writers/RTF.hs +3/−2
- src/Text/Pandoc/Writers/Shared.hs +18/−0
- src/Text/Pandoc/Writers/TEI.hs +3/−3
- src/Text/Pandoc/Writers/Typst.hs +13/−5
- src/Text/Pandoc/Writers/ZimWiki.hs +3/−1
- test/Tests/Old.hs +4/−0
- test/Tests/Readers/HTML.hs +4/−4
- test/Tests/Readers/Markdown.hs +8/−8
- test/Tests/Shared.hs +2/−1
- test/ansi-test.ansi +116/−0
- test/ansi-test.txt +122/−0
- test/command/10057.md +6/−0
- test/command/10062.md +10/−0
- test/command/10071.md +15/−0
- test/command/10093.md +53/−0
- test/command/10094.md +47/−0
- test/command/10105.md +8/−0
- test/command/10145.md +24/−0
- test/command/10148.md +18/−0
- test/command/10160.md +11/−0
- test/command/1166.md +3/−3
- test/command/4746.md +56/−0
- test/command/5071.md +4/−4
- test/command/5116.md +107/−0
- test/command/9121.md +17/−0
- test/command/9452.md +1/−1
- test/typst-reader.native +38/−59
- test/writer.djot +1/−1
- test/writer.typst +8/−0
- xml-light/Text/Pandoc/XML/Light/Output.hs +1/−1
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
@@ -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)
@@ -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" =:
@@ -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 & 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+++ 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+++ 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+++ 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