packages feed

pandoc 3.7.0.2 → 3.8

raw patch · 244 files changed

+8649/−1834 lines, 244 filesdep +unicode-datadep ~citeprocdep ~doclayoutdep ~skylightingbinary-added

Dependencies added: unicode-data

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

Files

AUTHORS.md view
@@ -78,6 +78,7 @@ - Christoffer Ackelman - Christoffer Sawicki - Christophe Dervieux+- Christopher Kenny - Clare Macrae - Clint Adams - Conal Elliott@@ -113,6 +114,7 @@ - Eric Kow - Eric Schrijver - Eric Seidel+- Erik Post - Erik Rask - Ethan Riley - Étienne Bersac@@ -342,11 +344,14 @@ - Raniere Silva - Raymond Ehlers - Recai Oktaş+- Repetitive+- Reuben Thomas - Rowan Rodrik van der Molen - Roland Hieber - Roman Beránek - Ruqi - RyanGlScott+- Ryan Gibb - S.P.H - Salim B - Sam S. Almahri@@ -356,6 +361,7 @@ - Santiago Zarate - Sascha Wilde - Scott Morrison+- Sean Soon - Sebastian Talmon - Sebbones - Sen-wen Deng@@ -465,6 +471,7 @@ - lux-lth - luz paz - lwolfsonkin+- massifrg - mbracke - mbrackeantidot - mh4ckt3mh4ckt1c4s
MANUAL.txt view
@@ -1,7 +1,7 @@ --- title: Pandoc User's Guide author: John MacFarlane-date: 2025-05-28+date: 2025-09-06 ---  # Synopsis@@ -156,7 +156,9 @@ for [typography] if the `csquotes` variable or metadata field is set to a true value.  The [`natbib`], [`biblatex`], [`bibtex`], and [`biber`] packages can optionally be used for [citation-rendering].  The following packages will be used to improve+rendering].  If math with `\cancel`, `\bcancel`, or `\xcancel`+is used, the [`cancel`] package is needed.+The following packages will be used to improve output quality if present, but pandoc does not require them to be present: [`upquote`] (for straight quotes in verbatim environments), [`microtype`] (for better spacing adjustments),@@ -182,6 +184,7 @@ [`framed`]: https://ctan.org/pkg/framed [`geometry`]: https://ctan.org/pkg/geometry [`graphicx`]: https://ctan.org/pkg/graphicx+[`cancel`]: https://ctan.org/pkg/cancel [`hyperref`]: https://ctan.org/pkg/hyperref [`iftex`]: https://ctan.org/pkg/iftex [`listings`]: https://ctan.org/pkg/listings@@ -279,6 +282,7 @@     - `twiki` ([TWiki markup])     - `typst` ([typst])     - `vimwiki` ([Vimwiki])+    - `xml` (XML version of native AST)     - the path of a custom Lua reader, see [Custom readers and writers] below     ::: @@ -357,6 +361,7 @@     - `s5` ([S5] HTML and JavaScript slide show)     - `tei` ([TEI Simple])     - `typst` ([typst])+    - `xml` (XML version of native AST)     - `xwiki` ([XWiki markup])     - `zimwiki` ([ZimWiki markup])     - the path of a custom Lua writer, see [Custom readers and writers] below@@ -461,7 +466,7 @@ `--list-highlight-styles`  :   List supported styles for syntax highlighting, one per line.-    See `--highlight-style`.+    See `--syntax-highlighting`.  `-v`, `--version` @@ -922,18 +927,32 @@     inside raw HTML blocks when the `markdown_in_html_blocks`     extension is not set. -`--no-highlight`+`--syntax-highlighting="default"|"none"|"idiomatic"|`*STYLE*`|`*FILE* -:   Disables syntax highlighting for code blocks and inlines, even when-    a language attribute is given.+:   The method to use for code syntax highlighting. Setting a+    specific *STYLE* causes highlighting to be performed with the+    internal highlighting engine, using KDE syntax definitions and+    styles. The `"idiomatic"` method uses a format-specific+    highlighter if one is available, or the default style if the+    target format has no idiomatic highlighting method. Setting this+    option to `none` disables all syntax highlighting. The+    `"default"` method uses a format-specific default. -`--highlight-style=`*STYLE*|*FILE*+    The default for HTML, EPUB, Docx, Ms, Man, and LaTeX output is+    to use the internal highlighter with the default style; Typst+    output relies on Typst's own syntax highlighting system by+    default. -:   Specifies the coloring style to be used in highlighted source code.-    Options are `pygments` (the default), `kate`, `monochrome`,-    `breezeDark`, `espresso`, `zenburn`, `haddock`, and `tango`.-    For more information on syntax highlighting in pandoc, see-    [Syntax highlighting], below.  See also+    The [`listings`][] LaTeX package is used for idiomatic+    highlighting in LaTeX. The package does not support multi-byte+    encoding for source code. To handle UTF-8 you would need to+    use a custom template. This issue is fully documented here:+    [Encoding issue with the listings package][].++    Style options are `pygments` (the default), `kate`,+    `monochrome`, `breezeDark`, `espresso`, `zenburn`, `haddock`,+    and `tango`. For more information on syntax highlighting in+    pandoc, see [Syntax highlighting], below. See also     `--list-highlight-styles`.      Instead of a *STYLE* name, a JSON file with extension@@ -944,11 +963,24 @@     To generate the JSON version of an existing style,     use `--print-highlight-style`. +`--no-highlight`++:   *Deprecated, use `--syntax-highlighting=none` instead.*++    Disables syntax highlighting for code blocks and inlines, even when+    a language attribute is given.++`--highlight-style=`*STYLE*|*FILE*++:   _Deprecated, use `--syntax-highlighting=`*STYLE*|*FILE* instead._++    Specifies the coloring style to be used in highlighted source code.+ `--print-highlight-style=`*STYLE*|*FILE*  :   Prints a JSON version of a highlighting style, which can     be modified, saved with a `.theme` extension, and used-    with `--highlight-style`.  This option may be used with+    with `--syntax-highlighting`.  This option may be used with     `-o`/`--output` to redirect output to a file, but     `-o`/`--output` must come before `--print-highlight-style`     on the command line.@@ -1171,7 +1203,10 @@  `--listings[=true|false]` -:   Use the [`listings`] package for LaTeX code blocks. The package+:   *Deprecated, use `--syntax-highlighting=idiomatic` or+    `--syntax-highlighting=default` instead.++    Use the [`listings`] package for LaTeX code blocks. The package     does not support multi-byte encoding for source code. To handle UTF-8     you would need to use a custom template. This issue is fully     documented here: [Encoding issue with the listings package].@@ -1700,6 +1735,7 @@    92 PandocUTF8DecodingError    93 PandocIpynbDecodingError    94 PandocUnsupportedCharsetError+   95 PandocInputNotTextError    97 PandocCouldNotFindDataFileError    98 PandocCouldNotFindMetadataFileError    99 PandocResourceNotFound@@ -1975,11 +2011,11 @@ | ```                              | ```                               | +----------------------------------+-----------------------------------+ | ```                              | ``` yaml                          |-| --no-highlight                   | highlight-style: null             |+| --no-highlight                   | syntax-highlighting: 'none'       | | ```                              | ```                               | +----------------------------------+-----------------------------------+ | ```                              | ``` yaml                          |-| --highlight-style kate           | highlight-style: kate             |+| --syntax-highlighting kate       | syntax-highlighting: kate         | | ```                              | ```                               | +----------------------------------+-----------------------------------+ | ```                              | ``` yaml                          |@@ -2728,7 +2764,7 @@     documents  `abstract-title`-:   title of abstract, currently used only in HTML, EPUB, and docx.+:   title of abstract, currently used only in HTML, EPUB, docx, and Typst.     This will be set automatically to a localized value,     depending on `lang`, but can be manually overridden. @@ -3207,6 +3243,16 @@ `natbiboptions` :   list of options for natbib +#### Other++`pdf-trailer-id`+:   the PDF trailer ID; must be two PDF byte strings if set,+    conventionally with 16 bytes each. E.g.,+    `<00112233445566778899aabbccddeeff>+    <00112233445566778899aabbccddeeff>`.++    See the section on [reproducible builds].+ [KOMA-Script]: https://ctan.org/pkg/koma-script [LaTeX Font Catalogue]: https://tug.org/FontCatalogue/ [LaTeX font encodings guide]: https://ctan.org/pkg/encguide@@ -3313,14 +3359,14 @@ `includesource` :   include all source documents as file attachments in the PDF file -[ConTeXt Paper Setup]: https://wiki.contextgarden.net/PaperSetup-[ConTeXt Layout]: https://wiki.contextgarden.net/Layout-[ConTeXt Font Switching]: https://wiki.contextgarden.net/Font_Switching+[ConTeXt Paper Setup]: https://wiki.contextgarden.net/Document_layout_and_layers/Paper_setup+[ConTeXt Layout]: https://wiki.contextgarden.net/Document_layout_and_layers/Tutorials+[ConTeXt Font Switching]: https://wiki.contextgarden.net/Characters_words_and_fonts/Tutorials [ConTeXt Color]: https://wiki.contextgarden.net/Color-[ConTeXt Headers and Footers]: https://wiki.contextgarden.net/Headers_and_Footers-[ConTeXt Indentation]: https://wiki.contextgarden.net/Indentation-[ConTeXt ICC Profiles]: https://wiki.contextgarden.net/PDFX#ICC_profiles-[ConTeXt PDFA]: https://wiki.contextgarden.net/PDF/A+[ConTeXt Headers and Footers]: https://wiki.contextgarden.net/Document_layout_and_layers/Headers_and_footers+[ConTeXt Indentation]: https://wiki.contextgarden.net/Text_blocks/Typography/Indentation+[ConTeXt PDFA]: https://wiki.contextgarden.net/Input_and_compilation/PDF/PDFA+[ConTeXt ICC Profiles]: https://wiki.contextgarden.net/Input_and_compilation/PDF/PDFX#ICC_profiles [`setupwhitespace`]: https://wiki.contextgarden.net/Command/setupwhitespace [`setupinterlinespace`]: https://wiki.contextgarden.net/Command/setupinterlinespace [`setuppagenumbering`]: https://wiki.contextgarden.net/Command/setuppagenumbering@@ -3391,6 +3437,19 @@ `columns` :    Number of columns for body text. +`thanks`+:   contents of acknowledgments footnote after document title++`mathfont`, `codefont`+:    Name of system font to use for math and code, respectively.++`linestretch`+:   adjusts line spacing, e.g. `1.25`, `1.5`++`linkcolor`, `filecolor`, `citecolor`+:   color for external links, internal links, and citation links,+    respectively: expects a hexadecimal color code+ ### Variables for ms  `fontfamily`@@ -3528,7 +3587,7 @@    `html`  output formats-:  `markdown`, `latex`, `context`, `rst`+:  `markdown`, `latex`, `context`, `org`, `rst`  enabled by default in :  `markdown`, `latex`, `context` (both input and output)@@ -3878,6 +3937,21 @@ Natural tables allow more fine-grained global customization but come at a performance penalty compared to extreme tables. +### Extension: `smart_quotes` (org) ###++Interpret straight quotes as curly quotes during parsing. When+*writing* Org, then the `smart_quotes` extension has the reverse+effect: what would have been curly quotes comes out straight.++This extension is implied if `smart` is enabled.++### Extension: `special_strings` (org) ###++Interpret `---` as em-dashes, `--` as en-dashes, `\-` as shy+hyphen, and `...` as ellipses.++This extension is implied if `smart` is enabled.+ ### Extension: `tagging` ### {#extension--tagging}  Enabling this extension with `context` output will produce markup@@ -4233,10 +4307,10 @@ class attribute will be printed after the opening fence as a bare word. -To prevent all highlighting, use the `--no-highlight` flag.-To set the highlighting style, use `--highlight-style`.-For more information on highlighting, see [Syntax highlighting],-below.+To prevent all highlighting, use the `--syntax-highlighting=none`+option. To set the highlighting style or method, use+`--syntax-highlighting`. For more information on highlighting, see+[Syntax highlighting], below.  ## Line blocks @@ -4502,9 +4576,6 @@       ~ Definition 2b  Note that space between items in a definition list is required.-(A variant that loosens this requirement, but disallows "lazy"-hard wrapping, can be activated with the [`compact_definition_lists`-extension][Extension: `compact_definition_lists`].)  [^3]:  I have been influenced by the suggestions of [David   Wheeler](https://justatheory.com/2009/02/modest-markdown-proposal/).@@ -5615,10 +5686,14 @@     ![This is the caption](/url/of/image.png)  How this is rendered depends on the output format. Some output-formats (e.g. RTF) do not yet support figures.  In those+formats (e.g. RTF) do not yet support figures. In those formats, you'll just get an image in a paragraph by itself, with-no caption.+no caption. For LaTeX output, you can specify a [figure's+positioning](https://www.overleaf.com/learn/latex/Positioning_images_and_tables#The_figure_environment)+by adding the `latex-placement` attribute. +    ![This is the caption](/url/of/image.png){latex-placement="ht"}+ If you just want a regular inline image, just make sure it is not the only thing in the paragraph. One way to do this is to insert a nonbreaking space after the image:@@ -6109,33 +6184,6 @@ Parses MultiMarkdown-style heading identifiers (in square brackets, after the heading but before any trailing `#`s in an ATX heading). -### Extension: `compact_definition_lists` ###--Activates the definition list syntax of pandoc 1.12.x and earlier.-This syntax differs from the one described above under [Definition lists]-in several respects:--  - No blank line is required between consecutive items of the-    definition list.-  - To get a "tight" or "compact" list, omit space between consecutive-    items; the space between a term and its definition does not affect-    anything.-  - Lazy wrapping of paragraphs is not allowed:  the entire definition must-    be indented four spaces.[^6]--[^6]:  To see why laziness is incompatible with relaxing the requirement-    of a blank line between items, consider the following example:--        bar-        :    definition-        foo-        :    definition--    Is this a single list item with two definitions of "bar," the first of-    which is lazily wrapped, or two list items?  To remove the ambiguity-    we must either disallow lazy wrapping or require a blank line between-    list items.- ### Extension: `gutenberg` ###  Use [Project Gutenberg] conventions for `plain` output:@@ -6439,7 +6487,7 @@ ## Placement of the bibliography  If the style calls for a list of works cited, it will be placed-in a div with id `refs`, if one exists:+in a div with id `refs`, if one exists:[^note-on-refs]      ::: {#refs}     :::@@ -6448,6 +6496,13 @@ Generation of the bibliography can be suppressed by setting `suppress-bibliography: true` in the YAML metadata. +[^note-on-refs]:+    Note that if `--file-scope` is used, a div written this way will be+    given an identifier of the form `FILE__refs`, to avoid duplicate+    identifiers (see `--file-scope`). In view of this possibility,+    pandoc will place the bibliography in any div whose identifier is+    `refs` *or* ends with `__refs`.+ If you wish the bibliography to have a section heading, you can set `reference-section-title` in the metadata, or put the heading at the beginning of the div with id `refs` (if you are using it)@@ -7370,22 +7425,23 @@ of language names that pandoc will recognize, type `pandoc --list-highlight-languages`. -The color scheme can be selected using the `--highlight-style` option.-The default color scheme is `pygments`, which imitates the default color-scheme used by the Python library pygments (though pygments is not actually-used to do the highlighting).  To see a list of highlight styles,-type `pandoc --list-highlight-styles`.+The color scheme can be selected using the `--syntax-highlighting`+option. The default color scheme is `pygments`, which imitates the+default color scheme used by the Python library pygments (though+pygments is not actually used to do the highlighting). To see a+list of highlight styles, type `pandoc --list-highlight-styles`. -If you are not satisfied with the predefined styles, you can-use `--print-highlight-style` to generate a JSON `.theme` file which-can be modified and used as the argument to `--highlight-style`. To-get a JSON version of the `pygments` style, for example:+If you are not satisfied with the predefined styles, you can use+`--print-highlight-style` to generate a JSON `.theme` file which+can be modified and used as the argument to+`--syntax-highlighting`. To get a JSON version of the `pygments`+style, for example:      pandoc -o my.theme --print-highlight-style pygments  Then edit `my.theme` and use it like this: -    pandoc --highlight-style my.theme+    pandoc --syntax-highlighting my.theme  If you are not satisfied with the built-in highlighting, or you want to highlight a language that isn't supported, you can use the@@ -7397,7 +7453,7 @@ If you receive an error that pandoc "Could not read highlighting theme", check that the JSON file is encoded with UTF-8 and has no Byte-Order Mark (BOM). -To disable highlighting, use the `--no-highlight` option.+To disable highlighting, use `--syntax-highlighting=none`.  [skylighting]: https://github.com/jgm/skylighting @@ -7556,6 +7612,11 @@ `SOURCE_DATE_EPOCH` should contain an integer unix timestamp (specifying the number of seconds since midnight UTC January 1, 1970). +For reproducible builds with LaTeX, you can either specify the+`pdf-trailer-id` in the metadata or leave it undefined, in which+case pandoc will create a trailer-id based on a hash of the+`SOURCE_DATE_EPOCH` and the document's contents.+ Some document formats also include a unique identifier.  For EPUB, this can be set explicitly by setting the `identifier` metadata field (see [EPUB Metadata], above).@@ -7610,7 +7671,7 @@  ## Prince XML -The non-free HTML-to-PDf converter `prince` has extensive support+The non-free HTML-to-PDF converter `prince` has extensive support for various PDF standards as well as tagging. E.g.:      pandoc --pdf-engine=prince \
README.md view
@@ -105,6 +105,7 @@   markup](https://twiki.org/cgi-bin/view/TWiki/TextFormattingRules)) - `typst` ([typst](https://typst.app)) - `vimwiki` ([Vimwiki](https://vimwiki.github.io))+- `xml` (XML version of native AST) - the path of a custom Lua reader, see [Custom readers and   writers](https://pandoc.org/MANUAL.html#custom-readers-and-writers)   below@@ -216,6 +217,7 @@   slide show) - `tei` ([TEI Simple](https://github.com/TEIC/TEI-Simple)) - `typst` ([typst](https://typst.app))+- `xml` (XML version of native AST) - `xwiki` ([XWiki   markup](https://www.xwiki.org/xwiki/bin/view/Documentation/UserGuide/Features/XWikiSyntax/)) - `zimwiki` ([ZimWiki
changelog.md view
@@ -1,5 +1,412 @@ # Revision history for pandoc +## pandoc 3.8 (2025-09-06)++  * Add a new input and output format `xml`, exactly representing a Pandoc+    AST and isomorphic to the existing `native` and `json` formats (massifrg).+    XML schemas for validation can be found in `tools/pandoc-xml.*`.+    The format is documented in `doc/xml.md`. Pandoc now defaults to this+    reader and writer when the `.xml` extension is used.++    Two new exported modules are added [API change]:+    Text.Pandoc.Readers.XML, exporting `readXML`, and+    Text.Pandoc.Writers.XML, exporting `writeXML`.+    A new unexported module Text.Pandoc.XMLFormat is also added.++  * Add a new command line option `--syntax-highlighting`; this takes+    the values `none`, `default`, `idiomatic`, a style name, or a path to a+    theme file. It replaces the `--no-highlighting`, `--highlighting-style`,+    and `--listings` options, which will still work but with a deprecation+    warning. (Albert Krewinkel)++  * Create directory of output file if it doesn't exist (#11040).++  * Update `--version` copyright dates (#10961), and use a hardcoded+    string "pandoc" for the program name in `--version`, per GNU+    guidelines.++  * Add `smart_quotes` and `special_strings` extensions (Albert Krewinkel).+    Currently these only affect `org`. Org mode makes a distinction between+    smart parsing of quotes, and smart parsing of special strings like `...`.+    The finer grained control over these features is necessary to truthfully+    reproduce Emacs Org mode behavior. Special strings are enabled by default,+    while smart quotes are disabled.++  * Remove the old `compact_definition_lists` extension. This was+    neded to preserve backwards compatibility after pandoc 1.12+    was released, but at this point we can get rid of it.++  * Make `-t chunkedhtml -o -` output to stdout (as documented), rather+    than creating a directory called `-` (#11068).++  * RST reader: Support multiple header rows (#10338, TuongNM).++  * LaTeX reader:++    + Support soft hyphens (Albert Krewinkel).+    + Parse `\minisec` as unlisted level 6 headings (#10635, Albert Krewinkel).+    + Support `\ifmmode` (#10915).+    + Change handling of math environments (#9711, #9296).+      Certain environments in LaTeX will trigger math mode and can't+      occur within math mode: e.g., `align` or `equation`.  Previously+      we "downshifted" these, parsing an `align` environment as a+      Math element with `aligned`, and an `equation` environment as a+      regular display math element.  With this shift, we put these in+      Math inlines but retain the original environments.+      texmath and MathJax both handle these environments well.++  * Typst reader:++    + Fix addition of image path prefix to use posix separator.+    + Properly resolve image paths in included files (#11090).+    + Handle inline-level show rules on block content (#11017).+      Typst allows things like `smallcaps` to be applied to block-level+      content like headings.  This produces a type mismatch in pandoc,+      so before processing the output of typst-hs, we transform it,+      pulling the block-level elements outside of the inline-level+      elements.++  * Org reader:++    + Improve sub- and superscript parsing (Albert Krewinkel).+      Sub- and superscript must be preceded by a string in Org mode. Some text+      preceded by space or at the start of a paragraph was previously parsed+      incorrectly as sub- or superscript.+    + Allow "greater block" names to contain any non-space char (#4287,+      Albert Krewinkel).+    + Accept quoted values as argument values (#8869, Albert Krewinkel).+    + Recognize "fast access" characters in TODO state definitions+      (#10990, Ryan Gibb).+    + Improve org-cite parsing: Handle global prefix and suffix properly.+      Use all and only the styles mentioned in oc-basic.el.+      Allow space after `;`.++  * HTML reader:++    + Don't drop the initial newline in a `pre` element (#11064).++  * DocBook reader:++    + Add rowspan support (#10981, Sean Soon).+    + Be sensitive to startingnumber attribute on ordered lists (#10912).++  * POD reader:++    + Fix named entity lookup (#11015, Evan Silberman).++  * Man reader:++    + Support header and footer reader (Sean Soon).++  * Markdown reader:++    + Don't confuse a span after an author-in-text citation with a+      locator.  E.g. `@foo [test]{.bar}`.+      See https://github.com/jgm/pandoc/issues/9080#issuecomment-3221689892.+    + Make definition lists behave like other lists (#10889).+      If the `four_space_rule` extension is not enabled,+      figure out the indentation needed for child blocks dynamically,+      by looking at the first nonspace content after the `:` marker.+      Previously the four-space rule was always obeyed.+    + Fix tight/loose detection for definition lists, to conform to+      the documentation.++  * ODT reader:++    + Support `table-header-rows` (Tuong Nguyen Manh).++  * Docx reader:++    + Don't add highlighting if highlight color is "none" (#10900).+    + Handle strict OpenXML as well as transitional (#7691).+    + Fix `stringToInteger` (#9184). It previously converted things like+      `11ccc` to an integer; now it requires that the whole string be parsable+      as an integer.+    + Improve handling of AlternateContent. This fixes handling of+      one representation of emojis in Word (#11113).++  * LaTeX writer:++    + Control figure placement with attribute (#10369, Sean Soon).+      If a `latex-placement` attribute is present on a figure, it will be used+      as the optional positioning hint in LaTeX (e.g. `ht`). With implicit+      figures, `latex-placement` will be added to the figure (and removed from+      the image) if it is present on the image.+    + Include cancel package only if there is math that contains `\cancel`,+      `\bcancel`, or `\xcancel`.+    + Add braces around comments in `title-meta` (#10501). This is needed to+      prevent PDFs from interpreting this as a sequence of titles.+    + Set `pdf-trailer-id` if `SOURCE_DATE_EPOCH` envvar is set (#6539, Albert+      Krewinkel). The `SOURCE_DATE_EPOCH` environment variable is used to trigger+      reproducible PDF compilation, i.e., PDFs that are identical down to the+      byte level for repeated runs.+    + Be more conservative about using `\url` (#8802). We only use it when the+      URL is all ASCII, since the `\url` macro causes problems when used with+      some non-ASCII characters.+    + Support soft hyphens (Albert Krewinkel).+    + Change handling of math environments (#9711, #9296).+      When certain math environments (e.g. `align`) are found in Math+      elements, we emit them "raw" instead of putting them in `$..$`.++  * Typst writer:++    + Check `XID_Continue` in identifiers (Tuong Nguyen Manh).+    + Add escapes to prevent inadvertent lists due to automatic wrapping+      (#10047). Also simplify existing code that was meant to do this.+    + Add parentheses around typst-native year-only citations (#11044).+    + Add native Typst support for `nocite` (#10680, Albert Krewinkel).+      The `nocite` metadata field can now be used to supply+      additional citations that don't appear in the text, just as with citeproc+      and LaTeX's bibtex and natbib.+    + Set `lang` attribute in Divs (#10965).+    + Rename `numbering` variable to `section-numbering` (Albert Krewinkel).+      This is the name expected by the default template.+    + Add support for custom and/or translated "Abstract" titles (Albert+      Krewinkel, #9724).++  * Org writer:++    + Don't wrap link descriptions (#9000). Org doesn't reliable display+      these as links if they have hard breaks.+    + Disable smart quotes by default (Albert Krewinkel).++  * Markdown writer:++    + Better handling of pandoc-generated code blocks (#10926).+      Omit the wrapper sourceCode divs added by pandoc around code blocks.+      More intelligently identify which class to use for the one class+      allowed in GFM code blocks.  If there is a class of form `language-X`,+      use `X`; otherwise use the first class other than `sourceCode`.+    + Use fenced divs even with empty attributes (#10955, Carlos Scheidegger).+      Previously fenced divs were not used in this case, causing the writer to+      fall back to raw HTML.+    + Match indents in definition items (#10890, Albert Krewinkel).+      Previously, the first line of a definition details item always used a+      colon and three spaces instead of respecting the tab-stop setting, which+      could lead to round-tripping issues. Likewise, the indentation of+      continuation paragraphs in definition lists now matches the+      two-characters leader of the first line for Markua output.++  * DocBook writer:++    + Use `startingnumber` instead of `override` for start numbers on ordered+      lists (#10912).++  * ANSI writer:++    + Make `--wrap=none` work properly (#10898).++  * Djot writer:++    + Fix duplicate attributes before section headings (#10984).++  * Docx writer:++    + Ensure that documents don't start with a section separator+      (#10578, Albert Krewinkel). Any leading section separator is removed from+      the result.++  * HTML writer:++    + Unwrap "wrapper" divs (#11014). Some of the readers (e.g. djot) add+      "wrapper" divs to hold attributes for elements that have no slot for+      attributes in the pandoc AST. The HTML reader now "unwraps"+      these wrappers so that the attributes go on the intended elements.++  * Asciidoc writer:++    + Handle lists with sublists following continuations (#11006).+      These require an additional blank line in some cases.++  * HTML styles template: prefix default styles with informative CSS comment+    (Albert Krewinkel, #8819).++  * Org template: add `#+options` lines if necessary (Albert Krewinkel).+    The default template now adds `#+options` lines if non-default settings+    are used for the `smart_quotes` and `special_strings` extensions.++  * LaTeX template:++    + Don't emit empty `linkcolor=` in hypersetup (#11098).+    + Add RTL support for LuaTeX engine (Reuben Thomas).++  * Typst template:++    + Add several new variables (Christopher T. Kenny, #9956):+      `thanks`, `abstract-title`, `linestretch`, `mathfont`, `codefont`,+      `linkcolor`, `filecolor`, `citecolor`.++  * `reference.docx`:++    + Don't left-align table header row (R. N. West, #11019).+    + Update East Asia font theme in `styles.xml` to `minorEastAsia` (TomBen).+    + Update language settings in `styles.xml` for East Asia to Simplified+      Chinese (TomBen).++  * Text.Pandoc.PDF:++    + `makePDF`: automatically embed resources from media bag in HTML+      before trying to convert it with weasyprint, etc. (#11099).+      This will give better results when converting from formats like docx.+    + Use `utf8ToText` for LaTeX log messages.+    + Make images from MediaBag available in tmp dir for every PDF engine,+      not just LaTeX/ConTeXt (#10911).+    + Improve error readability when pdf-engine is not supported (Albert+      Krewinkel). Each supported engine is now printed on a line of its own.+    + Allow `pdflatex-dev` and `lualatex-dev` as PDF engines (#10991, Albert+      Krewinkel). These are the development versions of the LaTeX binaries;+      installable, e.g., with `tlmgr install latex-base-dev`.+    + Clean up `makePDF` (Albert Krewinkel).+    + Avoid encoding errors when reading LaTeX logs (#10954).++  * Text.Pandoc.Readers:++    + Raise unknown reader error for `ods`, `odp`, `odf`, `xls`,+      `xslx`, `zip` extensions.++  * Text.Pandoc.App:++    + Recognize binary signatures and fail early (Repetitive). Fail early when+      receiving binary input with recognized signature: zip[-based], including+      OpenDocument and Microsoft formats, PDF, CFBF-based (old Microsoft formats+      including .doc and .xls), DjVu.+    + Remove code duplication around version info.+      Text.Pandoc.App.CommandLineOptions and `pandoc-cli/src/pandoc.hs`+      had similar code for generating version information.+      To avoid duplication, we now export `versionInfo` from+      Text.Pandoc.App [API change]. This function has three parameters that can+      be filled in when it is called by `pandoc-cli`.++  * Text.Pandoc.Parsing:++    + `tableWith` and `tableWith'` now return a list of lists of Blocks, rather+      than a list of Blocks, for the header rows, allowing for multiple header+      rows [API change] (#10338, TuongNM).++  * Text.Pandoc.Citeproc:++    + Don't move footnotes around em-dashes (#11046).+    + Allow `--citeproc` to put the bibliography in a Div with id `refs`+      even when `--file-scope` is used (#11072). When `--file-scope`+      is used, a prefix will be added based on the filename, so the Div+      will end up having an identifier like `myfile.md__refs`.+      Previously, this prevented the bibliography from being added to+      the marked Div. Now pandoc will add the bibliography to any Div+      with the id `refs` or any id ending in `__refs`.++  * Text.Pandoc.Citeproc.BibTeX: Protect case in periodical titles (#11048).+    Thus, for example, `{npj} Quantum Information` should translate as+    `[npj]{.nocase} Quantum Information`.++  * Text.Pandoc.ImageSize:++    + Detect more JPEG file signatures (R. N. West and John MacFarlane, #11049).+    + Unpack compressed object streams in PDFs and look inside for MediaBox+      information (#10902).+    + Add Point and Pica as constructors of ImageSize [API change] (#8957).+      This will prevent unnecessary conversion of units.+    + Add Avif constructor on ImageType [API change] and support avif images+      (#10979).++  * Text.Pandoc.Writers.Shared:++    + Amend docs of `lookupMeta...` functions (#10634, Albert Krewinkel).++  * Text.Pandoc.Options:++    + Add and export `defaultWebTeXURL` WebTeX URL [API change] (#11029,+      Sean Soon). This fixes the `webtex` option when used without+      parameter in a defaults file.+    + Add type `HighlightMethod` and patterns [API Change] (Albert Krewinkel).+    + The `writerListings` and `writerHighlightStyle` fields of the+      `WriterOptions` type are replaced with `writerHighlightStyle`+      [API change] (Albert Krewinkel, #10525).++  * Text.Pandoc.Extensions:++    + Remove `Ext_compact_definition_lists` constructor for+      `Extension` [API change].++  * Text.Pandoc.SelfContained:++    + Try fetching relative resources without query or fragment if the original+      fetch fails. This provides a fix for #1477 in a way that doesn't raise+      the problems mentioned in #11021.++  * Text.Pandoc.Highlighting:++    + Export `defaultStyle` [API Change] (Albert Krewinkel).+      This allows to be more explicit about using a default style, and+      providing a single point of truth for its value. The variable is+      an alias for `pygments`.++  * Text.Pandoc.Class:++    + `downloadOrRead`: do not drop fragment/hash for local file paths (#11021).+      With the previous behavior it was impossible to have an image+      file containing `#` or `?`.+    + Export function `runSilently` [API Change] (Albert Krewinkel).+      The function runs an action in the PandocMonad, but returns all log+      messages reported by that action instead of adding them to the main log.+    + Make CommonState opaque. Text.Pandoc.Class now exports CommonState as+      an opaque object, without its fields. [API change]+      The internal module Text.Pandoc.Class.CommonState still exports+      the fields.+    + Text.Pandoc.Class now exports the following new functions:+      `getRequestHeaders`, `setRequestHeaders`, `getSourceURL`,+      `getTrace`. [API change]+    + CommonState now has a `stManager` field. This allows us to cache the HTTP+      client manager and reuse it for many requests, instead of creating it again+      (an expensive operation) for each request. This fixes a memory leak and+      performance issue in files with a large number of remote images (#10997).++  * Lua subsystem (Albert Krewinkel):++    + Add function `pandoc.structure.unique_identifier`.+    + Add functions `pandoc.text.superscript` and `subscript`.+    + Use proper interface functions to access the CommonState.+      The `PANDOC_STATE` is no longer a userdata object, but a table that+      behaves like the old object. Log messages in `PANDOC_STATE.log` are now+      in temporal order.+    + Add function `pandoc.path.exists`.+    + Add `normalize` function to *Pandoc* objects (#10356).+      This function performs a normalization of Pandoc documents. E.g.,+      multiple successive spaces are collapsed, and tables are normalized such+      that all rows and columns contain the same number of cells.+    + Add more UTF-8-aware file operations to `pandoc.system`.+      Functions that expect UTF-8-encoded filenames should make it easier to+      write platform-independent scripts, as the encoding of the actual+      filename depends on the system. In addition, there is a new+      generalized method to run commands, and functions to retrieve XDG+      directory names. The new functions are `command`, `copy`, `read_file`,+      `remove`, `rename`, `times`, `write_file`, `xdg`.+    + Allow hslua-2.4.+    + Require lua-module-system 1.2.3. This provides List methods to the value+      returned by `pandoc.system.list_directory` (#11032).++  * MANUAL.txt:++    + Fix broken ConTeXt links (R. N. West, #11055).+    + Add `xml` as input/output format.+    + Fix minor capitalization typo (#11052, Albert Krewinkel).++  * `doc/lua-filters`:++    + Fix docs for `pandoc.Cite` (Albert Krewinkel).+    + Don't encourage returning tables of filters from Lua filters+      (R. N. West, #10995). Use the `Pandoc:walk` method instead.++  * doc/extras.md: Fix link to pandoc-mode (Erik Post).++  * doc/lua-filters.md: Add example on using pandoc.Table constructor (#10956,+    Sean Soon).++  * Update `default.csl` from new chicago-author-date.csl, which is now+    for the 18th edition.++  * Use latest releases of citeproc, typst-hs, texmath, doclayout,+    skylighting-core, skylighting.+ ## pandoc 3.7.0.2 (2025-05-28)    * RST writer:
data/default.csl view
@@ -1,679 +1,3933 @@ <?xml version="1.0" encoding="utf-8"?>-<style xmlns="http://purl.org/net/xbiblio/csl" class="in-text" version="1.0" demote-non-dropping-particle="display-and-sort" page-range-format="chicago">-  <info>-    <title>Chicago Manual of Style 17th edition (author-date)</title>-    <id>http://www.zotero.org/styles/chicago-author-date</id>-    <link href="http://www.zotero.org/styles/chicago-author-date" rel="self"/>-    <link href="http://www.chicagomanualofstyle.org/tools_citationguide.html" rel="documentation"/>-    <author>-      <name>Julian Onions</name>-      <email>julian.onions@gmail.com</email>-    </author>-    <contributor>-      <name>Sebastian Karcher</name>-    </contributor>-    <contributor>-      <name>Richard Karnesky</name>-      <email>karnesky+zotero@gmail.com</email>-      <uri>http://arc.nucapt.northwestern.edu/Richard_Karnesky</uri>-    </contributor>-    <contributor>-      <name>Andrew Dunning</name>-      <email>andrew.dunning@utoronto.ca</email>-      <uri>https://orcid.org/0000-0003-0464-5036</uri>-    </contributor>-    <contributor>-      <name>Matthew Roth</name>-      <email>matthew.g.roth@yale.edu</email>-      <uri> https://orcid.org/0000-0001-7902-6331</uri>-    </contributor>-    <contributor>-      <name>Brenton M. Wiernik</name>-    </contributor>-    <category citation-format="author-date"/>-    <category field="generic-base"/>-    <summary>The author-date variant of the Chicago style</summary>-    <updated>2018-01-24T12:00:00+00:00</updated>-    <rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>-  </info>-  <locale xml:lang="en">-    <terms>-      <term name="editor" form="verb-short">ed.</term>-      <term name="container-author" form="verb">by</term>-      <term name="translator" form="verb-short">trans.</term>-      <term name="editortranslator" form="verb">edited and translated by</term>-      <term name="translator" form="short">trans.</term>-    </terms>-  </locale>-  <locale xml:lang="pt-PT">-    <terms>-      <term name="accessed">acedido a</term>-    </terms>-  </locale>-  <locale xml:lang="pt">-    <terms>-      <term name="editor" form="verb">editado por</term>-      <term name="editor" form="verb-short">ed.</term>-      <term name="container-author" form="verb">por</term>-      <term name="translator" form="verb-short">traduzido por</term>-      <term name="translator" form="short">trad.</term>-      <term name="editortranslator" form="verb">editado e traduzido por</term>-      <term name="and">e</term>-      <term name="no date" form="long">s.d</term>-      <term name="no date" form="short">s.d.</term>-      <term name="in">em</term>-      <term name="at">em</term>-      <term name="by">por</term>-    </terms>-  </locale>-  <macro name="secondary-contributors">-    <choose>-      <if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="none">-        <group delimiter=". ">-          <names variable="editor translator" delimiter=". ">-            <label form="verb" text-case="capitalize-first" suffix=" "/>-            <name and="text" delimiter=", "/>-          </names>-          <names variable="director" delimiter=". ">-            <label form="verb" text-case="capitalize-first" suffix=" "/>-            <name and="text" delimiter=", "/>-          </names>-        </group>-      </if>-    </choose>-  </macro>-  <macro name="container-contributors">-    <choose>-      <if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="any">-        <group prefix=", " delimiter=", ">-          <names variable="container-author" delimiter=", ">-            <label form="verb" suffix=" "/>-            <name and="text" delimiter=", "/>-          </names>-          <names variable="editor translator" delimiter=", ">-            <label form="verb" suffix=" "/>-            <name and="text" delimiter=", "/>-          </names>-        </group>-      </if>-    </choose>-  </macro>-  <macro name="editor">-    <names variable="editor">-      <name name-as-sort-order="first" and="text" sort-separator=", " delimiter=", " delimiter-precedes-last="always"/>-      <label form="short" prefix=", "/>-    </names>-  </macro>-  <macro name="translator">-    <names variable="translator">-      <name name-as-sort-order="first" and="text" sort-separator=", " delimiter=", " delimiter-precedes-last="always"/>-      <label form="short" prefix=", "/>-    </names>-  </macro>-  <macro name="recipient">-    <choose>-      <if type="personal_communication">-        <choose>-          <if variable="genre">-            <text variable="genre" text-case="capitalize-first"/>-          </if>-          <else>-            <text term="letter" text-case="capitalize-first"/>-          </else>-        </choose>-      </if>-    </choose>-    <names variable="recipient" delimiter=", ">-      <label form="verb" prefix=" " text-case="lowercase" suffix=" "/>-      <name and="text" delimiter=", "/>-    </names>-  </macro>-  <macro name="substitute-title">-    <choose>-      <if type="article-magazine article-newspaper review review-book" match="any">-        <text macro="container-title"/>-      </if>-    </choose>-  </macro>-  <macro name="contributors">-    <group delimiter=". ">-      <names variable="author">-        <name and="text" name-as-sort-order="first" sort-separator=", " delimiter=", " delimiter-precedes-last="always"/>-        <label form="short" prefix=", "/>-        <substitute>-          <names variable="editor"/>-          <names variable="translator"/>-          <names variable="director"/>-          <text macro="substitute-title"/>-          <text macro="title"/>-        </substitute>-      </names>-      <text macro="recipient"/>-    </group>-  </macro>-  <macro name="contributors-short">-    <names variable="author">-      <name form="short" and="text" delimiter=", " initialize-with=". "/>-      <substitute>-        <names variable="editor"/>-        <names variable="translator"/>-        <names variable="director"/>-        <text macro="substitute-title"/>-        <text macro="title"/>-      </substitute>-    </names>-  </macro>-  <macro name="interviewer">-    <names variable="interviewer" delimiter=", ">-      <label form="verb" prefix=" " text-case="capitalize-first" suffix=" "/>-      <name and="text" delimiter=", "/>-    </names>-  </macro>-  <macro name="archive">-    <group delimiter=". ">-      <text variable="archive_location" text-case="capitalize-first"/>-      <text variable="archive"/>-      <text variable="archive-place"/>-    </group>-  </macro>-  <macro name="access">-    <group delimiter=". ">-      <choose>-        <if type="graphic report" match="any">-          <text macro="archive"/>-        </if>-        <else-if type="article-journal bill book chapter legal_case legislation motion_picture paper-conference" match="none">-          <text macro="archive"/>-        </else-if>-      </choose>-      <choose>-        <if type="webpage post-weblog" match="any">-          <date variable="issued" form="text"/>-        </if>-      </choose>-      <choose>-        <if variable="issued" match="none">-          <group delimiter=" ">-            <text term="accessed" text-case="capitalize-first"/>-            <date variable="accessed" form="text"/>-          </group>-        </if>-      </choose>-      <choose>-        <if type="legal_case" match="none">-          <choose>-            <if variable="DOI">-              <text variable="DOI" prefix="https://doi.org/"/>-            </if>-            <else>-              <text variable="URL"/>-            </else>-          </choose>-        </if>-      </choose>-    </group>-  </macro>-  <macro name="title">-    <choose>-      <if variable="title" match="none">-        <choose>-          <if type="personal_communication speech thesis" match="none">-            <text variable="genre" text-case="capitalize-first"/>-          </if>-        </choose>-      </if>-      <else-if type="bill book graphic legislation motion_picture song" match="any">-        <text variable="title" text-case="title" font-style="italic"/>-        <group prefix=" (" suffix=")" delimiter=" ">-          <text term="version"/>-          <text variable="version"/>-        </group>-      </else-if>-      <else-if variable="reviewed-author">-        <choose>-          <if variable="reviewed-title">-            <group delimiter=". ">-              <text variable="title" text-case="title" quotes="true"/>-              <group delimiter=", ">-                <text variable="reviewed-title" text-case="title" font-style="italic" prefix="Review of "/>-                <names variable="reviewed-author">-                  <label form="verb-short" text-case="lowercase" suffix=" "/>-                  <name and="text" delimiter=", "/>-                </names>-              </group>-            </group>-          </if>-          <else>-            <group delimiter=", ">-              <text variable="title" text-case="title" font-style="italic" prefix="Review of "/>-              <names variable="reviewed-author">-                <label form="verb-short" text-case="lowercase" suffix=" "/>-                <name and="text" delimiter=", "/>-              </names>-            </group>-          </else>-        </choose>-      </else-if>-      <else-if type="legal_case interview patent" match="any">-        <text variable="title"/>-      </else-if>-      <else>-        <text variable="title" text-case="title" quotes="true"/>-      </else>-    </choose>-  </macro>-  <macro name="edition">-    <choose>-      <if type="bill book graphic legal_case legislation motion_picture report song" match="any">-        <choose>-          <if is-numeric="edition">-            <group delimiter=" " prefix=". ">-              <number variable="edition" form="ordinal"/>-              <text term="edition" form="short" strip-periods="true"/>-            </group>-          </if>-          <else>-            <text variable="edition" text-case="capitalize-first" prefix=". "/>-          </else>-        </choose>-      </if>-      <else-if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="any">-        <choose>-          <if is-numeric="edition">-            <group delimiter=" " prefix=", ">-              <number variable="edition" form="ordinal"/>-              <text term="edition" form="short"/>-            </group>-          </if>-          <else>-            <text variable="edition" prefix=", "/>-          </else>-        </choose>-      </else-if>-    </choose>-  </macro>-  <macro name="locators">-    <choose>-      <if type="article-journal">-        <choose>-          <if variable="volume">-            <text variable="volume" prefix=" "/>-            <group prefix=" (" suffix=")">-              <choose>-                <if variable="issue">-                  <text variable="issue"/>-                </if>-                <else>-                  <date variable="issued">-                    <date-part name="month"/>-                  </date>-                </else>-              </choose>-            </group>-          </if>-          <else-if variable="issue">-            <group delimiter=" " prefix=", ">-              <text term="issue" form="short"/>-              <text variable="issue"/>-              <date variable="issued" prefix="(" suffix=")">-                <date-part name="month"/>-              </date>-            </group>-          </else-if>-          <else>-            <date variable="issued" prefix=", ">-              <date-part name="month"/>-            </date>-          </else>-        </choose>-      </if>-      <else-if type="legal_case">-        <text variable="volume" prefix=", "/>-        <text variable="container-title" prefix=" "/>-        <text variable="page" prefix=" "/>-      </else-if>-      <else-if type="bill book graphic legal_case legislation motion_picture report song" match="any">-        <group prefix=". " delimiter=". ">-          <group>-            <text term="volume" form="short" text-case="capitalize-first" suffix=" "/>-            <number variable="volume" form="numeric"/>-          </group>-          <group>-            <number variable="number-of-volumes" form="numeric"/>-            <text term="volume" form="short" prefix=" " plural="true"/>-          </group>-        </group>-      </else-if>-      <else-if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="any">-        <choose>-          <if variable="page" match="none">-            <group prefix=". ">-              <text term="volume" form="short" text-case="capitalize-first" suffix=" "/>-              <number variable="volume" form="numeric"/>-            </group>-          </if>-        </choose>-      </else-if>-    </choose>-  </macro>-  <macro name="locators-chapter">-    <choose>-      <if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="any">-        <choose>-          <if variable="page">-            <group prefix=", ">-              <text variable="volume" suffix=":"/>-              <text variable="page"/>-            </group>-          </if>-        </choose>-      </if>-    </choose>-  </macro>-  <macro name="locators-article">-    <choose>-      <if type="article-newspaper">-        <group prefix=", " delimiter=", ">-          <group delimiter=" ">-            <text variable="edition"/>-            <text term="edition"/>-          </group>-          <group>-            <text term="section" form="short" suffix=" "/>-            <text variable="section"/>-          </group>-        </group>-      </if>-      <else-if type="article-journal">-        <choose>-          <if variable="volume issue" match="any">-            <text variable="page" prefix=": "/>-          </if>-          <else>-            <text variable="page" prefix=", "/>-          </else>-        </choose>-      </else-if>-    </choose>-  </macro>-  <macro name="point-locators">-    <choose>-      <if variable="locator">-        <choose>-          <if locator="page" match="none">-            <choose>-              <if type="bill book graphic legal_case legislation motion_picture report song" match="any">-                <choose>-                  <if variable="volume">-                    <group>-                      <text term="volume" form="short" suffix=" "/>-                      <number variable="volume" form="numeric"/>-                      <label variable="locator" form="short" prefix=", " suffix=" "/>-                    </group>-                  </if>-                  <else>-                    <label variable="locator" form="short" suffix=" "/>-                  </else>-                </choose>-              </if>-              <else>-                <label variable="locator" form="short" suffix=" "/>-              </else>-            </choose>-          </if>-          <else-if type="bill book graphic legal_case legislation motion_picture report song" match="any">-            <number variable="volume" form="numeric" suffix=":"/>-          </else-if>-        </choose>-        <text variable="locator"/>-      </if>-    </choose>-  </macro>-  <macro name="container-prefix">-    <text term="in" text-case="capitalize-first"/>-  </macro>-  <macro name="container-title">-    <choose>-      <if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="any">-        <text macro="container-prefix" suffix=" "/>-      </if>-    </choose>-    <choose>-      <if type="webpage">-        <text variable="container-title" text-case="title"/>-      </if>-      <else-if type="legal_case" match="none">-        <group delimiter=" ">-          <text variable="container-title" text-case="title" font-style="italic"/>-          <choose>-            <if type="post-weblog">-              <text value="(blog)"/>-            </if>-          </choose>-        </group>-      </else-if>-    </choose>-  </macro>-  <macro name="publisher">-    <group delimiter=": ">-      <text variable="publisher-place"/>-      <text variable="publisher"/>-    </group>-  </macro>-  <macro name="date">-    <choose>-      <if variable="issued">-        <group delimiter=" ">-          <date variable="original-date" form="text" date-parts="year" prefix="(" suffix=")"/>-          <date variable="issued">-            <date-part name="year"/>-          </date>-        </group>-      </if>-      <else-if variable="status">-        <text variable="status" text-case="capitalize-first"/>-      </else-if>-      <else>-        <text term="no date" form="short"/>-      </else>-    </choose>-  </macro>-  <macro name="date-in-text">-    <choose>-      <if variable="issued">-        <group delimiter=" ">-          <date variable="original-date" form="text" date-parts="year" prefix="[" suffix="]"/>-          <date variable="issued">-            <date-part name="year"/>-          </date>-        </group>-      </if>-      <else-if variable="status">-        <text variable="status"/>-      </else-if>-      <else>-        <text term="no date" form="short"/>-      </else>-    </choose>-  </macro>-  <macro name="day-month">-    <date variable="issued">-      <date-part name="month"/>-      <date-part name="day" prefix=" "/>-    </date>-  </macro>-  <macro name="collection-title">-    <choose>-      <if match="none" type="article-journal">-        <choose>-          <if match="none" is-numeric="collection-number">-            <group delimiter=", ">-              <text variable="collection-title" text-case="title"/>-              <text variable="collection-number"/>-            </group>-          </if>-          <else>-            <group delimiter=" ">-              <text variable="collection-title" text-case="title"/>-              <text variable="collection-number"/>-            </group>-          </else>-        </choose>-      </if>-    </choose>-  </macro>-  <macro name="collection-title-journal">-    <choose>-      <if type="article-journal">-        <group delimiter=" ">-          <text variable="collection-title"/>-          <text variable="collection-number"/>-        </group>-      </if>-    </choose>-  </macro>-  <macro name="event">-    <group delimiter=" ">-      <choose>-        <if variable="genre">-          <text term="presented at"/>-        </if>-        <else>-          <text term="presented at" text-case="capitalize-first"/>-        </else>-      </choose>-      <text variable="event"/>-    </group>-  </macro>-  <macro name="description">-    <choose>-      <if variable="interviewer" type="interview" match="any">-        <group delimiter=". ">-          <text macro="interviewer"/>-          <text variable="medium" text-case="capitalize-first"/>-        </group>-      </if>-      <else-if type="patent">-        <group delimiter=" " prefix=". ">-          <text variable="authority"/>-          <text variable="number"/>-        </group>-      </else-if>-      <else>-        <text variable="medium" text-case="capitalize-first" prefix=". "/>-      </else>-    </choose>-    <choose>-      <if variable="title" match="none"/>-      <else-if type="thesis personal_communication speech" match="any"/>-      <else>-        <group delimiter=" " prefix=". ">-          <text variable="genre" text-case="capitalize-first"/>-          <choose>-            <if type="report">-              <text variable="number"/>-            </if>-          </choose>-        </group>-      </else>-    </choose>-  </macro>-  <macro name="issue">-    <choose>-      <if type="legal_case">-        <text variable="authority" prefix=". "/>-      </if>-      <else-if type="speech">-        <group prefix=". " delimiter=", ">-          <group delimiter=" ">-            <text variable="genre" text-case="capitalize-first"/>-            <text macro="event"/>-          </group>-          <text variable="event-place"/>-          <text macro="day-month"/>-        </group>-      </else-if>-      <else-if type="article-newspaper article-magazine personal_communication" match="any">-        <date variable="issued" form="text" prefix=", "/>-      </else-if>-      <else-if type="patent">-        <group delimiter=", " prefix=", ">-          <group delimiter=" ">-            <!--Needs Localization-->-            <text value="filed"/>-            <date variable="submitted" form="text"/>-          </group>-          <group delimiter=" ">-            <choose>-              <if variable="issued submitted" match="all">-                <text term="and"/>-              </if>-            </choose>-            <!--Needs Localization-->-            <text value="issued"/>-            <date variable="issued" form="text"/>-          </group>-        </group>-      </else-if>-      <else-if type="article-journal" match="any"/>-      <else>-        <group prefix=". " delimiter=", ">-          <choose>-            <if type="thesis">-              <text variable="genre" text-case="capitalize-first"/>-            </if>-          </choose>-          <text macro="publisher"/>-        </group>-      </else>-    </choose>-  </macro>-  <citation et-al-min="4" et-al-use-first="1" disambiguate-add-year-suffix="true" disambiguate-add-names="true" disambiguate-add-givenname="true" givenname-disambiguation-rule="primary-name" collapse="year" after-collapse-delimiter="; ">-    <layout prefix="(" suffix=")" delimiter="; ">-      <group delimiter=", ">-        <choose>-          <if variable="issued accessed" match="any">-            <group delimiter=" ">-              <text macro="contributors-short"/>-              <text macro="date-in-text"/>-            </group>-          </if>-          <!---comma before forthcoming and n.d.-->-          <else>-            <group delimiter=", ">-              <text macro="contributors-short"/>-              <text macro="date-in-text"/>-            </group>-          </else>-        </choose>-        <text macro="point-locators"/>-      </group>-    </layout>-  </citation>-  <bibliography hanging-indent="true" et-al-min="11" et-al-use-first="7" subsequent-author-substitute="&#8212;&#8212;&#8212;" entry-spacing="0">-    <sort>-      <key macro="contributors"/>-      <key variable="issued"/>-      <key variable="title"/>-    </sort>-    <layout suffix=".">-      <group delimiter=". ">-        <text macro="contributors"/>-        <text macro="date"/>-        <text macro="title"/>-      </group>-      <text macro="description"/>-      <text macro="secondary-contributors" prefix=". "/>-      <text macro="container-title" prefix=". "/>-      <text macro="container-contributors"/>-      <text macro="edition"/>-      <text macro="locators-chapter"/>-      <text macro="collection-title-journal" prefix=", " suffix=", "/>-      <text macro="locators"/>-      <text macro="collection-title" prefix=". "/>-      <text macro="issue"/>-      <text macro="locators-article"/>-      <text macro="access" prefix=". "/>+<style xmlns="http://purl.org/net/xbiblio/csl" class="in-text" demote-non-dropping-particle="display-and-sort" page-range-format="chicago-16" version="1.0">+  <!-- This file was generated by the Style Variant Builder <https://github.com/citation-style-language/style-variant-builder>. To contribute changes, modify the template and regenerate variants. -->+  <info>+    <title>Chicago Manual of Style 18th edition (author-date)</title>+    <title-short>CMOS with Bluebook (author-date [13.102])</title-short>+    <id>http://www.zotero.org/styles/chicago-author-date</id>+    <link href="http://www.zotero.org/styles/chicago-author-date" rel="self"/>+    <link href="http://www.zotero.org/styles/chicago-notes-bibliography" rel="template"/>+    <link href="https://www.chicagomanualofstyle.org/" rel="documentation"/>+    <author>+      <name>Andrew Dunning</name>+      <uri>https://orcid.org/0000-0003-0464-5036</uri>+    </author>+    <category citation-format="author-date"/>+    <category field="anthropology"/>+    <category field="communications"/>+    <category field="generic-base"/>+    <category field="geography"/>+    <category field="history"/>+    <category field="humanities"/>+    <category field="law"/>+    <category field="linguistics"/>+    <category field="literature"/>+    <category field="philosophy"/>+    <category field="political_science"/>+    <category field="science"/>+    <category field="social_science"/>+    <category field="sociology"/>+    <category field="theology"/>+    <summary>Chicago-style source citations (with Bluebook for legal citations), author-date system</summary>+    <updated>2025-08-07T00:00:00+00:00</updated>+    <rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>+  </info>+  <locale xml:lang="en">+    <terms>+      <!-- Chicago omits 'by' from `verb-short` forms; it abbreviates only the most common roles -->+      <term name="advance-online-publication">ahead of print</term>+      <term name="anonymous">unsigned</term>+      <term form="verb-short" name="collection-editor">ed.</term>+      <term form="short" name="collection-number">+        <single>vol.</single>+        <multiple>vols.</multiple>+      </term>+      <term form="verb-short" name="compiler">comp.</term>+      <term form="verb-short" name="editor">ed.</term>+      <term form="short" name="editor-translator">+        <single>ed. and trans.</single>+        <multiple>eds. and trans.</multiple>+      </term>+      <term form="short" name="editortranslator">+        <single>ed. and trans.</single>+        <multiple>eds. and trans.</multiple>+      </term>+      <term form="verb" name="editor-translator">edited and translated by</term>+      <term form="verb" name="editortranslator">edited and translated by</term>+      <term form="verb-short" name="editor-translator">ed. and trans.</term>+      <term form="verb-short" name="editortranslator">ed. and trans.</term>+      <term form="verb-short" name="illustrator">ill.</term>+      <term form="short" name="legislation">Pub. L.</term>+      <term name="manuscript">unpublished manuscript</term>+      <term name="original-work-published">originally published as</term>+      <term form="short" name="paper-conference">paper</term>+      <!-- 'under' replaces 's.v.' from CMOS17 and earlier (CMOS18 14.130) -->+      <term name="sub-verbo">under</term>+      <term form="short" name="sub-verbo">under</term>+      <term name="timestamp">at</term>+      <term form="verb-short" name="translator">trans.</term>+    </terms>+  </locale>+  <locale xml:lang="en-GB">+    <terms>+      <!-- ensure consistency with other `en-GB` contractions -->+      <term form="short" name="collection-number">+        <single>vol.</single>+        <multiple>vols</multiple>+      </term>+      <term form="short" name="editor-translator">+        <single>ed. and trans.</single>+        <multiple>eds and trans.</multiple>+      </term>+      <term form="short" name="editortranslator">+        <single>ed. and trans.</single>+        <multiple>eds and trans.</multiple>+      </term>+    </terms>+  </locale>+  <!-- Contents:+    +       This file interprets Chicago using APA's four basic reference elements+       (cf. CMOS18 14.2, 14.64, 14.161):++        1. Author (CMOS18 13.74-86)+        2. Date (author-date system only, CMOS18 13.102)+        3. Title and descriptions (CMOS18 13.87-101)+            3.1. Title+            3.2. Description+            3.3. Identifiers (edition, contributors, volume)+        4. Source+            4.1. Serial sources+            4.2. Monographic sources+            4.3. Series+            4.4. Event+            4.5. Publisher+            4.6. Date+            4.7. Locator (including page references)+            4.8. Medium+            4.9. Archival location+            4.10. URL or persistent identifier+      +       Freeform annotations to bibliography entries: +        +        5. Notes+       +       Chicago also provides parallel rules for legal references following+       The Bluebook: A Uniform System of Citation (code shared with APA):++        6. Legal references+  -->+  <!-- In this file, macros suffixed `-bib` and `-note` are parallel versions+       of the same features for the bibliography and notes, and all changes+       must be applied to both. They should only contain differences of+       punctuation (periods in bibliography, commas in notes) and capitalization,+       except where the comments indicate structural changes. -->+  <!-- Categories of CSL item types:++       Serial+       : article-journal article-magazine article-newspaper periodical post-weblog review review-book++       Serial or Monographic+       : interview paper-conference++         Monographic with any of `collection-editor compiler editor editorial-director`.+         A serial `paper-conference` is unpublished if it lacks any of `issue page supplement-number volume`.++       Monographic+       : article book broadcast chapter classic collection dataset document+         entry entry-dictionary entry-encyclopedia event figure+         graphic manuscript map motion_picture musical_score+         pamphlet patent performance personal_communication post report+         software song speech standard thesis webpage++       Legal+       : bill hearing legal_case legislation regulation treaty+  -->+  <!-- Variable labels -->+  <macro name="label-chapter-number">+    <group delimiter=" ">+      <choose>+        <if is-numeric="chapter-number" type="song">+          <text value="track"/>+        </if>+        <else-if is-numeric="chapter-number">+          <label form="short" variable="chapter-number"/>+        </else-if>+      </choose>+      <text variable="chapter-number"/>+    </group>+  </macro>+  <macro name="label-chapter-number-capitalized">+    <group delimiter=" ">+      <choose>+        <if is-numeric="chapter-number" type="song">+          <text text-case="capitalize-first" value="track"/>+        </if>+        <else-if is-numeric="chapter-number">+          <label form="short" text-case="capitalize-first" variable="chapter-number"/>+        </else-if>+      </choose>+      <text text-case="capitalize-first" variable="chapter-number"/>+    </group>+  </macro>+  <macro name="label-collection-number">+    <group delimiter=" ">+      <choose>+        <if is-numeric="collection-number">+          <label form="short" variable="collection-number"/>+        </if>+      </choose>+      <text variable="collection-number"/>+    </group>+  </macro>+  <macro name="label-edition">+    <group delimiter=" ">+      <choose>+        <if is-numeric="edition">+          <number form="ordinal" variable="edition"/>+          <label form="short" variable="edition"/>+        </if>+        <else-if match="any" type="article-journal article-magazine article-newspaper periodical post-weblog review review-book">+          <!-- full label for serial edition (CMOS18 14.89) -->+          <text variable="edition"/>+          <label variable="edition"/>+        </else-if>+        <else-if match="any" type="interview paper-conference">+          <choose>+            <if match="any" variable="collection-editor compiler editor editorial-director">+              <!-- monographic usage -->+              <text variable="edition"/>+            </if>+            <else>+              <!-- serial usage -->+              <text variable="edition"/>+              <label variable="edition"/>+            </else>+          </choose>+        </else-if>+        <else>+          <text variable="edition"/>+        </else>+      </choose>+    </group>+  </macro>+  <macro name="label-edition-capitalized">+    <group delimiter=" ">+      <choose>+        <if is-numeric="edition">+          <number form="ordinal" variable="edition"/>+          <label form="short" variable="edition"/>+        </if>+        <else-if match="any" type="article-journal article-magazine article-newspaper periodical post-weblog review review-book">+          <!-- full label for serial edition (CMOS18 14.89) -->+          <text text-case="title" variable="edition"/>+          <label text-case="capitalize-first" variable="edition"/>+        </else-if>+        <else-if match="any" type="interview paper-conference">+          <choose>+            <if match="any" variable="collection-editor compiler editor editorial-director">+              <!-- monographic usage -->+              <text text-case="capitalize-first" variable="edition"/>+            </if>+            <else>+              <!-- serial usage -->+              <text text-case="title" variable="edition"/>+              <label text-case="capitalize-first" variable="edition"/>+            </else>+          </choose>+        </else-if>+        <else>+          <text text-case="capitalize-first" variable="edition"/>+        </else>+      </choose>+    </group>+  </macro>+  <macro name="label-issue">+    <group delimiter=" ">+      <label form="short" variable="issue"/>+      <text variable="issue"/>+    </group>+  </macro>+  <macro name="label-locator">+    <group delimiter=" ">+      <choose>+        <if locator="page"/>+        <else-if match="any" type="bill hearing legal_case legislation regulation treaty">+          <!-- Bluebook-style labels for legal types (CMOS18 14.174) -->+          <choose>+            <if locator="chapter paragraph section" match="any">+              <label form="symbol" variable="locator"/>+            </if>+            <else>+              <label form="short" variable="locator"/>+            </else>+          </choose>+        </else-if>+        <else-if is-numeric="locator">+          <choose>+            <if locator="line">+              <label variable="locator"/>+            </if>+            <else>+              <label form="short" variable="locator"/>+            </else>+          </choose>+        </else-if>+        <else-if locator="chapter line verse" match="any"/>+        <!-- a non-numeric canonical reference is identified by its formatting and does not need a label (CMOS18 14.143-54) -->+        <else>+          <label form="short" variable="locator"/>+        </else>+      </choose>+      <text variable="locator"/>+    </group>+  </macro>+  <macro name="label-number-capitalized">+    <group delimiter=" ">+      <choose>+        <if type="standard"/>+        <else-if is-numeric="number" match="any" type="legislation regulation">+          <label form="short" text-case="capitalize-first" variable="number"/>+        </else-if>+      </choose>+      <text text-case="capitalize-first" variable="number"/>+    </group>+  </macro>+  <macro name="label-number-of-volumes">+    <group delimiter=" ">+      <text variable="number-of-volumes"/>+      <choose>+        <if is-numeric="number-of-volumes">+          <label form="short" variable="number-of-volumes"/>+        </if>+      </choose>+    </group>+  </macro>+  <macro name="label-part-number">+    <group delimiter=" ">+      <choose>+        <if is-numeric="part-number">+          <!-- TODO: Replace with `part-number` label when CSL provides one -->+          <text form="short" term="part"/>+        </if>+      </choose>+      <text variable="part-number"/>+    </group>+  </macro>+  <macro name="label-part-number-capitalized">+    <group delimiter=" ">+      <choose>+        <if is-numeric="part-number">+          <!-- TODO: Replace with `part-number` label when CSL provides one -->+          <text form="short" term="part" text-case="capitalize-first"/>+        </if>+      </choose>+      <text text-case="capitalize-first" variable="part-number"/>+    </group>+  </macro>+  <macro name="label-section-capitalized">+    <group delimiter=" ">+      <choose>+        <if is-numeric="section">+          <label form="short" text-case="capitalize-first" variable="section"/>+        </if>+      </choose>+      <text text-case="title" variable="section"/>+    </group>+  </macro>+  <macro name="label-section-symbol">+    <group delimiter=" ">+      <label form="symbol" variable="section"/>+      <text variable="section"/>+    </group>+  </macro>+  <macro name="label-supplement-number">+    <group delimiter=" ">+      <choose>+        <!-- TODO: Replace with `supplement-number` label when CSL provides one -->+        <if is-numeric="supplement-number" variable="volume-title">+          <!-- if there is a volume title, it is already described as a supplement -->+          <text form="short" term="issue"/>+        </if>+        <else-if is-numeric="supplement-number" type="periodical" variable="title">+          <text form="short" term="issue"/>+        </else-if>+        <else-if is-numeric="supplement-number">+          <text form="short" term="supplement"/>+        </else-if>+      </choose>+      <text variable="supplement-number"/>+    </group>+  </macro>+  <macro name="label-version">+    <group delimiter=" ">+      <choose>+        <if type="software">+          <!-- short version label for software (CMOS18 14.169) -->+          <label form="short" variable="version"/>+        </if>+        <else>+          <label variable="version"/>+        </else>+      </choose>+      <text variable="version"/>+    </group>+  </macro>+  <macro name="label-version-capitalized">+    <group delimiter=" ">+      <choose>+        <if type="software">+          <!-- short version label for software (CMOS18 14.169) -->+          <label form="short" text-case="capitalize-first" variable="version"/>+        </if>+        <else>+          <label text-case="capitalize-first" variable="version"/>+        </else>+      </choose>+      <text variable="version"/>+    </group>+  </macro>+  <macro name="label-volume">+    <group delimiter=" ">+      <choose>+        <if is-numeric="volume">+          <label form="short" variable="volume"/>+        </if>+      </choose>+      <text variable="volume"/>+    </group>+  </macro>+  <macro name="label-volume-capitalized">+    <group delimiter=" ">+      <choose>+        <if is-numeric="volume">+          <label form="short" text-case="capitalize-first" variable="volume"/>+        </if>+      </choose>+      <text text-case="capitalize-first" variable="volume"/>+    </group>+  </macro>+  <!-- 1. Author (CMOS18 13.74-86) -->+  <macro name="author-bib">+    <names variable="composer">+      <name and="text" delimiter-precedes-last="always" name-as-sort-order="first"/>+      <label form="short" prefix=", "/>+      <substitute>+        <names variable="author"/>+        <!-- cf. `interview` model (CMOS18 14.110); if it is desired to prioritize `host` over `guest`, the latter could be encoded as a `contributor` -->+        <names variable="guest"/>+        <names variable="host"/>+        <choose>+          <if type="song">+            <names variable="performer"/>+          </if>+        </choose>+        <choose>+          <if type="classic">+            <!-- contributors fall after the title of `classic` (CMOS18 14.147) -->+            <text macro="author-title-substitute-bib"/>+          </if>+          <else-if type="entry-dictionary" variable="container-title">+            <!-- contributors fall after the title of unsigned reference entries (CMOS18 14.130) -->+            <text macro="author-title-substitute-container"/>+          </else-if>+          <else-if type="entry-encyclopedia" variable="container-title">+            <text macro="author-title-substitute-container"/>+          </else-if>+        </choose>+        <names variable="illustrator"/>+        <choose>+          <if match="none" type="standard">+            <names variable="editor-translator"/>+            <names variable="editor"/>+            <names variable="translator"/>+            <names variable="collection-editor"/>+          </if>+        </choose>+        <names variable="director"/>+        <choose>+          <!-- serial `broadcast` prioritizes title (CMOS18 14.165, 14.168) -->+          <if type="broadcast" variable="container-title number title"/>+          <else>+            <names variable="producer"/>+            <names variable="executive-producer"/>+            <names variable="series-creator"/>+            <choose>+              <if type="broadcast">+                <names variable="contributor"/>+              </if>+            </choose>+          </else>+        </choose>+        <names variable="editorial-director"/>+        <names variable="compiler"/>+        <choose>+          <if match="any" type="event performance speech">+            <names variable="chair"/>+            <names variable="organizer"/>+          </if>+        </choose>+        <names variable="curator"/>+        <choose>+          <if type="software">+            <!-- `software` listed under the name of the publisher or developer (CMOS18 14.169) -->+            <text variable="publisher"/>+          </if>+          <else-if type="standard">+            <!-- `standard` listed in bibliography under organization, but note omits this (CMOS18 14.159) -->+            <text variable="authority"/>+          </else-if>+        </choose>+        <text macro="author-title-substitute-container"/>+        <text macro="author-title-substitute-bib"/>+        <choose>+          <if type="manuscript">+            <choose>+              <if match="none" variable="container-title event-date event-place event-title genre title publisher publisher-place">+                <text macro="source-archive-bib"/>+              </if>+            </choose>+          </if>+        </choose>+      </substitute>+    </names>+  </macro>+  <macro name="author-inline">+    <choose>+      <if match="any" type="bill hearing legal_case legislation regulation treaty">+        <text macro="title-and-descriptions-short"/>+      </if>+      <else-if match="any" type="interview personal_communication">+        <text macro="author-inline-and-recipient"/>+      </else-if>+      <else>+        <names variable="composer">+          <name and="text" form="short" initialize-with=". "/>+          <substitute>+            <names variable="author"/>+            <names variable="guest"/>+            <names variable="host"/>+            <choose>+              <if type="song">+                <names variable="performer"/>+              </if>+            </choose>+            <choose>+              <if match="any" type="classic performance">+                <!-- contributors fall after the title of `classic` (CMOS18 14.147), `performance` (CMOS18 14.166) -->+                <text macro="author-title-substitute-short"/>+              </if>+              <else-if match="any" type="entry entry-dictionary entry-encyclopedia">+                <!-- contributors fall after the title of unsigned reference entries (CMOS18 14.130) -->+                <choose>+                  <if variable="container-title">+                    <text macro="author-title-substitute-container"/>+                  </if>+                </choose>+              </else-if>+            </choose>+            <names variable="illustrator"/>+            <choose>+              <if match="none" type="standard">+                <names variable="editor-translator"/>+                <names variable="editor"/>+                <names variable="translator"/>+                <names variable="collection-editor"/>+              </if>+            </choose>+            <choose>+              <if type="broadcast" variable="container-title number title"/>+              <else>+                <names variable="director"/>+                <names variable="producer"/>+                <names variable="executive-producer"/>+                <names variable="series-creator"/>+                <choose>+                  <if type="broadcast">+                    <names variable="contributor"/>+                  </if>+                </choose>+              </else>+            </choose>+            <names variable="editorial-director"/>+            <names variable="compiler"/>+            <choose>+              <if match="any" type="event performance speech">+                <names variable="chair"/>+                <names variable="organizer"/>+              </if>+            </choose>+            <names variable="curator"/>+            <choose>+              <if type="software">+                <!-- `software` listed under the name of the publisher or developer (CMOS18 14.169) -->+                <text variable="publisher"/>+              </if>+              <else-if type="standard">+                <!-- `standard` listed in bibliography under organization, but note omits this (CMOS18 14.159) -->+                <text variable="authority"/>+              </else-if>+            </choose>+            <text macro="author-title-substitute-container-short"/>+            <text macro="author-title-substitute-short"/>+            <choose>+              <if type="manuscript">+                <choose>+                  <if match="none" variable="container-title event-date event-place event-title genre title publisher publisher-place">+                    <text macro="source-archive-note"/>+                  </if>+                </choose>+              </if>+            </choose>+          </substitute>+        </names>+      </else>+    </choose>+  </macro>+  <macro name="author-sort">+    <choose>+      <if match="any" type="bill hearing legal_case legislation regulation treaty">+        <text macro="legal-title"/>+      </if>+      <else>+        <text macro="author-bib"/>+      </else>+    </choose>+  </macro>+  <!-- Author elements -->+  <macro name="author-inline-and-recipient">+    <!-- identical to `author-short-and-recipient` but with initialization -->+    <group delimiter=" ">+      <choose>+        <!-- Inaccessible personal commmunication is cited in-text (CMOS18 14.111) -->+        <if match="none" variable="archive archive-place container-title DOI number publisher references URL">+          <!-- These variables indicate whether the letter is retrievable by the reader -->+          <group delimiter=", ">+            <names variable="author">+              <name and="text" initialize-with=". "/>+              <substitute>+                <text macro="title-and-descriptions-short"/>+              </substitute>+            </names>+          </group>+          <choose>+            <if match="none" variable="genre">+              <names variable="recipient">+                <label form="verb" suffix=" "/>+                <name and="text" initialize-with=". "/>+              </names>+            </if>+          </choose>+        </if>+        <else-if variable="author recipient">+          <names variable="author">+            <label/>+            <name and="text" form="short" initialize-with=". "/>+          </names>+          <choose>+            <if match="none" variable="genre">+              <names variable="recipient">+                <label form="verb" suffix=" "/>+                <name and="text" form="short" initialize-with=". "/>+              </names>+            </if>+          </choose>+        </else-if>+        <else>+          <names variable="author">+            <name and="text" form="short" initialize-with=". "/>+            <substitute>+              <text macro="title-and-descriptions-short"/>+            </substitute>+          </names>+        </else>+      </choose>+    </group>+  </macro>+  <macro name="author-title-substitute-bib">+    <choose>+      <if match="any" type="review review-book" variable="reviewed-author reviewed-genre reviewed-title">+        <!-- If a review has no `reviewed-genre` or `reviewed-title`, assume that `title` contains the title of the reviewed work; the description provides it. -->+        <choose>+          <if variable="reviewed-genre title">+            <text macro="title-bib"/>+          </if>+          <else-if variable="reviewed-genre reviewed-title title">+            <text macro="title-bib"/>+          </else-if>+          <else>+            <text macro="title-and-descriptions-bib"/>+          </else>+        </choose>+      </if>+      <else-if variable="title">+        <text macro="title-bib"/>+      </else-if>+      <else>+        <!-- If an item has no `title`, substitute with descriptions. -->+        <text macro="title-and-descriptions-bib"/>+      </else>+    </choose>+  </macro>+  <macro name="author-title-substitute-short">+    <choose>+      <if match="any" type="review review-book" variable="reviewed-author reviewed-genre reviewed-title">+        <!-- If a review has no `reviewed-genre` or `reviewed-title`, assume that `title` contains the title of the reviewed work; the description provides it. -->+        <choose>+          <if variable="reviewed-genre title">+            <text macro="title-short"/>+          </if>+          <else-if variable="reviewed-genre reviewed-title title">+            <text macro="title-short"/>+          </else-if>+          <else>+            <text macro="title-and-descriptions-short"/>+          </else>+        </choose>+      </if>+      <else-if variable="title">+        <text macro="title-short"/>+      </else-if>+      <else>+        <!-- If an item has no `title`, substitute with descriptions and capitalize -->+        <text macro="title-and-descriptions-bib"/>+      </else>+    </choose>+  </macro>+  <macro name="author-title-substitute-container">+    <choose>+      <if match="none" variable="container-title"/>+      <else-if match="any" type="article-magazine article-newspaper">+        <!-- Anonymous magazine and newspaper articles substitute name of publication (CMOS18 14.87, 14.97) -->+        <text macro="source-serial-name"/>+      </else-if>+      <else-if match="any" type="review review-book" variable="reviewed-author reviewed-genre reviewed-title">+        <!-- Publication name also substituted for unsigned reviews (CMOS18 14.102) -->+        <text macro="source-serial-name"/>+      </else-if>+      <else-if match="any" type="interview paper-conference">+        <choose>+          <if match="none" variable="collection-editor compiler editor editorial-director">+            <!-- serial usage -->+            <text macro="source-serial-name"/>+          </if>+        </choose>+      </else-if>+      <else-if match="any" type="entry entry-dictionary entry-encyclopedia">+        <!-- Anonymous entries in reference works (CMOS18 14.130) -->+        <text font-style="italic" text-case="title" variable="container-title"/>+      </else-if>+      <else-if type="broadcast">+        <!-- TV broadcasts and podcasts (CMOS18 14.165, 14.168) -->+        <text font-style="italic" text-case="title" variable="container-title"/>+      </else-if>+      <else-if type="webpage">+        <!-- Website title substituted in bibliography only (CMOS18 14.104) -->+        <text text-case="title" variable="container-title"/>+      </else-if>+    </choose>+  </macro>+  <macro name="author-title-substitute-container-short">+    <choose>+      <if match="none" variable="container-title"/>+      <else-if match="any" type="article-magazine article-newspaper">+        <!-- Anonymous magazine/newspaper articles substitute name of publication (CMOS18 14.87, 14.97) -->+        <text font-style="italic" text-case="title" variable="container-title"/>+      </else-if>+      <else-if match="any" type="review review-book" variable="reviewed-author reviewed-genre reviewed-title">+        <!-- Publication name also substituted for unsigned reviews (CMOS18 14.102) -->+        <text font-style="italic" text-case="title" variable="container-title"/>+      </else-if>+      <else-if match="any" type="interview paper-conference">+        <choose>+          <if match="none" variable="collection-editor compiler editor editorial-director">+            <!-- serial usage -->+            <text font-style="italic" text-case="title" variable="container-title"/>+          </if>+        </choose>+      </else-if>+      <else-if match="any" type="entry entry-dictionary entry-encyclopedia">+        <!-- Anonymous entries in reference works (CMOS18 14.130) -->+        <text font-style="italic" text-case="title" variable="container-title"/>+      </else-if>+      <else-if type="broadcast">+        <!-- TV broadcasts and podcasts (CMOS18 14.165, 14.168) -->+        <text font-style="italic" text-case="title" variable="container-title"/>+      </else-if>+      <else-if type="webpage">+        <!-- Website title substituted in bibliography only (CMOS18 14.104) -->+        <text text-case="title" variable="container-title"/>+      </else-if>+    </choose>+  </macro>+  <!-- 2. Date (CMOS18 13.102) -->+  <macro name="date">+    <choose>+      <if variable="issued">+        <group delimiter=" ">+          <!-- reprints and earlier editions may give original year in brackets (CMOS18 14.16) -->+          <text macro="date-original-year" prefix="(" suffix=")"/>+          <group>+            <text macro="date-issued-year"/>+            <text variable="year-suffix"/>+          </group>+        </group>+      </if>+      <else-if variable="available-date">+        <date date-parts="year" form="text" variable="available-date"/>+      </else-if>+      <else-if variable="event-date">+        <text macro="date-event-year"/>+      </else-if>+      <else-if variable="status">+        <group>+          <!-- Print the status variable rather than use generic CSL terms (`in press`, etc.) -->+          <text text-case="capitalize-first" variable="status"/>+          <text prefix="-" variable="year-suffix"/>+        </group>+      </else-if>+      <else-if type="collection">+        <!-- do not give n.d. for archival collections (CMOS18 14.128) -->+        <text prefix="-" variable="year-suffix"/>+      </else-if>+      <else-if type="manuscript">+        <!-- do not give n.d. with a bare shelfmark -->+        <choose>+          <if match="any" variable="container-title event-date event-place event-title genre title publisher publisher-place">+            <text form="short" term="no date"/>+            <text prefix="-" variable="year-suffix"/>+          </if>+        </choose>+      </else-if>+      <else>+        <text form="short" term="no date"/>+        <text prefix="-" variable="year-suffix"/>+      </else>+    </choose>+  </macro>+  <macro name="date-short">+    <choose>+      <if variable="issued">+        <group delimiter=" ">+          <choose>+            <if is-uncertain-date="original-date">+              <!-- Uncertain date already has square brackets -->+              <text macro="date-original-year"/>+            </if>+            <else>+              <text macro="date-original-year" prefix="[" suffix="]"/>+            </else>+          </choose>+          <group>+            <choose>+              <if match="any" type="interview personal_communication">+                <choose>+                  <if match="any" variable="archive archive-place container-title DOI number publisher references URL">+                    <!-- These variables indicate that the communication is retrievable by the reader. If not, then use the in-text-only personal communication format -->+                    <text macro="date-issued-year"/>+                  </if>+                  <else>+                    <text macro="date-issued-full"/>+                  </else>+                </choose>+              </if>+              <else>+                <text macro="date-issued-year"/>+              </else>+            </choose>+            <text variable="year-suffix"/>+          </group>+        </group>+      </if>+      <else-if variable="available-date">+        <date date-parts="year" form="text" variable="available-date"/>+      </else-if>+      <else-if variable="event-date">+        <text macro="date-event-year"/>+      </else-if>+      <else-if variable="status">+        <!-- Print the status variable rather than use generic CSL terms (`in press`, etc.) -->+        <text text-case="lowercase" variable="status"/>+        <text prefix="-" variable="year-suffix"/>+      </else-if>+      <else-if match="any" type="interview personal_communication">+        <choose>+          <if match="any" variable="archive archive-place container-title DOI number publisher references URL">+            <!-- only give n.d. for accessible personal communication (CMOS18 14.111)-->+            <text form="short" term="no date"/>+          </if>+        </choose>+        <text prefix="-" variable="year-suffix"/>+      </else-if>+      <else-if match="any" type="classic collection entry entry-dictionary entry-encyclopedia">+        <!-- do not give n.d. for archival collections (CMOS18 14.128), `classic` (CMOS18 14.143), or reference entries (CMOS18 14.131) -->+        <text prefix="-" variable="year-suffix"/>+      </else-if>+      <else-if type="manuscript">+        <!-- do not give n.d. with a bare shelfmark -->+        <choose>+          <if match="any" variable="container-title event-date event-place event-title genre title publisher publisher-place">+            <text form="short" term="no date"/>+            <text prefix="-" variable="year-suffix"/>+          </if>+        </choose>+      </else-if>+      <else>+        <text form="short" term="no date"/>+        <text prefix="-" variable="year-suffix"/>+      </else>+    </choose>+  </macro>+  <macro name="date-sort-group">+    <!-- Sort items with and without dates (CMOS18 14.44):++          1. items with dates (= 0)+          2. `no date` items (= 1)+          3. items with `status` (forthcoming, in press, etc.) (= 2) -->+    <choose>+      <if variable="issued">+        <text value="0"/>+      </if>+      <else-if variable="status">+        <text value="2"/>+      </else-if>+      <else>+        <!-- n.d. -->+        <text value="1"/>+      </else>+    </choose>+  </macro>+  <macro name="date-sort-year">+    <!-- while reference lists are to be sorted chronologically (CMOS18 13.112), it appears that only the year is to be taken into account (CMOS18 13.114) -->+    <choose>+      <if type="personal_communication" variable="event-date issued">+        <date date-parts="year" form="text" variable="event-date"/>+      </if>+      <else>+        <text macro="date-issued-year"/>+      </else>+    </choose>+  </macro>+  <!-- Date elements -->+  <macro name="date-event-full">+    <choose>+      <if is-uncertain-date="issued">+        <!-- guessed-at date (CMOS18 14.44) -->+        <date form="text" prefix="[" suffix="?]" variable="event-date"/>+      </if>+      <else>+        <date form="text" variable="event-date"/>+      </else>+    </choose>+  </macro>+  <macro name="date-event-year">+    <choose>+      <if is-uncertain-date="issued">+        <!-- guessed-at date (CMOS18 14.44) -->+        <date date-parts="year" form="text" prefix="[" suffix="?]" variable="event-date"/>+      </if>+      <else>+        <date date-parts="year" form="text" variable="event-date"/>+      </else>+    </choose>+  </macro>+  <macro name="date-issued-full">+    <choose>+      <if is-uncertain-date="issued">+        <!-- guessed-at date (CMOS18 14.44) -->+        <date form="text" prefix="[" suffix="?]" variable="issued"/>+      </if>+      <else>+        <date form="text" variable="issued"/>+      </else>+    </choose>+  </macro>+  <macro name="date-issued-month">+    <date variable="issued">+      <date-part name="month"/>+    </date>+  </macro>+  <macro name="date-issued-month-day">+    <date variable="issued">+      <date-part name="month"/>+      <date-part name="day" prefix=" "/>+    </date>+  </macro>+  <macro name="date-issued-year">+    <choose>+      <if is-uncertain-date="issued">+        <!-- guessed-at date (CMOS18 14.44) -->+        <date date-parts="year" form="text" prefix="[" suffix="?]" variable="issued"/>+      </if>+      <else>+        <date date-parts="year" form="text" variable="issued"/>+      </else>+    </choose>+  </macro>+  <macro name="date-original-month">+    <date variable="original-date">+      <date-part name="month"/>+    </date>+  </macro>+  <macro name="date-original-month-day">+    <date variable="original-date">+      <date-part name="month"/>+      <date-part name="day" prefix=" "/>+    </date>+  </macro>+  <macro name="date-original-year">+    <choose>+      <if is-uncertain-date="original-date">+        <date date-parts="year" form="text" prefix="[" suffix="?]" variable="original-date"/>+      </if>+      <else>+        <date date-parts="year" form="text" variable="original-date"/>+      </else>+    </choose>+  </macro>+  <!-- 3. Title and descriptions (CMOS18 13.87-101) -->+  <macro name="title-and-descriptions-bib">+    <group delimiter=". ">+      <choose>+        <if variable="title">+          <text macro="title-bib"/>+          <text macro="description-bib"/>+          <text macro="identifier-bib"/>+        </if>+        <else-if match="any" type="bill report">+          <!-- Bills, resolutions, and congressional reports substitute bill number if no title -->+          <!-- Congressional reports are indistinguishable from other reports -->+          <text macro="identifier-number-bib"/>+          <text macro="identifier-bib"/>+          <text macro="description-bib"/>+        </else-if>+        <else>+          <text macro="description-bib"/>+          <text macro="identifier-bib"/>+        </else>+      </choose>+    </group>+  </macro>+  <macro name="title-and-descriptions-short">+    <choose>+      <if variable="title">+        <text macro="title-short"/>+      </if>+      <else-if match="any" type="bill report">+        <!-- Bills, resolutions, and congressional reports substitute bill number if no title -->+        <text macro="legal-identifier-bill-report"/>+      </else-if>+      <else>+        <text macro="description-short"/>+      </else>+    </choose>+  </macro>+  <macro name="title-and-source-bib">+    <group delimiter=". ">+      <choose>+        <if type="broadcast" variable="container-title number title">+          <!-- Bespoke `broadcast` format (CMOS18 14.165, 14.168) -->+          <text macro="source-monographic-title-bib"/>+          <group delimiter=", ">+            <text macro="identifier-number-bib"/>+            <text macro="title-bib"/>+            <text macro="description-bib"/>+            <text macro="source-monographic-identifier-contributors-bib"/>+          </group>+          <text macro="source-series-bib"/>+          <choose>+            <!-- show event information here only if not collapsed with `issued` (CMOS18 14.167) -->+            <if match="any" variable="event-date original-date original-publisher original-publisher-place publisher status">+              <text macro="source-event-bib"/>+            </if>+          </choose>+        </if>+        <else-if type="chapter" variable="container-title genre">+          <!-- 'Introduction to' etc. (CMOS18 14.12, 14.14) -->+          <group delimiter=" ">+            <text macro="title-and-descriptions-bib"/>+            <text macro="source-bib"/>+          </group>+        </else-if>+        <else>+          <text macro="title-and-descriptions-bib"/>+          <text macro="source-bib"/>+        </else>+      </choose>+      <group delimiter=", ">+        <choose>+          <!-- show event information here only if collapsed with `issued` (CMOS18 14.167) -->+          <if match="any" variable="event-date original-date original-publisher original-publisher-place publisher status"/>+          <!-- monographic usage only -->+          <else-if match="any" type="article-journal article-magazine article-newspaper periodical post-weblog review review-book"/>+          <else-if match="any" type="interview paper-conference">+            <choose>+              <if match="any" variable="collection-editor container-author editor editorial-director">+                <!-- monographic usage -->+                <text macro="source-event-bib"/>+              </if>+            </choose>+          </else-if>+          <else>+            <text macro="source-event-bib"/>+          </else>+        </choose>+        <text macro="source-monographic-publication-bib"/>+      </group>+      <text macro="source-medium-bib"/>+      <text macro="source-archive-bib"/>+      <text macro="source-date-accessed-DOI-URL-bib"/>+    </group>+  </macro>+  <!-- 3.1. Title -->+  <macro name="title-bib">+    <choose>+      <if match="any" type="post webpage">+        <!-- Handle `container-title` on `post` or `webpage` in manner of `publisher` -->+        <text macro="title-and-part-filter-review-bib"/>+      </if>+      <else-if match="any" type="article-journal article-magazine article-newspaper periodical post-weblog review review-book">+        <text macro="title-and-part-filter-review-bib"/>+      </else-if>+      <else-if match="any" type="interview paper-conference">+        <choose>+          <if match="any" variable="collection-editor compiler editor editorial-director">+            <!-- monographic usage -->+            <text macro="title-monographic-bib"/>+          </if>+          <else>+            <!-- serial usage -->+            <text macro="title-and-part-filter-review-bib"/>+          </else>+        </choose>+      </else-if>+      <else>+        <text macro="title-monographic-bib"/>+      </else>+    </choose>+  </macro>+  <macro name="title-short">+    <choose>+      <if match="any" type="review review-book" variable="reviewed-author reviewed-genre reviewed-title">+        <!-- If a review has no `reviewed-title`, assume that `title` contains the title of the reviewed work; the description provides it. -->+        <choose>+          <if variable="reviewed-genre title">+            <!-- Quotes, title case -->+            <text form="short" quotes="true" text-case="title" variable="title"/>+          </if>+          <else-if variable="reviewed-genre reviewed-title title">+            <!-- Quotes, title case -->+            <text form="short" quotes="true" text-case="title" variable="title"/>+          </else-if>+          <else>+            <text macro="description-short"/>+          </else>+        </choose>+      </if>+      <else>+        <text macro="title-primary-short"/>+      </else>+    </choose>+  </macro>+  <!-- Title elements -->+  <macro name="title-and-part-filter-review-bib">+    <choose>+      <if match="any" type="review review-book" variable="reviewed-author reviewed-genre reviewed-title">+        <!-- `title` is only the review title if there is a separate `reviewed-genre` or `reviewed-title`; otherwise, it is the title of the reviewed work, printed in the description -->+        <choose>+          <if match="any" variable="reviewed-genre reviewed-title">+            <text macro="title-and-part-title-bib"/>+          </if>+        </choose>+      </if>+      <else>+        <text macro="title-and-part-title-bib"/>+      </else>+    </choose>+  </macro>+  <macro name="title-and-part-title-bib">+    <group delimiter=". ">+      <text macro="title-primary"/>+      <group delimiter=", ">+        <text macro="label-part-number-capitalized"/>+        <text macro="title-part"/>+      </group>+    </group>+  </macro>+  <macro name="title-monographic-bib">+    <!-- For monographic items, assume `part-number` and `part-title` refer to the book/volume. -->+    <!-- There is no `title-monographic-note` as notes always open with the primary title. -->+    <choose>+      <if variable="container-title">+        <text macro="title-primary"/>+      </if>+      <!-- For monographic items without `container-title`, bibliography entries list `part-title` or `volume-title` first if available -->+      <else-if variable="part-title">+        <text macro="title-part"/>+      </else-if>+      <else-if variable="volume-title">+        <text font-style="italic" text-case="title" variable="volume-title"/>+      </else-if>+      <else>+        <text macro="title-primary"/>+      </else>+    </choose>+  </macro>+  <macro name="title-part">+    <choose>+      <if type="patent">+        <!-- No italics or quotes, sentence case -->+        <text form="short" text-case="capitalize-first" variable="part-title"/>+      </if>+      <else-if match="any" type="bill collection legislation regulation treaty">+        <!-- No italics or quotes, title case -->+        <text text-case="title" variable="part-title"/>+      </else-if>+      <else-if type="legal_case">+        <!-- Italicized, sentence case -->+        <text font-style="italic" variable="part-title"/>+      </else-if>+      <else-if match="any" type="book classic graphic hearing map">+        <!-- Italicized, title case (regardless of `container-title`) -->+        <text font-style="italic" text-case="title" variable="part-title"/>+      </else-if>+      <else-if type="entry-encyclopedia" variable="author container-title">+        <!-- Signed encyclopedia entry in quotes, title case (CMOS18 14.132) -->+        <text quotes="true" text-case="title" variable="part-title"/>+      </else-if>+      <else-if type="entry-dictionary" variable="container-title">+        <!-- Quotes, sentence case -->+        <text quotes="true" variable="part-title"/>+      </else-if>+      <else-if type="entry-encyclopedia" variable="container-title">+        <!-- Quotes, sentence case -->+        <text quotes="true" variable="part-title"/>+      </else-if>+      <else-if type="post">+        <!-- Quotes, sentence case -->+        <text quotes="true" variable="part-title"/>+      </else-if>+      <!-- Other types are formatted based on presence of `container-title` -->+      <else-if variable="container-title">+        <!-- Quotes, title case -->+        <text quotes="true" text-case="title" variable="part-title"/>+      </else-if>+      <else-if match="any" type="article dataset document interview manuscript paper-conference personal_communication speech thesis webpage">+        <!-- Container-like but not necessarily with `container-title` -->+        <!-- Quotes, title case -->+        <text quotes="true" text-case="title" variable="part-title"/>+      </else-if>+      <else>+        <!-- Italicized, title case (default) -->+        <text font-style="italic" text-case="title" variable="part-title"/>+      </else>+    </choose>+  </macro>+  <macro name="title-primary">+    <choose>+      <if type="patent">+        <!-- No italics or quotes, sentence case -->+        <text form="short" text-case="capitalize-first" variable="title"/>+      </if>+      <else-if match="any" type="bill collection legislation regulation treaty">+        <!-- No italics or quotes, title case -->+        <text text-case="title" variable="title"/>+      </else-if>+      <else-if type="legal_case">+        <!-- Italicized, sentence case -->+        <text font-style="italic" variable="title"/>+      </else-if>+      <else-if match="any" type="book classic graphic hearing map">+        <!-- Italicized, title case (regardless of `container-title`) -->+        <text font-style="italic" text-case="title" variable="title"/>+      </else-if>+      <else-if type="entry-encyclopedia" variable="author container-title">+        <!-- Signed encyclopedia entry in quotes, title case (CMOS18 14.132) -->+        <text quotes="true" text-case="title" variable="title"/>+      </else-if>+      <else-if type="entry-dictionary" variable="container-title">+        <!-- Quotes, sentence case -->+        <text quotes="true" variable="title"/>+      </else-if>+      <else-if type="entry-encyclopedia" variable="container-title">+        <!-- Quotes, sentence case -->+        <text quotes="true" variable="title"/>+      </else-if>+      <else-if type="post">+        <!-- Quotes, sentence case -->+        <text quotes="true" variable="title"/>+      </else-if>+      <!-- Other types are formatted based on presence of `container-title` -->+      <else-if variable="container-title">+        <!-- Quotes, title case -->+        <text quotes="true" text-case="title" variable="title"/>+      </else-if>+      <else-if match="any" type="article dataset document interview manuscript paper-conference personal_communication speech thesis webpage">+        <!-- Container-like but not necessarily with `container-title` -->+        <!-- Quotes, title case -->+        <text quotes="true" text-case="title" variable="title"/>+      </else-if>+      <else>+        <!-- Italicized, title case (default) -->+        <text font-style="italic" text-case="title" variable="title"/>+      </else>+    </choose>+  </macro>+  <macro name="title-primary-short">+    <choose>+      <if type="patent">+        <!-- No italics or quotes, sentence case -->+        <text form="short" text-case="capitalize-first" variable="title"/>+      </if>+      <else-if match="any" type="bill collection legislation regulation treaty">+        <!-- No italics or quotes, title case -->+        <text form="short" text-case="title" variable="title"/>+      </else-if>+      <else-if type="legal_case">+        <!-- Italicized, sentence case -->+        <text font-style="italic" form="short" variable="title"/>+      </else-if>+      <else-if match="any" type="book classic graphic hearing map">+        <!-- Italicized, title case (regardless of `container-title`) -->+        <text font-style="italic" form="short" text-case="title" variable="title"/>+      </else-if>+      <else-if type="entry-encyclopedia" variable="author container-title">+        <!-- Signed encyclopedia entry in quotes, title case (CMOS18 14.132) -->+        <text form="short" quotes="true" text-case="title" variable="title"/>+      </else-if>+      <else-if type="entry-dictionary" variable="container-title">+        <!-- Quotes, sentence case -->+        <text form="short" quotes="true" variable="title"/>+      </else-if>+      <else-if type="entry-encyclopedia" variable="container-title">+        <!-- Quotes, sentence case -->+        <text form="short" quotes="true" variable="title"/>+      </else-if>+      <else-if type="post">+        <!-- Quotes, sentence case -->+        <text form="short" quotes="true" variable="title"/>+      </else-if>+      <!-- Other types are formatted based on presence of `container-title` -->+      <else-if variable="container-title">+        <!-- Quotes, title case -->+        <text form="short" quotes="true" text-case="title" variable="title"/>+      </else-if>+      <else-if match="any" type="article dataset document interview manuscript paper-conference personal_communication speech thesis webpage">+        <!-- Container-like but not necessarily with `container-title` -->+        <!-- Quotes, title case -->+        <text form="short" quotes="true" text-case="title" variable="title"/>+      </else-if>+      <else>+        <!-- Italicized, title case (default) -->+        <text font-style="italic" form="short" text-case="title" variable="title"/>+      </else>+    </choose>+  </macro>+  <!-- 3.2. Description -->+  <macro name="description-bib">+    <choose>+      <if match="any" type="interview" variable="interviewer">+        <text macro="description-interview-bib"/>+      </if>+      <else-if match="any" type="review review-book" variable="reviewed-author reviewed-genre reviewed-title">+        <text macro="description-review-bib"/>+      </else-if>+      <else-if type="personal_communication">+        <text macro="description-letter-bib"/>+      </else-if>+      <else-if match="any" type="article-journal article-magazine article-newspaper periodical post-weblog review review-book">+        <text macro="description-serial-bib"/>+      </else-if>+      <else-if type="paper-conference">+        <text macro="description-paper-conference-bib"/>+      </else-if>+      <else-if type="song" variable="composer">+        <text macro="description-song-bib"/>+      </else-if>+      <!-- thesis type appears with university name (CMOS18 14.113) -->+      <else-if type="thesis"/>+      <else-if match="none" variable="container-title">+        <!-- Other description -->+        <text macro="description-format-bib"/>+      </else-if>+      <else>+        <text macro="description-generic-bib"/>+      </else>+    </choose>+  </macro>+  <macro name="description-short">+    <choose>+      <if match="any" type="interview" variable="interviewer">+        <text macro="description-interview-short"/>+      </if>+      <else-if match="any" type="review review-book" variable="reviewed-author reviewed-genre reviewed-title">+        <text macro="description-review-short"/>+      </else-if>+      <else-if type="personal_communication">+        <text macro="description-letter-short"/>+      </else-if>+      <else-if match="any" type="article-journal article-magazine article-newspaper periodical post-weblog review review-book">+        <text macro="description-serial-short"/>+      </else-if>+      <else-if type="paper-conference">+        <choose>+          <if match="any" variable="collection-editor container-author editor editorial-director">+            <!-- monographic usage -->+            <text macro="description-format-short"/>+          </if>+          <else>+            <!-- serial usage -->+            <text macro="description-serial-short"/>+          </else>+        </choose>+      </else-if>+      <else>+        <text macro="description-format-short"/>+      </else>+    </choose>+  </macro>+  <!-- Description elements -->+  <macro name="description-format-bib">+    <choose>+      <if variable="genre number"/>+      <else-if variable="genre">+        <text text-case="capitalize-first" variable="genre"/>+      </else-if>+      <else-if type="manuscript">+        <!-- 'unpublished manuscript' if no `genre` (CMOS18 14.114) -->+        <choose>+          <if match="none" variable="archive archive-place container-title DOI number publisher references URL">+            <text term="manuscript" text-case="capitalize-first"/>+          </if>+        </choose>+      </else-if>+      <else-if type="personal_communication">+        <!-- 'personal communication' if no `genre` (CMOS18 14.111) -->+        <choose>+          <if match="none" variable="archive archive-place container-title DOI number publisher references URL">+            <text term="personal-communication" text-case="capitalize-first"/>+          </if>+        </choose>+      </else-if>+    </choose>+  </macro>+  <macro name="description-format-short">+    <choose>+      <if variable="genre">+        <text variable="genre"/>+      </if>+      <else-if variable="medium">+        <text variable="medium"/>+      </else-if>+      <else-if type="manuscript">+        <!-- 'unpublished manuscript' if no `genre` (CMOS18 14.114) -->+        <choose>+          <if match="none" variable="archive archive-place container-title DOI number publisher references URL">+            <text term="manuscript"/>+          </if>+        </choose>+      </else-if>+      <else-if type="personal_communication">+        <!-- 'pers. comm.' if no `genre` (CMOS18 14.111) -->+        <choose>+          <if match="none" variable="archive archive-place container-title DOI number publisher references URL">+            <text form="short" term="personal-communication"/>+          </if>+        </choose>+      </else-if>+      <else-if variable="chapter-number">+        <text macro="label-chapter-number"/>+      </else-if>+    </choose>+  </macro>+  <macro name="description-generic-bib">+    <!-- For conference presentations/performances/events, chapters in reports/standards/generic documents, software, place description within the source element -->+    <choose>+      <if match="any" type="event paper-conference performance speech">+        <choose>+          <if match="any" variable="collection-editor compiler editor editorial-director">+            <!-- monographic usage -->+            <text macro="description-format-bib"/>+          </if>+        </choose>+      </if>+      <else-if match="none" type="document report software standard">+        <text macro="description-format-bib"/>+      </else-if>+    </choose>+  </macro>+  <macro name="description-interview-bib">+    <group delimiter=", ">+      <choose>+        <if variable="genre number">+          <!-- `genre` printed with `number` -->+          <names variable="interviewer">+            <label form="verb" suffix=" " text-case="capitalize-first"/>+            <name and="text"/>+          </names>+        </if>+        <else-if variable="genre">+          <group delimiter=" ">+            <text text-case="capitalize-first" variable="genre"/>+            <group delimiter=" ">+              <text form="verb" term="container-author"/>+              <names variable="interviewer"/>+            </group>+          </group>+        </else-if>+        <else-if variable="interviewer">+          <names variable="interviewer">+            <label form="verb" suffix=" " text-case="capitalize-first"/>+            <name and="text"/>+          </names>+        </else-if>+        <else>+          <text macro="description-format-bib"/>+        </else>+      </choose>+      <text macro="source-event-place-first"/>+    </group>+  </macro>+  <macro name="description-interview-short">+    <choose>+      <if disambiguate="true">+        <names variable="interviewer">+          <label form="verb" suffix=" "/>+          <name and="text"/>+          <substitute>+            <text macro="description-format-short"/>+          </substitute>+        </names>+      </if>+      <else-if match="any" variable="genre medium">+        <choose>+          <if match="none" variable="author chair collection-editor compiler composer curator director editor editor-translator editorial-director executive-producer guest host illustrator organizer producer series-creator translator">+            <!-- capitalize if no author or title -->+            <text macro="description-format-bib"/>+          </if>+          <else>+            <text macro="description-format-short"/>+          </else>+        </choose>+      </else-if>+      <else>+        <!-- generic description for an unpublished interview (CMOS18 14.108) -->+        <text term="interview"/>+      </else>+    </choose>+  </macro>+  <macro name="description-letter-bib">+    <choose>+      <if variable="recipient">+        <group delimiter=", ">+          <choose>+            <if variable="genre number">+              <!-- `genre` appears with `number` -->+              <names variable="recipient">+                <label form="verb" suffix=" " text-case="capitalize-first"/>+                <name and="text"/>+              </names>+            </if>+            <else-if variable="genre">+              <group delimiter=" ">+                <text macro="description-format-bib"/>+                <names variable="recipient">+                  <label form="verb" suffix=" "/>+                  <name and="text"/>+                </names>+              </group>+            </else-if>+            <else>+              <names variable="recipient">+                <label form="verb" suffix=" " text-case="capitalize-first"/>+                <name and="text"/>+              </names>+            </else>+          </choose>+          <text variable="event-place"/>+          <text macro="date-event-full"/>+        </group>+      </if>+      <else>+        <text macro="description-format-bib"/>+      </else>+    </choose>+  </macro>+  <macro name="description-letter-short">+    <!-- shortened notes ideally give author, recipient, place, and date (CMOS18 14.13) -->+    <group delimiter=", ">+      <choose>+        <if variable="genre recipient">+          <group delimiter=" ">+            <text macro="description-format-short"/>+            <names variable="recipient">+              <label form="verb" suffix=" "/>+              <name and="text"/>+            </names>+          </group>+        </if>+        <else>+          <text macro="description-format-short"/>+        </else>+      </choose>+      <text variable="event-place"/>+      <text macro="date-event-full"/>+    </group>+  </macro>+  <macro name="description-paper-conference-bib">+    <choose>+      <if match="any" variable="collection-editor container-author editor editorial-director">+        <!-- monographic usage -->+        <text macro="description-generic-bib"/>+      </if>+      <else>+        <!-- serial usage -->+        <group delimiter=". ">+          <text macro="description-serial-bib"/>+          <text macro="source-event-bib"/>+        </group>+      </else>+    </choose>+  </macro>+  <macro name="description-review-bib">+    <!-- Reviewed item -->+    <group delimiter=". ">+      <group delimiter=", ">+        <group delimiter=" ">+          <text macro="description-review-genre-bib"/>+          <text macro="description-review-title"/>+        </group>+        <choose>+          <if variable="reviewed-genre reviewed-title title">+            <names variable="reviewed-author">+              <label form="verb" suffix=" "/>+              <name and="text"/>+            </names>+          </if>+          <else-if variable="reviewed-genre"/>+          <else>+            <names variable="reviewed-author">+              <label form="verb" suffix=" "/>+              <name and="text"/>+            </names>+          </else>+        </choose>+        <text macro="source-event-place-first"/>+      </group>+      <text macro="label-section-capitalized"/>+    </group>+  </macro>+  <macro name="description-review-genre-bib">+    <choose>+      <if variable="reviewed-genre">+        <group delimiter=" ">+          <text macro="description-review-term-unsigned-bib"/>+          <text variable="reviewed-genre"/>+          <choose>+            <if match="none" variable="reviewed-title">+              <names variable="reviewed-author">+                <label form="verb" suffix=" "/>+                <name and="text"/>+              </names>+            </if>+          </choose>+        </group>+      </if>+      <else-if variable="number">+        <text macro="description-review-term-unsigned-bib"/>+      </else-if>+      <!-- If no `reviewed-genre`, assume that `genre` is entered as 'Review of the book' or similar -->+      <else-if variable="genre">+        <text text-case="capitalize-first" variable="genre"/>+      </else-if>+      <else>+        <text macro="description-review-term-unsigned-bib"/>+      </else>+    </choose>+  </macro>+  <macro name="description-review-short">+    <group delimiter=" ">+      <text term="review-of"/>+      <text macro="description-review-title-short"/>+    </group>+  </macro>+  <macro name="description-review-term-unsigned-bib">+    <!-- Anonymous reviews appear as 'unsigned' (CMOS18 14.102) -->+    <choose>+      <if match="any" variable="author chair collection-editor compiler composer curator director editor editor-translator editorial-director executive-producer guest host illustrator organizer producer series-creator translator">+        <text term="review-of" text-case="capitalize-first"/>+      </if>+      <else>+        <group delimiter=" ">+          <text term="anonymous" text-case="capitalize-first"/>+          <text term="review-of"/>+        </group>+      </else>+    </choose>+  </macro>+  <macro name="description-review-title">+    <choose>+      <if match="any" variable="reviewed-genre reviewed-title">+        <!-- Not possible to distinguish TV series episode from other reviewed works without a reviewed source title -->+        <!-- Adapt for `reviewed-container-title` or similar if it becomes available -->+        <text font-style="italic" text-case="title" variable="reviewed-title"/>+      </if>+      <else>+        <!-- Assume title is title of reviewed work -->+        <text font-style="italic" text-case="title" variable="title"/>+      </else>+    </choose>+  </macro>+  <macro name="description-review-title-short">+    <choose>+      <if match="any" variable="reviewed-genre reviewed-title">+        <!-- Not possible to distinguish TV series episode from other reviewed works without a reviewed source title -->+        <!-- Adapt for `reviewed-container-title` or similar if it becomes available -->+        <text font-style="italic" form="short" text-case="title" variable="reviewed-title"/>+      </if>+      <else>+        <!-- Assume title is title of reviewed work -->+        <text font-style="italic" form="short" text-case="title" variable="title"/>+      </else>+    </choose>+  </macro>+  <macro name="description-serial-bib">+    <group delimiter=". ">+      <text macro="description-format-bib"/>+      <!-- `section` provides magazine departments (CMOS18 14.88) and newspaper column names (CMOS18 14.93) -->+      <text macro="label-section-capitalized"/>+    </group>+  </macro>+  <macro name="description-serial-short">+    <choose>+      <if variable="title"/>+      <else-if variable="genre">+        <text macro="description-format-short"/>+      </else-if>+      <else>+        <text variable="section"/>+      </else>+    </choose>+  </macro>+  <macro name="description-song-bib">+    <!-- Performer of classical music works -->+    <!-- TODO: remove when Zotero fixes mapping of performer to `author` -->+    <group delimiter=" ">+      <!-- Based on `description-format` macro -->+      <choose>+        <if variable="genre">+          <text text-case="capitalize-first" variable="genre"/>+          <text form="verb" term="performer"/>+        </if>+        <!-- providing 'performed by' label for recorded readings (CMOS18 14.164), but it should be omitted for classical music (CMOS18 14.163) -->+        <else>+          <text form="verb" term="performer" text-case="capitalize-first"/>+        </else>+      </choose>+      <names variable="author">+        <substitute>+          <names variable="performer"/>+        </substitute>+      </names>+    </group>+  </macro>+  <!-- 3.3. Identifier (edition, contributors, volume) -->+  <macro name="identifier-bib">+    <group delimiter=". ">+      <choose>+        <if type="patent">+          <text macro="identifier-patent"/>+        </if>+        <else-if type="report">+          <text macro="identifier-report-bib"/>+        </else-if>+        <else-if match="any" type="post webpage">+          <!-- Handle `container-title` on `post` or `webpage` as `publisher` -->+          <text macro="identifier-number-bib"/>+          <text macro="label-version-capitalized"/>+          <text macro="identifier-edition-bib"/>+          <text macro="identifier-contributors-bib"/>+          <text macro="identifier-volume-monographic-bib"/>+        </else-if>+        <else-if variable="container-title">+          <choose>+            <if match="any" type="broadcast graphic map motion_picture">+              <!-- For audiovisual media, number information comes after `title`, not `container-title`; `song` places album catalogue `number` with `publisher` (CMOS18 14.163-164) -->+              <text macro="identifier-number-bib"/>+            </if>+          </choose>+          <text macro="identifier-contributors-bib"/>+        </else-if>+        <else>+          <choose>+            <if match="none" type="song">+              <text macro="identifier-number-bib"/>+            </if>+          </choose>+          <text macro="label-version-capitalized"/>+          <text macro="identifier-edition-bib"/>+          <choose>+            <if match="any" variable="part-title volume-title">+              <text macro="identifier-contributors-bib"/>+            </if>+            <else-if match="any" variable="number-of-volumes part-number volume">+              <!-- `collection-editor` belongs with `collection-title` if item is not multivolume -->+              <choose>+                <if variable="collection-editor">+                  <names variable="collection-editor">+                    <label form="verb" suffix=" " text-case="capitalize-first"/>+                    <name and="text"/>+                  </names>+                </if>+                <else>+                  <text macro="identifier-contributors-bib"/>+                </else>+              </choose>+            </else-if>+            <else>+              <text macro="identifier-contributors-bib"/>+            </else>+          </choose>+          <text macro="identifier-volume-monographic-bib"/>+          <choose>+            <!-- `collection-editor` supplied in `identifier-volume-monographic-bib` if there is a `part-title` or `volume-title` -->+            <if match="any" variable="part-title volume-title"/>+            <else-if match="any" variable="number-of-volumes part-number volume">+              <choose>+                <if variable="collection-editor">+                  <text macro="identifier-contributors-bib"/>+                </if>+              </choose>+            </else-if>+          </choose>+        </else>+      </choose>+    </group>+  </macro>+  <!-- Identifier elements -->+  <macro name="identifier-contributors-bib">+    <choose>+      <if match="any" type="article-journal article-magazine article-newspaper periodical post-weblog review review-book">+        <text macro="identifier-contributors-serial-bib"/>+      </if>+      <else-if match="any" type="interview paper-conference">+        <choose>+          <if match="any" variable="collection-editor compiler editor editorial-director">+            <!-- monographic usage -->+            <text macro="identifier-contributors-monographic-bib"/>+          </if>+          <else>+            <!-- serial usage -->+            <text macro="identifier-contributors-serial-bib"/>+          </else>+        </choose>+      </else-if>+      <else>+        <text macro="identifier-contributors-monographic-bib"/>+      </else>+    </choose>+  </macro>+  <macro name="identifier-contributors-monographic-bib">+    <group delimiter=". ">+      <choose>+        <if match="any" type="post webpage">+          <group delimiter=". ">+            <names variable="container-author">+              <label form="verb" suffix=" " text-case="capitalize-first"/>+              <name and="text"/>+            </names>+            <names variable="editor-translator">+              <label form="verb" suffix=" " text-case="capitalize-first"/>+              <name and="text"/>+            </names>+            <names delimiter=". " variable="editor translator">+              <label form="verb" suffix=" " text-case="capitalize-first"/>+              <name and="text"/>+            </names>+            <names variable="editorial-director">+              <label form="verb" suffix=" " text-case="capitalize-first"/>+              <name and="text"/>+            </names>+            <names variable="guest">+              <label form="verb" suffix=" " text-case="capitalize-first"/>+              <name and="text"/>+            </names>+            <names variable="host">+              <label form="verb" suffix=" " text-case="capitalize-first"/>+              <name and="text"/>+            </names>+            <names variable="illustrator">+              <label form="verb" suffix=" " text-case="capitalize-first"/>+              <name and="text"/>+            </names>+            <names variable="narrator">+              <label form="verb" suffix=" " text-case="capitalize-first"/>+              <name and="text"/>+            </names>+            <names delimiter=". " variable="compiler chair organizer curator">+              <label form="verb" suffix=" " text-case="capitalize-first"/>+              <name and="text"/>+            </names>+            <names delimiter=". " variable="series-creator executive-producer">+              <label form="verb" suffix=" " text-case="capitalize-first"/>+              <name and="text"/>+            </names>+            <names variable="producer">+              <label form="verb" suffix=" " text-case="capitalize-first"/>+              <name and="text"/>+            </names>+            <names variable="director">+              <label form="verb" suffix=" " text-case="capitalize-first"/>+              <name and="text"/>+            </names>+            <choose>+              <if match="any" type="broadcast performance">+                <names variable="script-writer">+                  <label form="verb" suffix=" " text-case="capitalize-first"/>+                  <name and="text"/>+                </names>+              </if>+            </choose>+            <names variable="performer">+              <label form="verb" suffix=" " text-case="capitalize-first"/>+              <name and="text"/>+            </names>+            <choose>+              <if match="none" type="thesis">+                <names variable="contributor">+                  <label form="verb" suffix=" " text-case="capitalize-first"/>+                  <name and="text"/>+                </names>+              </if>+            </choose>+          </group>+        </if>+        <else>+          <!-- Handle `container-title` on `post` or `webpage` as `publisher` -->+          <group delimiter=". ">+            <choose>+              <if match="none" variable="container-title">+                <names variable="container-author">+                  <label form="verb" suffix=" " text-case="capitalize-first"/>+                  <name and="text"/>+                </names>+                <names variable="editor-translator">+                  <label form="verb" suffix=" " text-case="capitalize-first"/>+                  <name and="text"/>+                </names>+                <names delimiter=". " variable="editor translator">+                  <label form="verb" suffix=" " text-case="capitalize-first"/>+                  <name and="text"/>+                </names>+                <names variable="editorial-director">+                  <label form="verb" suffix=" " text-case="capitalize-first"/>+                  <name and="text"/>+                </names>+                <names variable="guest">+                  <label form="verb" suffix=" " text-case="capitalize-first"/>+                  <name and="text"/>+                </names>+                <names variable="host">+                  <label form="verb" suffix=" " text-case="capitalize-first"/>+                  <name and="text"/>+                </names>+              </if>+            </choose>+            <names variable="illustrator">+              <label form="verb" suffix=" " text-case="capitalize-first"/>+              <name and="text"/>+            </names>+            <names variable="narrator">+              <label form="verb" suffix=" " text-case="capitalize-first"/>+              <name and="text"/>+            </names>+            <choose>+              <if match="none" variable="container-title">+                <names delimiter=". " variable="compiler chair organizer curator">+                  <label form="verb" suffix=" " text-case="capitalize-first"/>+                  <name and="text"/>+                </names>+                <names delimiter=". " variable="series-creator executive-producer">+                  <label form="verb" suffix=" " text-case="capitalize-first"/>+                  <name and="text"/>+                </names>+                <names variable="producer">+                  <label form="verb" suffix=" " text-case="capitalize-first"/>+                  <name and="text"/>+                </names>+                <names variable="director">+                  <label form="verb" suffix=" " text-case="capitalize-first"/>+                  <name and="text"/>+                </names>+                <choose>+                  <if match="any" type="broadcast performance">+                    <names variable="script-writer">+                      <label form="verb" suffix=" " text-case="capitalize-first"/>+                      <name and="text"/>+                    </names>+                  </if>+                </choose>+                <names variable="performer">+                  <label form="verb" suffix=" " text-case="capitalize-first"/>+                  <name and="text"/>+                </names>+                <choose>+                  <if match="none" type="song thesis">+                    <names variable="contributor">+                      <label form="verb" suffix=" " text-case="capitalize-first"/>+                      <name and="text"/>+                    </names>+                  </if>+                </choose>+              </if>+            </choose>+            <choose>+              <if type="song">+                <!-- Song contributors attached to album (CMOS18 14.163) -->+                <names variable="contributor">+                  <label form="verb" suffix=" " text-case="capitalize-first"/>+                  <name and="text"/>+                </names>+              </if>+            </choose>+          </group>+        </else>+      </choose>+    </group>+  </macro>+  <macro name="identifier-contributors-serial-bib">+    <group delimiter=". ">+      <names delimiter=". " variable="translator narrator">+        <label form="verb" suffix=" " text-case="capitalize-first"/>+        <name and="text"/>+      </names>+      <names delimiter=", " variable="compiler chair organizer curator">+        <label form="verb" suffix=" " text-case="capitalize-first"/>+        <name and="text"/>+      </names>+      <names delimiter=", " variable="series-creator executive-producer">+        <label form="verb" suffix=" " text-case="capitalize-first"/>+        <name and="text"/>+      </names>+      <names variable="producer">+        <label form="verb" suffix=" " text-case="capitalize-first"/>+        <name and="text"/>+      </names>+      <names variable="director">+        <label form="verb" suffix=" " text-case="capitalize-first"/>+        <name and="text"/>+      </names>+      <names variable="script-writer">+        <label form="verb" suffix=" " text-case="capitalize-first"/>+        <name and="text"/>+      </names>+      <names variable="performer">+        <label form="verb" suffix=" " text-case="capitalize-first"/>+        <name and="text"/>+      </names>+    </group>+  </macro>+  <macro name="identifier-edition-bib">+    <choose>+      <if match="none" variable="original-date">+        <text macro="label-edition-capitalized"/>+      </if>+      <else-if variable="original-title">+        <text macro="label-edition-capitalized"/>+      </else-if>+    </choose>+  </macro>+  <macro name="identifier-number-bib">+    <group delimiter=" ">+      <choose>+        <if is-numeric="number" type="broadcast" variable="genre">+          <text text-case="capitalize-first" variable="genre"/>+          <text variable="number"/>+        </if>+        <else-if is-numeric="number" type="broadcast">+          <text text-case="capitalize-first" value="episode"/>+          <text variable="number"/>+        </else-if>+        <else-if variable="number">+          <text text-case="title" variable="genre"/>+          <text macro="label-number-capitalized"/>+        </else-if>+      </choose>+    </group>+  </macro>+  <macro name="identifier-patent">+    <group delimiter=", ">+      <group delimiter=" ">+        <!-- `authority`: US ; `genre`: patent ; `number`: 123,445 -->+        <text form="short" variable="authority"/>+        <!-- 'US Patent' capitalized in both bibliography and note forms -->+        <choose>+          <if variable="genre">+            <text text-case="capitalize-first" variable="genre"/>+          </if>+          <else>+            <text term="patent" text-case="capitalize-first"/>+          </else>+        </choose>+        <text variable="number"/>+      </group>+      <group delimiter=" ">+        <text value="filed"/>+        <date form="text" variable="submitted"/>+      </group>+      <group delimiter=" ">+        <choose>+          <if variable="issued submitted">+            <text term="and"/>+          </if>+        </choose>+        <text value="issued"/>+        <!-- Always give full issue date, even in author-date (CMOS18 14.158) -->+        <text macro="date-issued-full"/>+      </group>+    </group>+  </macro>+  <macro name="identifier-report-bib">+    <group delimiter=". ">+      <choose>+        <if variable="container-title">+          <!-- If the report is a chapter in a larger report, then most identifying information is printed in the source. -->+          <text macro="identifier-contributors-bib"/>+        </if>+        <else-if variable="title">+          <text macro="identifier-number-bib"/>+          <text macro="label-version-capitalized"/>+          <text macro="identifier-edition-bib"/>+          <text macro="identifier-contributors-bib"/>+          <text macro="identifier-volume-monographic-bib"/>+        </else-if>+        <else>+          <!-- If there is no `title`, then `genre` and `number` are already printed as the title. -->+          <text macro="label-version-capitalized"/>+          <text macro="identifier-edition-bib"/>+          <text macro="identifier-contributors-bib"/>+          <text macro="identifier-volume-monographic-bib"/>+        </else>+      </choose>+    </group>+  </macro>+  <macro name="identifier-volume-bib">+    <!-- In notes styles, bibliography entries may be listed either under an individual volume title or its series, but the former approach is required for author-date, which is the form that this macro implements (CMOS18 14.21) -->+    <group delimiter=", ">+      <choose>+        <if variable="part-number part-title volume volume-title">+          <!-- part and title with individual titles -->+          <group delimiter=" ">+            <text macro="label-part-number-capitalized"/>+            <text value="of"/>+            <text font-style="italic" text-case="title" variable="volume-title"/>+          </group>+          <group delimiter=" ">+            <text macro="label-volume"/>+            <text value="of"/>+            <group delimiter=", ">+              <text macro="title-primary"/>+              <names variable="collection-editor">+                <label form="verb" suffix=" "/>+                <name and="text"/>+              </names>+            </group>+          </group>+        </if>+        <else-if match="any" variable="part-title volume-title">+          <group delimiter=" ">+            <choose>+              <if variable="part-number volume">+                <group delimiter=", ">+                  <text macro="label-volume-capitalized"/>+                  <text macro="label-part-number"/>+                  <text value="of"/>+                </group>+              </if>+              <else-if variable="part-number">+                <text macro="label-part-number-capitalized"/>+                <text value="of"/>+              </else-if>+              <else-if variable="volume">+                <text macro="label-volume-capitalized"/>+                <text value="of"/>+              </else-if>+            </choose>+            <group delimiter=", ">+              <text macro="title-primary"/>+              <names variable="collection-editor">+                <label form="verb" suffix=" "/>+                <name and="text"/>+              </names>+            </group>+          </group>+        </else-if>+        <else-if variable="part-number volume">+          <text macro="label-volume-capitalized"/>+          <text macro="label-part-number"/>+        </else-if>+        <else-if variable="part-number">+          <text macro="label-part-number-capitalized"/>+        </else-if>+        <else-if variable="volume">+          <text macro="label-volume-capitalized"/>+        </else-if>+        <else>+          <text macro="label-number-of-volumes"/>+        </else>+      </choose>+    </group>+  </macro>+  <macro name="identifier-volume-monographic-bib">+    <choose>+      <if match="any" type="article-journal article-magazine article-newspaper periodical post-weblog review review-book"/>+      <else-if match="any" type="interview paper-conference">+        <choose>+          <if match="any" variable="collection-editor compiler editor editorial-director">+            <!-- monographic usage -->+            <text macro="identifier-volume-bib"/>+          </if>+        </choose>+      </else-if>+      <else>+        <text macro="identifier-volume-bib"/>+      </else>+    </choose>+  </macro>+  <!-- 4. Source -->+  <macro name="source-bib">+    <choose>+      <if match="any" type="article-journal article-magazine article-newspaper periodical post-weblog review review-book">+        <!-- serial usage -->+        <text macro="source-serial-bib"/>+      </if>+      <else-if match="any" type="interview paper-conference">+        <choose>+          <if match="any" variable="collection-editor container-author editor editorial-director">+            <!-- monographic usage -->+            <text macro="source-monographic-bib"/>+          </if>+          <else>+            <!-- serial usage -->+            <text macro="source-serial-bib"/>+          </else>+        </choose>+      </else-if>+      <else-if match="any" type="patent post webpage"/>+      <else>+        <text macro="source-monographic-bib"/>+      </else>+    </choose>+  </macro>+  <!-- 4.1. Serial sources -->+  <macro name="source-serial-bib">+    <group delimiter=". ">+      <text macro="source-serial-title-volume-bib"/>+      <choose>+        <if type="article-newspaper">+          <group delimiter=", ">+            <text macro="source-serial-title-bib"/>+            <text macro="source-serial-identifier-bib"/>+          </group>+        </if>+        <else-if variable="collection-title volume">+          <group delimiter=", ">+            <text macro="source-serial-title-bib"/>+            <text macro="source-serial-identifier-bib"/>+          </group>+        </else-if>+        <else-if variable="volume">+          <group delimiter=" ">+            <text macro="source-serial-title-bib"/>+            <text macro="source-serial-identifier-bib"/>+          </group>+        </else-if>+        <else>+          <group delimiter=", ">+            <text macro="source-serial-title-bib"/>+            <text macro="source-serial-identifier-bib"/>+          </group>+        </else>+      </choose>+    </group>+  </macro>+  <!-- Serial source title -->+  <macro name="source-serial-name">+    <group delimiter=" ">+      <text font-style="italic" text-case="title" variable="container-title"/>+      <choose>+        <!-- TODO: remove conditional when Zotero stops double-mapping `event-place` and `publisher-place` -->+        <if match="none" variable="event-date event-title">+          <text prefix="(" suffix=")" variable="publisher-place"/>+        </if>+      </choose>+    </group>+  </macro>+  <macro name="source-serial-title-bib">+    <group delimiter=", ">+      <choose>+        <!-- Journal special issues (CMOS18 14.77) and supplements (CMOS18 14.78) -->+        <if match="none" variable="container-title"/>+        <else-if match="none" type="periodical" variable="supplement-number volume-title"/>+        <!-- TODO: use `container-genre` here once available to allow a custom description of the journal volume -->+        <else-if variable="supplement-number volume-title">+          <text term="supplement" text-case="capitalize-first"/>+        </else-if>+        <else-if type="periodical" variable="supplement-number title">+          <text term="supplement" text-case="capitalize-first"/>+        </else-if>+        <else-if variable="volume-title">+          <text term="special-issue" text-case="capitalize-first"/>+        </else-if>+        <else-if type="periodical" variable="title">+          <text term="special-issue" text-case="capitalize-first"/>+        </else-if>+      </choose>+      <text macro="source-serial-name"/>+      <choose>+        <!-- 'ahead of print' is placed akin to a series (CMOS18 14.75) -->+        <if match="any" variable="available-date collection-title issue number page status supplement-number volume"/>+        <else-if type="article-journal" variable="DOI issued">+          <text term="advance-online-publication"/>+        </else-if>+      </choose>+    </group>+  </macro>+  <macro name="source-serial-title-volume-bib">+    <choose>+      <if variable="volume-title">+        <!-- Journal special issues (CMOS18 14.77) and supplements (CMOS18 14.78) -->+        <group delimiter=", ">+          <group delimiter=" ">+            <text macro="source-monographic-preposition-bib"/>+            <text quotes="true" text-case="title" variable="volume-title"/>+          </group>+          <text macro="source-monographic-identifier-contributors-bib"/>+        </group>+      </if>+    </choose>+  </macro>+  <!-- Serial source identifier -->+  <macro name="source-serial-identifier-bib">+    <choose>+      <if match="any" variable="issue supplement-number volume">+        <group delimiter=": ">+          <text macro="source-serial-identifier-volume-author-date"/>+          <text macro="source-serial-locator"/>+        </group>+      </if>+      <else>+        <group delimiter=", ">+          <group delimiter=". ">+            <text macro="source-serial-identifier-volume-author-date"/>+            <!-- periodical edition always capitalized (CMOS18 14.89) -->+            <text macro="label-edition-capitalized"/>+          </group>+          <text macro="source-serial-locator"/>+        </group>+      </else>+      <!-- TODO: If CSL adds `date-part` detection, add two further conditions to address CMOS18 14.74: delimiting with ":" if there is a `volume` and no month or `issue` or `supplement number`; delimiting with ", " or there is an `issue` or `supplement number` and no month -->+    </choose>+  </macro>+  <macro name="source-serial-identifier-volume-author-date">+    <group delimiter=", ">+      <choose>+        <if type="article-newspaper">+          <!-- newspapers provide the full date in place of volume/issue numbers (CMOS18 14.89) -->+          <text variable="collection-title"/>+          <text macro="source-serial-volume-status-bib"/>+        </if>+        <else-if match="any" variable="issue supplement-number volume">+          <choose>+            <if match="any" type="article-magazine review review-book" variable="reviewed-author reviewed-genre reviewed-title">+              <!-- date appears first if the magazine or review `container-title` has been substituted for a missing author (CMOS18 14.87, 14.102) -->+              <choose>+                <if match="none" variable="author chair collection-editor compiler composer curator director editor editor-translator editorial-director executive-producer guest host illustrator organizer producer series-creator translator">+                  <choose>+                    <!-- no extra date details with a volume plus issue/supplement -->+                    <if variable="issue volume"/>+                    <else-if variable="supplement-number"/>+                    <!-- nothing to substitute if there is no issue/supplement/volume -->+                    <else-if match="none" variable="issue volume"/>+                    <else>+                      <text macro="source-date-bib"/>+                      <!-- for CMOS17 author-date: -->+                      <!-- <text macro="source-date-issued-month-day"/> -->+                    </else>+                  </choose>+                </if>+              </choose>+            </if>+          </choose>+          <!-- `collection-title` is for any serial with multiple series (e.g. '4th ser.') -->+          <text variable="collection-title"/>+          <group delimiter=" ">+            <choose>+              <if variable="volume">+                <choose>+                  <if variable="collection-title">+                    <text macro="label-volume"/>+                  </if>+                  <else-if match="any" type="article-magazine review review-book" variable="reviewed-author reviewed-genre reviewed-title">+                    <!-- provide label if a magazine or review `container-title` has been substituted for a missing author (CMOS18 14.87, 14.102) -->+                    <choose>+                      <if match="any" variable="author chair collection-editor compiler composer curator director editor editor-translator editorial-director executive-producer guest host illustrator organizer producer series-creator translator">+                        <text variable="volume"/>+                      </if>+                      <!-- TODO: when CSL provides date part detection, volume should be lowercase if there is a month, but otherwise capitalized -->+                      <else>+                        <text macro="label-volume-capitalized"/>+                      </else>+                    </choose>+                  </else-if>+                  <else>+                    <text variable="volume"/>+                  </else>+                </choose>+                <group delimiter=", " prefix="(" suffix=")">+                  <choose>+                    <if match="any" variable="issue supplement-number">+                      <text variable="issue"/>+                      <text macro="label-supplement-number"/>+                    </if>+                    <else-if match="any" type="article-magazine review review-book" variable="reviewed-author reviewed-genre reviewed-title">+                      <!-- date for anonymous magazine and review articles only appears here if it did not earlier (CMOS18 14.87, 14.102) -->+                      <choose>+                        <if match="any" variable="author chair collection-editor compiler composer curator director editor editor-translator editorial-director executive-producer guest host illustrator organizer producer series-creator translator">+                          <text macro="source-date-bib"/>+                          <!-- for CMOS17 author-date: -->+                          <!-- <text macro="source-date-issued-month-day"/> -->+                        </if>+                      </choose>+                    </else-if>+                    <else>+                      <text macro="source-date-bib"/>+                      <!-- for CMOS17 author-date: -->+                      <!-- <text macro="source-date-issued-month-day"/> -->+                    </else>+                  </choose>+                </group>+              </if>+              <else-if match="any" variable="issue supplement-number">+                <group delimiter=" ">+                  <group delimiter=", ">+                    <text macro="label-issue"/>+                    <text macro="label-supplement-number"/>+                  </group>+                  <choose>+                    <if match="any" variable="author chair collection-editor compiler composer curator director editor editor-translator editorial-director executive-producer guest host illustrator organizer producer series-creator translator">+                      <text macro="source-date-bib" prefix="(" suffix=")"/>+                      <!-- for CMOS17 author-date: -->+                      <!-- <text macro="source-date-issued-month-day" prefix="(" suffix=")"/> -->+                    </if>+                  </choose>+                </group>+              </else-if>+            </choose>+          </group>+        </else-if>+        <else>+          <text variable="collection-title"/>+          <choose>+            <if match="any" type="interview" variable="interviewer">+              <!-- publisher possible with `interview` (cf. CMOS18 14.110) -->+              <text variable="publisher"/>+            </if>+          </choose>+          <text macro="source-serial-volume-status-bib"/>+        </else>+      </choose>+    </group>+  </macro>+  <macro name="source-serial-volume-status-bib">+    <group delimiter=", ">+      <choose>+        <if match="none" variable="collection-title issue number page supplement-number volume">+          <group delimiter=" ">+            <!-- article accepted for publication and available on publisher website (CMOS18 14.75) -->+            <!-- TODO: use CSL term for `available-date` when available -->+            <text value="accepted"/>+            <date form="text" variable="available-date"/>+          </group>+        </if>+      </choose>+      <group delimiter=" ">+        <text macro="source-date-status-bib"/>+        <text macro="source-date-bib"/>+        <!-- for CMOS17 author-date: -->+        <!-- <text macro="source-date-issued-full-serial"/> -->+      </group>+    </group>+  </macro>+  <!-- Serial source locator -->+  <macro name="source-serial-locator">+    <choose>+      <if match="any" variable="locator number">+        <group delimiter=", ">+          <text macro="label-locator"/>+          <!-- an article ID appears alongside locators in notes (CMOS18 14.71) -->+          <text variable="number"/>+        </group>+      </if>+      <!-- do not give pages for newspapers (CMOS18 14.89) -->+      <else-if type="article-newspaper"/>+      <else>+        <text variable="page"/>+      </else>+    </choose>+  </macro>+  <!-- 4.2. Monographic sources -->+  <macro name="source-monographic-bib">+    <group delimiter=". ">+      <!-- Monographic sources repeat main reference elements -->+      <choose>+        <if variable="container-title">+          <group delimiter=", ">+            <group delimiter=" ">+              <choose>+                <if match="none" type="broadcast motion_picture">+                  <text macro="source-monographic-preposition-bib"/>+                </if>+              </choose>+              <text macro="source-monographic-title-bib"/>+            </group>+            <text macro="source-monographic-description-bib"/>+            <text macro="source-monographic-identifier-bib"/>+            <text macro="source-monographic-locator"/>+          </group>+        </if>+      </choose>+      <text macro="source-series-bib"/>+      <choose>+        <!-- show event information here only if not collapsed with `issued` (CMOS18 14.167) -->+        <if match="any" variable="event-date original-date original-publisher original-publisher-place publisher status">+          <text macro="source-event-bib"/>+        </if>+      </choose>+    </group>+  </macro>+  <!-- Monographic source title -->+  <macro name="source-monographic-preposition-bib">+    <choose>+      <if type="chapter" variable="container-title genre">+        <text value="to"/>+      </if>+      <else-if match="any" type="entry entry-dictionary entry-encyclopedia">+        <choose>+          <if match="any" variable="author composer">+            <!-- Give preposition only for signed entries; otherwise, title is substituted -->+            <text term="in" text-case="capitalize-first"/>+          </if>+        </choose>+      </else-if>+      <!-- if printing chapter page numbers (CMOS17/classic):+      <else-if variable="chapter-number page title"><text term="in" text-case="capitalize-first"/></else-if>+      -->+      <else-if variable="chapter-number">+        <group delimiter=" ">+          <text macro="label-chapter-number-capitalized"/>+          <choose>+            <if type="song">+              <text term="on"/>+            </if>+            <else>+              <text term="in"/>+            </else>+          </choose>+        </group>+      </else-if>+      <else>+        <text term="in" text-case="capitalize-first"/>+      </else>+    </choose>+  </macro>+  <macro name="source-monographic-title-bib">+    <choose>+      <if variable="part-title">+        <text macro="title-part"/>+      </if>+      <else-if variable="volume-title">+        <text font-style="italic" text-case="title" variable="volume-title"/>+      </else-if>+      <else>+        <text font-style="italic" text-case="title" variable="container-title"/>+      </else>+    </choose>+  </macro>+  <!-- Monographic source description -->+  <macro name="source-monographic-description-bib">+    <choose>+      <if match="any" type="event paper-conference performance speech">+        <!-- Conference presentations should describe the session unless published in a proceedings -->+        <choose>+          <if match="none" variable="collection-editor compiler editor editorial-director">+            <!-- serial usage -->+            <text macro="description-format-bib"/>+          </if>+        </choose>+      </if>+      <else-if type="software">+        <!-- For entries in mobile app reference works, place description after `container-title` -->+        <text macro="description-format-bib"/>+      </else-if>+      <else-if match="any" type="document report standard">+        <!-- For chapters in report, standards, and generic documents, place description after `container-title` -->+        <text macro="description-format-bib"/>+      </else-if>+    </choose>+  </macro>+  <!-- Monographic source identifier -->+  <macro name="source-monographic-identifier-bib">+    <!-- Based on `identifier-bib` -->+    <choose>+      <if variable="container-title">+        <group delimiter=", ">+          <choose>+            <if match="none" type="broadcast graphic map motion_picture song">+              <!-- For audiovisual media, number information comes after `title`, not `container-title`; `song` places album catalogue `number` with `publisher` (CMOS18 14.163-164) -->+              <text macro="identifier-number-bib"/>+            </if>+          </choose>+          <text macro="label-version"/>+          <text macro="label-edition"/>+          <choose>+            <if match="any" variable="part-title volume-title">+              <text macro="source-monographic-identifier-contributors-bib"/>+            </if>+            <else-if match="any" variable="number-of-volumes part-number volume">+              <!-- `collection-editor` belongs with `collection-title` if item is not multivolume -->+              <choose>+                <if variable="collection-editor">+                  <names variable="collection-editor">+                    <label form="verb" suffix=" "/>+                    <name and="text"/>+                  </names>+                </if>+                <else>+                  <text macro="source-monographic-identifier-contributors-bib"/>+                </else>+              </choose>+            </else-if>+            <else>+              <text macro="source-monographic-identifier-contributors-bib"/>+            </else>+          </choose>+          <text macro="source-monographic-identifier-volume-bib"/>+          <choose>+            <!-- `collection-editor` supplied in `source-monographic-identifier-volume-bib` if there is a `part-title` or `volume-title` -->+            <if match="any" variable="part-title volume-title"/>+            <else-if match="any" variable="number-of-volumes part-number volume">+              <choose>+                <if variable="collection-editor">+                  <text macro="source-monographic-identifier-contributors-bib"/>+                </if>+              </choose>+            </else-if>+          </choose>+        </group>+      </if>+    </choose>+  </macro>+  <macro name="source-monographic-identifier-contributors-bib">+    <group delimiter=", ">+      <names variable="container-author">+        <label form="verb" suffix=" "/>+        <name and="text"/>+      </names>+      <names variable="editor-translator">+        <label form="verb" suffix=" "/>+        <name and="text"/>+      </names>+      <names delimiter=", " variable="editor translator">+        <label form="verb" suffix=" "/>+        <name and="text"/>+      </names>+      <names variable="guest">+        <label form="verb" suffix=" "/>+        <name and="text"/>+      </names>+      <names variable="host">+        <label form="verb" suffix=" "/>+        <name and="text"/>+      </names>+      <names delimiter=", " variable="chair organizer">+        <label form="verb" suffix=" "/>+        <name and="text"/>+      </names>+      <names delimiter=", " variable="illustrator narrator compiler curator">+        <label form="verb" suffix=" "/>+        <name and="text"/>+      </names>+      <names delimiter=", " variable="series-creator executive-producer">+        <label form="verb" suffix=" "/>+        <name and="text"/>+      </names>+      <names variable="producer">+        <label form="verb" suffix=" "/>+        <name and="text"/>+      </names>+      <names variable="editorial-director">+        <label form="verb" suffix=" "/>+        <name and="text"/>+      </names>+      <choose>+        <if match="any" type="broadcast performance">+          <names variable="script-writer">+            <label form="verb" suffix=" "/>+            <name and="text"/>+          </names>+        </if>+      </choose>+      <names variable="director">+        <label form="verb" suffix=" "/>+        <name and="text"/>+      </names>+      <names variable="performer">+        <label form="verb" suffix=" "/>+        <name and="text"/>+      </names>+      <choose>+        <if match="none" type="song thesis">+          <!-- Song contributors attached to album (CMOS18 14.163) -->+          <names variable="contributor">+            <label form="verb" suffix=" "/>+            <name and="text"/>+          </names>+        </if>+      </choose>+    </group>+  </macro>+  <macro name="source-monographic-identifier-volume-bib">+    <!-- Mostly identical to `identifier-volume-bib` but without capitalization; giving `container-title` rather than `title-primary`; and ensuring volume number -->+    <group delimiter=", ">+      <choose>+        <if variable="part-number part-title volume volume-title">+          <!-- part and title with individual titles -->+          <group delimiter=" ">+            <text macro="label-part-number"/>+            <text value="of"/>+            <text font-style="italic" text-case="title" variable="volume-title"/>+          </group>+          <group delimiter=" ">+            <text macro="label-volume"/>+            <text value="of"/>+            <group delimiter=", ">+              <text font-style="italic" text-case="title" variable="container-title"/>+              <names variable="collection-editor">+                <label form="verb" suffix=" "/>+                <name and="text"/>+              </names>+            </group>+          </group>+        </if>+        <else-if match="any" variable="part-title volume-title">+          <group delimiter=" ">+            <choose>+              <if variable="part-number volume">+                <group delimiter=", ">+                  <text macro="label-volume"/>+                  <text macro="label-part-number"/>+                  <text value="of"/>+                </group>+              </if>+              <else-if variable="part-number">+                <text macro="label-part-number"/>+                <text value="of"/>+              </else-if>+              <else-if variable="volume">+                <text macro="label-volume"/>+                <text value="of"/>+              </else-if>+            </choose>+            <group delimiter=", ">+              <text font-style="italic" text-case="title" variable="container-title"/>+              <names variable="collection-editor">+                <label form="verb" suffix=" "/>+                <name and="text"/>+              </names>+            </group>+          </group>+        </else-if>+        <else-if match="any" variable="part-number volume">+          <choose>+            <if is-numeric="volume" match="none">+              <text macro="label-volume"/>+            </if>+            <else-if variable="container-title">+              <!-- remove condition in styles that print chapter page numbers (CMOS17/classic) -->+              <text macro="label-volume"/>+            </else-if>+            <else-if is-numeric="volume" variable="page">+              <choose>+                <!-- check for variables that might come between the volume and page number -->+                <if match="any" variable="collection-editor part-number part-title volume-title">+                  <text macro="label-volume"/>+                </if>+              </choose>+            </else-if>+            <else>+              <text macro="label-volume"/>+            </else>+          </choose>+          <text macro="label-part-number"/>+        </else-if>+        <else>+          <text macro="label-number-of-volumes"/>+        </else>+      </choose>+    </group>+  </macro>+  <!-- Monographic source locator -->+  <macro name="source-monographic-locator">+    <choose>+      <if is-numeric="volume" locator="page">+        <group delimiter=":">+          <choose>+            <if match="none" variable="collection-editor part-number part-title volume-title">+              <text variable="volume"/>+            </if>+          </choose>+          <text variable="locator"/>+        </group>+      </if>+      <else-if variable="locator">+        <text macro="label-locator"/>+      </else-if>+      <!-- remove `container-title` condition in styles that print chapter page numbers (CMOS17/classic) -->+      <else-if variable="container-title"/>+      <else-if is-numeric="volume" variable="page">+        <!-- collapse the volume and page number if adjacent -->+        <group delimiter=":">+          <choose>+            <!-- check for variables that might come between the volume and page number -->+            <if match="none" variable="collection-editor part-number part-title volume-title">+              <text variable="volume"/>+            </if>+          </choose>+          <text variable="page"/>+        </group>+      </else-if>+      <else>+        <text variable="page"/>+      </else>+    </choose>+  </macro>+  <!-- 4.3. Series -->+  <macro name="source-series-bib">+    <group delimiter=", ">+      <choose>+        <if variable="collection-editor collection-title">+          <choose>+            <if match="any" variable="number-of-volumes part-number part-title volume volume-title">+              <text macro="source-series-title"/>+            </if>+            <else>+              <text text-case="title" variable="collection-title"/>+              <names variable="collection-editor">+                <label form="verb" suffix=" "/>+                <name and="text"/>+              </names>+              <text macro="label-collection-number"/>+              <text macro="label-issue"/>+            </else>+          </choose>+        </if>+        <else>+          <text macro="source-series-title"/>+        </else>+      </choose>+    </group>+  </macro>+  <macro name="source-series-title">+    <group delimiter=", ">+      <choose>+        <if variable="issue">+          <text text-case="title" variable="collection-title"/>+          <text macro="label-collection-number"/>+          <text macro="label-issue"/>+        </if>+        <else-if is-numeric="collection-number" variable="collection-title">+          <group delimiter=" ">+            <text text-case="title" variable="collection-title"/>+            <text variable="collection-number"/>+          </group>+        </else-if>+        <else-if variable="collection-title">+          <text text-case="title" variable="collection-title"/>+          <text variable="collection-number"/>+        </else-if>+      </choose>+    </group>+  </macro>+  <!-- 4.4. Event -->+  <macro name="source-event-bib">+    <group delimiter=" ">+      <choose>+        <!-- omit types that provide event information in description  -->+        <if match="any" type="interview" variable="interviewer"/>+        <else-if type="personal_communication" variable="recipient"/>+        <else-if match="any" type="review review-book" variable="reviewed-author reviewed-genre reviewed-title"/>+        <else-if match="any" variable="event event-date event-title">+          <!-- TODO: To prevent Zotero from printing `event-place`, due to its double-mapping of `publisher-place` and `event-place`. Remove this when that is changed. -->+          <choose>+            <if type="paper-conference">+              <choose>+                <if match="none" variable="collection-editor compiler editor editorial-director issue page supplement-number volume">+                  <!-- Don't print event info for conference papers published in proceedings -->+                  <text macro="source-event-status-bib"/>+                  <text macro="source-event-description-bib"/>+                </if>+              </choose>+            </if>+            <else>+              <!-- For other item types, print event info even if published (e.g. collection catalogs, performance programs). -->+              <text macro="source-event-status-bib"/>+              <text macro="source-event-description-bib"/>+            </else>+          </choose>+        </else-if>+      </choose>+    </group>+  </macro>+  <macro name="source-event-place-first">+    <!-- for descriptive elements for interviews, reviews, letters -->+    <choose>+      <if match="any" variable="event event-date event-title">+        <group delimiter=", ">+          <text variable="event-title"/>+          <text variable="event-place"/>+          <text macro="date-event-full"/>+        </group>+      </if>+    </choose>+  </macro>+  <macro name="source-event-status-bib">+    <group delimiter=" ">+      <choose>+        <if type="broadcast" variable="status">+          <!-- 'aired', 'performed', etc. (CMOS18 14.165) -->+          <text text-case="capitalize-first" variable="status"/>+        </if>+        <else-if type="paper-conference">+          <choose>+            <if variable="genre">+              <text text-case="capitalize-first" value="presented"/>+            </if>+            <else>+              <text form="short" term="paper-conference" text-case="capitalize-first"/>+              <text value="presented"/>+            </else>+          </choose>+          <choose>+            <if variable="event-title">+              <text term="at"/>+            </if>+          </choose>+        </else-if>+        <else-if type="song">+          <text text-case="capitalize-first" value="recorded"/>+          <choose>+            <if variable="event-title">+              <text term="at"/>+            </if>+          </choose>+        </else-if>+        <else-if variable="event-date issued"/>+        <else-if match="none" variable="issued">+          <text text-case="capitalize-first" variable="status"/>+        </else-if>+      </choose>+    </group>+  </macro>+  <macro name="source-event-title">+    <choose>+      <!-- TODO: We expect `event-title` to be used, but processors and applications may not be updated yet. This macro ensures that either `event` or `event-title` can be accepted. Remove if processor logic and application adoption can handle this. -->+      <if variable="event-title">+        <text variable="event-title"/>+      </if>+      <else>+        <text variable="event"/>+      </else>+    </choose>+  </macro>+  <macro name="source-event-title-capitalized">+    <choose>+      <!-- TODO: We expect `event-title` to be used, but processors and applications may not be updated yet. This macro ensures that either `event` or `event-title` can be accepted. Remove if processor logic and application adoption can handle this. -->+      <if variable="event-title">+        <text text-case="capitalize-first" variable="event-title"/>+      </if>+      <else>+        <text text-case="capitalize-first" variable="event"/>+      </else>+    </choose>+  </macro>+  <macro name="source-event-description-bib">+    <group delimiter=", ">+      <choose>+        <if type="song">+          <text macro="source-event-title"/>+        </if>+        <else-if type="paper-conference" variable="genre">+          <text macro="source-event-title-capitalized"/>+        </else-if>+        <else-if type="paper-conference">+          <text macro="source-event-title"/>+        </else-if>+        <else>+          <text macro="source-event-title-capitalized"/>+        </else>+      </choose>+      <text macro="date-event-full"/>+      <text variable="event-place"/>+    </group>+  </macro>+  <!-- 4.5. Facts of publication -->+  <macro name="source-monographic-publication-bib">+    <group delimiter=". ">+      <choose>+        <!-- Provide only for monographic types -->+        <if match="any" type="article-journal article-magazine article-newspaper periodical post-weblog review review-book"/>+        <else-if match="any" type="interview paper-conference">+          <choose>+            <if match="any" variable="collection-editor container-author editor editorial-director">+              <!-- monographic usage -->+              <text macro="source-publication-and-date-bib"/>+            </if>+          </choose>+        </else-if>+        <!-- `patent` date in identification (CMOS18 14.158) -->+        <else-if type="patent"/>+        <else>+          <text macro="source-publication-and-date-bib"/>+        </else>+      </choose>+      <text macro="source-publication-original-title-bib"/>+    </group>+  </macro>+  <macro name="source-publication-and-date-bib">+    <group delimiter=", ">+      <choose>+        <if match="any" type="post webpage">+          <!-- `container-title` functions like a publisher with social media and website sources (CMOS18 14.104-106) -->+          <text text-case="title" variable="container-title"/>+        </if>+      </choose>+      <choose>+        <if type="broadcast" variable="DOI">+          <!-- a podcast publisher appears before the date, whereas the network of an aired show appears after (CMOS18 14.165); unfortunately CSL stores both in `publisher` -->+          <!-- TODO: `DOI` or `URL` detection is the only way to distinguish radio/TV from podcasts, but it is obviously imprecise; modify if CSL provides a `podcast` type -->+          <text macro="source-publication-history-bib"/>+        </if>+        <else-if type="broadcast" variable="URL">+          <text macro="source-publication-history-bib"/>+        </else-if>+        <else-if type="broadcast"/>+        <else>+          <text macro="source-publication-history-bib"/>+        </else>+      </choose>+      <group delimiter=" ">+        <text macro="source-date-status-bib"/>+        <text macro="source-date-bib"/>+      </group>+      <choose>+        <if type="broadcast" variable="URL"/>+        <else-if type="broadcast">+          <group delimiter=" ">+            <text term="on"/>+            <text macro="source-publication-history-bib"/>+          </group>+        </else-if>+      </choose>+    </group>+  </macro>+  <!-- Facts of publication elements -->+  <macro name="source-publication-description-bib">+    <choose>+      <if type="article" variable="genre"/>+      <else-if type="article">+        <!-- `preprint` term attached to repository name, but specific working paper descriptors appear in description (CMOS18 14.76, 14.116) -->+        <text term="preprint" text-case="capitalize-first"/>+      </else-if>+      <else-if type="thesis">+        <!-- thesis type appears with university name (CMOS18 14.113) -->+        <text macro="description-format-bib"/>+      </else-if>+      <else-if match="any" variable="original-publisher original-publisher-place">+        <choose>+          <!-- `edition` provides an alternative label to `reprint` (CMOS18 14.16) -->+          <if match="any" variable="edition original-title"/>+          <else-if match="none" type="book chapter classic entry entry-dictionary entry-encyclopedia interview musical_score pamphlet paper-conference report thesis"/>+          <else-if variable="issued original-date">+            <text text-case="capitalize-first" value="reprint"/>+          </else-if>+        </choose>+      </else-if>+    </choose>+  </macro>+  <macro name="source-publication-history-bib">+    <choose>+      <if variable="original-title">+        <!-- `original-title` is covered in `source-publication-original-title-bib` -->+        <group delimiter=", ">+          <text macro="source-publication-description-bib"/>+          <text macro="source-publication-publisher-bib"/>+        </group>+      </if>+      <else-if match="any" variable="edition original-publisher original-publisher-place">+        <group delimiter=". ">+          <!-- full stop to separate original date if `original-publisher` (CMOS18 14.16) -->+          <group delimiter=", ">+            <text macro="source-publication-publisher-original-bib"/>+            <text macro="source-date-original"/>+          </group>+          <group delimiter=". ">+            <choose>+              <if variable="issued original-date">+                <text macro="label-edition-capitalized"/>+              </if>+            </choose>+            <group delimiter=", ">+              <text macro="source-publication-description-bib"/>+              <text macro="source-publication-publisher-bib"/>+            </group>+          </group>+        </group>+      </else-if>+      <else>+        <group delimiter="; ">+          <!-- semicolon to separate original date if no publisher (CMOS18 14.165) -->+          <text macro="source-date-original"/>+          <group delimiter=", ">+            <text macro="source-publication-description-bib"/>+            <text macro="source-publication-publisher-bib"/>+          </group>+        </group>+      </else>+    </choose>+  </macro>+  <macro name="source-publication-original-title-bib">+    <!-- Work originally published under a different title (CMOS18 13.101) -->+    <choose>+      <if variable="original-title">+        <group delimiter=" ">+          <text term="original-work-published" text-case="capitalize-first"/>+          <group delimiter=", ">+            <names variable="original-author"/>+            <text font-style="italic" text-case="title" variable="original-title"/>+          </group>+          <group delimiter=", " prefix="(" suffix=")">+            <text macro="source-publication-publisher-original-bib"/>+            <text macro="source-date-original"/>+          </group>+        </group>+      </if>+    </choose>+  </macro>+  <macro name="source-publication-publisher-bib">+    <group delimiter=" ">+      <choose>+        <if type="thesis" variable="publisher">+          <text text-case="capitalize-first" variable="publisher"/>+        </if>+        <else-if variable="publisher">+          <group delimiter=": ">+            <!-- <text text-case="capitalize-first" variable="publisher-place"/> -->+            <text text-case="capitalize-first" variable="publisher"/>+          </group>+        </else-if>+        <!-- TODO: remove conditional when Zotero fixes double-mapping of `event-place` -->+        <else-if match="any" variable="event-date event-title"/>+        <else>+          <text text-case="capitalize-first" variable="publisher-place"/>+        </else>+      </choose>+      <choose>+        <if type="song">+          <!-- Album catalogue number follows label name (CMOS18 14.163-164) -->+          <text variable="number"/>+        </if>+      </choose>+    </group>+  </macro>+  <macro name="source-publication-publisher-original-bib">+    <choose>+      <if variable="original-publisher">+        <group delimiter=": ">+          <!-- <text text-case="capitalize-first" variable="original-publisher-place"/> -->+          <text text-case="capitalize-first" variable="original-publisher"/>+        </group>+      </if>+      <else>+        <text text-case="capitalize-first" variable="original-publisher-place"/>+      </else>+    </choose>+  </macro>+  <!-- 4.6. Date -->+  <macro name="source-date-bib">+    <!-- the date represents the last-mentioned title (CMOS18 14.21) -->+    <!-- there is no `source-date-note` as the date of a multivolume work is not used in note form -->+    <choose>+      <if variable="available-date volume-title">+        <!-- TODO: Is there a better CSL variable for a date of a multivolume work (CMOS18 14.21)? -->+        <date date-parts="year" form="text" variable="available-date"/>+      </if>+      <else-if variable="available-date part-title">+        <date date-parts="year" form="text" variable="available-date"/>+      </else-if>+      <else>+        <text macro="source-date-issued-month-day"/>+      </else>+    </choose>+  </macro>+  <!-- Date elements -->+  <macro name="source-date-issued-month-day">+    <!-- Variant for author-date styles -->+    <!-- Give full date for more ephemeral types -->+    <!-- NB: any changes must also be applied to `source-date-original-month-day` -->+    <choose>+      <if type="personal_communication" variable="event-date issued">+        <!-- Provide issue date for letters listed under event-date -->+        <text macro="date-issued-year"/>+      </if>+      <else-if match="any" type="article-journal article-magazine article-newspaper periodical post-weblog review review-book">+        <text macro="source-date-issued-month-day-serial"/>+      </else-if>+      <else-if match="any" type="interview paper-conference">+        <choose>+          <if match="none" variable="collection-editor compiler editor editorial-director">+            <!-- serial usage -->+            <text macro="source-date-issued-month-day-serial"/>+          </if>+        </choose>+      </else-if>+      <else-if match="any" type="entry entry-dictionary entry-encyclopedia">+        <choose>+          <if match="any" variable="DOI URL">+            <!-- Online reference works use full dates (CMOS18 14.131) -->+            <text macro="date-issued-month-day"/>+          </if>+        </choose>+      </else-if>+      <else-if match="any" type="article broadcast collection dataset document event graphic interview manuscript map patent performance personal_communication post software song speech standard webpage">+        <text macro="date-issued-month-day"/>+      </else-if>+    </choose>+  </macro>+  <macro name="source-date-issued-month-day-serial">+    <choose>+      <if type="article-newspaper">+        <!-- newspapers provide the full date in place of volume/issue numbers (CMOS18 14.89) -->+        <text macro="date-issued-month-day"/>+      </if>+      <else-if match="any" variable="issue supplement-number volume">+        <text macro="date-issued-month"/>+      </else-if>+      <else>+        <text macro="date-issued-month-day"/>+      </else>+    </choose>+  </macro>+  <macro name="source-date-original">+    <text macro="source-date-original-month-day"/>+  </macro>+  <macro name="source-date-original-month-day">+    <!-- Give full date for more ephemeral types -->+    <!-- Macro derived from `source-date-issued-month-day` -->+    <choose>+      <if type="personal_communication" variable="event-date original-date">+        <!-- Provide original date for letters listed under event-date -->+        <text macro="date-original-year"/>+      </if>+      <else-if match="any" type="article-journal article-magazine article-newspaper periodical post-weblog review review-book">+        <choose>+          <if match="any" variable="issue supplement-number volume">+            <text macro="date-original-month"/>+          </if>+          <else>+            <text macro="date-original-month-day"/>+          </else>+        </choose>+      </else-if>+      <else-if match="any" type="interview paper-conference">+        <choose>+          <if match="none" variable="collection-editor compiler editor editorial-director">+            <!-- serial usage -->+            <choose>+              <if match="any" variable="issue supplement-number volume">+                <text macro="date-original-month"/>+              </if>+              <else>+                <text macro="date-original-month-day"/>+              </else>+            </choose>+          </if>+        </choose>+      </else-if>+      <else-if match="any" type="entry entry-dictionary entry-encyclopedia">+        <choose>+          <if match="any" variable="DOI URL">+            <!-- Online reference works use full dates (CMOS18 14.131) -->+            <text macro="date-original-month-day"/>+          </if>+        </choose>+      </else-if>+      <else-if match="any" type="article broadcast collection dataset document event graphic interview manuscript map patent performance personal_communication post software song speech standard webpage">+        <text macro="date-original-month-day"/>+      </else-if>+    </choose>+  </macro>+  <macro name="source-date-status-bib">+    <choose>+      <if type="broadcast" variable="event-title issued status"/>+      <!-- on a `broadcast`, if there is an `event-title`, `status` appears with `event-date` as part of `source-event` (CMOS18 14.165) -->+      <else-if variable="issued status">+        <!-- `status` specifies date type, e.g. 'effective', 'last modified', 'approved' (CMOS18 14.104 for `webpage`; CMOS18 14.159 for `standard`) -->+        <choose>+          <if match="any" variable="original-date original-publisher original-publisher-place original-title publisher">+            <text variable="status"/>+          </if>+          <else>+            <text text-case="capitalize-first" variable="status"/>+          </else>+        </choose>+      </else-if>+      <else-if type="broadcast" variable="issued URL"/>+      <else-if type="broadcast" variable="issued">+        <!-- `status` of a radio or TV broadcast is 'aired' if unspecified (CMOS18 14.165) -->+        <text text-case="capitalize-first" value="aired"/>+      </else-if>+      <else-if type="software" variable="issued publisher">+        <!-- `status` of software is 'released' if unspecified (CMOS18 14.169) -->+        <choose>+          <if match="any" variable="author chair collection-editor compiler composer contributor curator director editor editor-translator editorial-director executive-producer guest host illustrator organizer producer series-creator translator">+            <!-- lowercase if `publisher` is adjacent -->+            <text value="released"/>+          </if>+          <else>+            <text text-case="capitalize-first" value="released"/>+          </else>+        </choose>+      </else-if>+      <else-if type="software" variable="original-date">+        <!-- lowercase if `original-date` is adjacent -->+        <text value="released"/>+      </else-if>+      <else-if type="software" variable="issued">+        <!-- capitalize if `publisher` is not present -->+        <text text-case="capitalize-first" value="released"/>+      </else-if>+    </choose>+  </macro>+  <!-- 4.7. Locator (including page references) -->+  <macro name="source-locator-author-date">+    <choose>+      <if match="any" type="entry entry-dictionary entry-encyclopedia">+        <choose>+          <if match="any" variable="author locator">+            <text macro="label-locator"/>+          </if>+          <else-if variable="container-title title">+            <!-- unsigned reference entry title appears in the locator (CMOS18 13.130) -->+            <group delimiter=" ">+              <choose>+                <if match="none" variable="DOI URL">+                  <!-- Only print reference entries use `sub-verbo` (CMOS18 14.131) -->+                  <text form="short" term="sub-verbo"/>+                </if>+              </choose>+              <text form="short" quotes="true" variable="title"/>+            </group>+          </else-if>+        </choose>+      </if>+      <else>+        <text macro="label-locator"/>+      </else>+    </choose>+  </macro>+  <!-- 4.8. Medium -->+  <macro name="source-medium-bib">+    <group delimiter=", ">+      <text text-case="capitalize-first" variable="medium"/>+      <text variable="scale"/>+      <text variable="dimensions"/>+    </group>+  </macro>+  <!-- 4.9. Archival location -->+  <macro name="source-archive-bib">+    <choose>+      <!-- With `archive_collection` or `archive-place`: physical archives -->+      <if type="graphic">+        <text macro="source-archive-name-first"/>+      </if>+      <else-if match="any" type="collection document manuscript personal_communication" variable="archive_collection archive-place">+        <text macro="source-archive-location-first-bib"/>+      </else-if>+      <!-- Without `archive_collection` or `archive-place`: digital archives (database and identifier) -->+      <else>+        <text macro="source-archive-identifier"/>+      </else>+    </choose>+  </macro>+  <macro name="source-archive-note">+    <choose>+      <!-- With `archive_collection` or `archive-place`: physical archives -->+      <if type="graphic">+        <text macro="source-archive-name-first"/>+      </if>+      <else-if match="any" type="collection document manuscript personal_communication" variable="archive_collection archive-place">+        <text macro="source-archive-location-first-note"/>+      </else-if>+      <!-- Without `archive_collection` or `archive-place`: digital archives (database and identifier) -->+      <else>+        <text macro="source-archive-identifier"/>+      </else>+    </choose>+  </macro>+  <!-- Archival elements -->+  <macro name="source-archive-identifier">+    <choose>+      <if variable="archive archive_location">+        <!-- database identifier: the only example is `thesis`, but presumably this is for all types (CMOS18 14.113) -->+        <group delimiter=" ">+          <text variable="archive"/>+          <text prefix="(" suffix=")" variable="archive_location"/>+        </group>+      </if>+      <else>+        <group delimiter=", ">+          <text variable="archive"/>+          <text variable="archive_location"/>+        </group>+      </else>+    </choose>+  </macro>+  <macro name="source-archive-location-first-bib">+    <!-- Order of elements begins with the most specific (CMOS18 14.119, 14.127) -->+    <!-- In note styles, the bibliography generally provide entries for a `collection` rather than individual items (CMOS18 14.120, 14.128) -->+    <group delimiter=". ">+      <group delimiter=", ">+        <text text-case="capitalize-first" variable="archive_location"/>+        <text variable="archive_collection"/>+      </group>+      <group delimiter=", ">+        <text variable="archive"/>+        <text variable="archive-place"/>+      </group>+    </group>+  </macro>+  <macro name="source-archive-location-first-note">+    <!-- Order of elements begins with the most specific (CMOS18 14.119, 14.127) -->+    <!-- In note styles, the bibliography generally provide entries for a `collection` rather than individual items (CMOS18 14.120, 14.128) -->+    <group delimiter=", ">+      <group delimiter=", ">+        <text variable="archive_location"/>+        <text variable="archive_collection"/>+      </group>+      <group delimiter=", ">+        <text variable="archive"/>+        <text variable="archive-place"/>+      </group>+    </group>+  </macro>+  <macro name="source-archive-name-first">+    <!-- Archive (gallery) name first for art (CMOS18 14.133) -->+    <group delimiter=", ">+      <text variable="archive"/>+      <text variable="archive-place"/>+      <text variable="archive_collection"/>+      <text variable="archive_location"/>+    </group>+  </macro>+  <!-- 4.10. URL or persistent identifier -->+  <macro name="source-date-accessed-DOI-URL-bib">+    <group delimiter=". ">+      <choose>+        <if variable="DOI"/>+        <else-if match="any" variable="available-date event-date issued status"/>+        <else-if variable="accessed URL">+          <group delimiter=" ">+            <text term="accessed" text-case="capitalize-first"/>+            <date form="text" variable="accessed"/>+          </group>+        </else-if>+      </choose>+      <text macro="source-DOI-URL"/>+    </group>+  </macro>+  <macro name="source-DOI-URL">+    <choose>+      <if variable="DOI">+        <text prefix="https://doi.org/" variable="DOI"/>+      </if>+      <else-if variable="URL">+        <text variable="URL"/>+      </else-if>+    </choose>+  </macro>+  <!-- 5. Notes -->+  <!-- TODO: add variables for distributor and exhibitions if available in CSL -->+  <!-- 6. Legal references: Bluebook style (shared with APA) -->+  <!-- Where APA or Chicago diverge from Bluebook, the official manual is followed -->+  <macro name="legal-reference">+    <!-- Type usage:++         `bill`+         : bills, resolutions, federal reports++         `legal_case`+         : all legal and court cases++         `hearing`+         : hearings and testimony++         `legislation`+         : statutes, constitutional items, and charters++         `regulation`+         : codified regulations, uncodified regulations, executive orders++         `treaty`+         : treaties+    -->+    <group delimiter=", ">+      <choose>+        <if type="treaty">+          <text macro="legal-title"/>+          <names variable="author">+            <!-- Treaty parties should be included at least for bilateral treaties (Bluebook 21.4.2) -->+            <name delimiter="-" et-al-min="100" et-al-use-first="99" form="short"/>+          </names>+          <text macro="legal-date"/>+          <!-- treaty source/report in addition to URL (Bluebook 21.4.5) -->+          <text macro="legal-source"/>+        </if>+        <else>+          <group delimiter=" ">+            <group delimiter=", ">+              <text macro="legal-title"/>+              <text macro="legal-source"/>+            </group>+            <text macro="legal-date"/>+            <text macro="legal-identifier"/>+          </group>+        </else>+      </choose>+      <group delimiter=" ">+        <!-- locator for use in notes -->+        <choose>+          <if locator="page" variable="page">+            <text term="at"/>+          </if>+        </choose>+        <text macro="label-locator"/>+      </group>+    </group>+  </macro>+  <!-- 6.1. Legal date -->+  <macro name="legal-date">+    <choose>+      <if type="treaty">+        <text macro="date-issued-full"/>+      </if>+      <else-if type="legal_case">+        <text macro="legal-date-case"/>+      </else-if>+      <else-if match="any" type="bill hearing legislation regulation">+        <group delimiter=" " prefix="(" suffix=")">+          <group delimiter=" ">+            <text macro="date-original-year"/>+            <text form="symbol" term="and"/>+          </group>+          <choose>+            <if variable="issued">+              <text macro="date-issued-year"/>+            </if>+            <else>+              <!-- Show proposal date for uncodified regulations. Assume date is entered literally ala "proposed May 23, 2016". -->+              <!-- TODO: Add `proposed` date here if that becomes available -->+              <date form="text" variable="submitted"/>+            </else>+          </choose>+        </group>+      </else-if>+    </choose>+  </macro>+  <macro name="legal-date-case">+    <group delimiter=" " prefix="(" suffix=")">+      <text variable="authority"/>+      <choose>+        <if variable="container-title">+          <!-- Print only year for cases published in reporters-->+          <text macro="date-issued-year"/>+        </if>+        <else>+          <text macro="date-issued-full"/>+        </else>+      </choose>+    </group>+  </macro>+  <!-- 6.2.1. Legal title -->+  <macro name="legal-title">+    <choose>+      <if match="any" type="bill legal_case legislation regulation treaty">+        <text text-case="title" variable="title"/>+      </if>+      <else-if type="hearing">+        <!-- use standard format (Bluebook 13.3) -->+        <group delimiter=": " font-style="italic">+          <text text-case="capitalize-first" variable="title"/>+          <group delimiter=" ">+            <text term="hearing" text-case="capitalize-first"/>+            <group delimiter=" ">+              <group delimiter=" ">+                <text term="on"/>+                <text variable="number"/>+              </group>+              <group delimiter=" ">+                <text value="before the"/>+                <text variable="section"/>+              </group>+            </group>+          </group>+        </group>+      </else-if>+    </choose>+  </macro>+  <!-- 6.2.2. Legal identifier -->+  <macro name="legal-identifier">+    <choose>+      <if type="hearing">+        <group delimiter=" " prefix="(" suffix=")">+          <!-- Use the 'verb' form of the hearing term to hold 'testimony of' -->+          <text form="verb" term="hearing"/>+          <names variable="author">+            <name and="symbol" initialize="false"/>+          </names>+        </group>+      </if>+      <else-if match="any" type="bill legislation regulation">+        <!-- For uncodified regulations, assume future code section is in `status`. -->+        <text prefix="(" suffix=")" variable="status"/>+      </else-if>+    </choose>+  </macro>+  <macro name="legal-identifier-bill-report">+    <group delimiter=" ">+      <text variable="genre"/>+      <choose>+        <if match="any" variable="authority chapter-number container-title">+          <text variable="number"/>+        </if>+        <else>+          <!-- If there is no legislative body, session number, or code/record title, assume the item is a congressional report and include 'No.' label. -->+          <text macro="label-number-capitalized"/>+        </else>+      </choose>+    </group>+  </macro>+  <!-- 6.3. Legal source -->+  <macro name="legal-source">+    <!-- Expect legal item `container-title` to be stored in short form -->+    <choose>+      <if type="bill">+        <text macro="legal-source-bill"/>+      </if>+      <else-if type="hearing">+        <text macro="legal-source-hearing"/>+      </else-if>+      <else-if type="legal_case">+        <text macro="legal-source-case"/>+      </else-if>+      <else-if type="legislation">+        <text macro="legal-source-legislation"/>+      </else-if>+      <else-if type="regulation">+        <text macro="legal-source-regulation"/>+      </else-if>+      <else-if type="treaty">+        <text macro="legal-source-treaty"/>+      </else-if>+    </choose>+  </macro>+  <!-- Legal source types -->+  <macro name="legal-source-bill">+    <group delimiter=", ">+      <text macro="legal-identifier-bill-report"/>+      <group delimiter=" ">+        <text variable="authority"/>+        <!-- `chapter-number` is a session number -->+        <text variable="chapter-number"/>+      </group>+      <group delimiter=" ">+        <text variable="volume"/>+        <text variable="container-title"/>+        <text variable="page-first"/>+      </group>+    </group>+  </macro>+  <macro name="legal-source-case">+    <group delimiter=" ">+      <choose>+        <if variable="container-title">+          <group delimiter=" ">+            <text variable="volume"/>+            <text variable="container-title"/>+            <text macro="label-section-symbol"/>+            <choose>+              <if match="any" variable="page page-first">+                <text variable="page-first"/>+              </if>+              <else>+                <text value="___"/>+              </else>+            </choose>+          </group>+        </if>+        <else>+          <text macro="label-number-capitalized"/>+        </else>+      </choose>+    </group>+  </macro>+  <macro name="legal-source-hearing">+    <group delimiter=" ">+      <text variable="authority"/>+      <!-- `chapter-number` is a session number -->+      <text variable="chapter-number"/>+    </group>+  </macro>+  <macro name="legal-source-legislation">+    <choose>+      <if variable="number">+        <!-- `number` is a public law number -->+        <group delimiter=", ">+          <group delimiter=" ">+            <choose>+              <if variable="genre">+                <text text-case="capitalize-first" variable="genre"/>+              </if>+              <else>+                <text form="short" term="legislation" text-case="capitalize-first"/>+              </else>+            </choose>+            <text macro="label-number-capitalized"/>+          </group>+          <group delimiter=" ">+            <text variable="volume"/>+            <text variable="container-title"/>+            <text variable="page-first"/>+          </group>+        </group>+      </if>+      <else>+        <group delimiter=" ">+          <text variable="volume"/>+          <text variable="container-title"/>+          <choose>+            <if variable="section">+              <text macro="label-section-symbol"/>+            </if>+            <else>+              <text variable="page-first"/>+            </else>+          </choose>+        </group>+      </else>+    </choose>+  </macro>+  <macro name="legal-source-regulation">+    <group delimiter=", ">+      <group delimiter=" ">+        <text variable="genre"/>+        <text macro="label-number-capitalized"/>+      </group>+      <group delimiter=" ">+        <text variable="volume"/>+        <text variable="container-title"/>+        <choose>+          <if variable="section">+            <text macro="label-section-symbol"/>+          </if>+          <else>+            <text variable="page-first"/>+          </else>+        </choose>+      </group>+    </group>+  </macro>+  <macro name="legal-source-treaty">+    <group delimiter=" ">+      <number variable="volume"/>+      <text variable="container-title"/>+      <choose>+        <if match="any" variable="page page-first">+          <text variable="page-first"/>+        </if>+        <else>+          <text macro="label-number-capitalized"/>+        </else>+      </choose>+    </group>+  </macro>+  <!-- Citation -->+  <macro name="citation-author-date-item">+    <group delimiter=", ">+      <choose>+        <if type="classic">+          <text macro="author-inline"/>+          <choose>+            <if variable="author">+              <text macro="title-and-descriptions-short"/>+            </if>+          </choose>+        </if>+        <else-if match="any" variable="event-date issued">+          <choose>+            <if match="any" type="interview personal_communication">+              <choose>+                <if match="any" variable="archive archive-place container-title DOI number publisher references URL">+                  <group delimiter=" ">+                    <text macro="author-inline"/>+                    <text macro="date-short"/>+                  </group>+                </if>+                <else>+                  <!-- unpublished `interview` or `personal_communication` use inline format (CMOS18 14.111) -->+                  <text macro="author-inline"/>+                  <text macro="title-and-descriptions-short"/>+                  <text macro="date-short"/>+                </else>+              </choose>+            </if>+            <else>+              <group delimiter=" ">+                <text macro="author-inline"/>+                <text macro="date-short"/>+              </group>+            </else>+          </choose>+        </else-if>+        <else>+          <!--- Comma with forthcoming or n.d. -->+          <text macro="author-inline"/>+          <choose>+            <if match="any" type="interview personal_communication">+              <choose>+                <if match="none" variable="archive archive-place container-title DOI number publisher references URL">+                  <!-- unpublished `interview` or `personal_communication` use inline format (CMOS18 14.111) -->+                  <text macro="title-and-descriptions-short"/>+                </if>+              </choose>+            </if>+          </choose>+          <text macro="date-short"/>+        </else>+      </choose>+    </group>+  </macro>+  <citation after-collapse-delimiter="; " collapse="year" disambiguate-add-givenname="true" disambiguate-add-names="true" disambiguate-add-year-suffix="true" et-al-min="3" et-al-use-first="1">+    <layout delimiter="; " prefix="(" suffix=")">+      <choose>+        <if type="classic">+          <!-- with `classic`, a non-numeric canonical reference or identifying number is separated by a space rather than a comma (CMOS18 14.145) -->+          <choose>+            <if is-numeric="locator">+              <group delimiter=", ">+                <text macro="citation-author-date-item"/>+                <text macro="source-locator-author-date"/>+              </group>+            </if>+            <else-if locator="chapter line verse" match="any">+              <group delimiter=" ">+                <text macro="citation-author-date-item"/>+                <text macro="source-locator-author-date"/>+              </group>+            </else-if>+            <else>+              <group delimiter=", ">+                <text macro="citation-author-date-item"/>+                <text macro="source-locator-author-date"/>+              </group>+            </else>+          </choose>+        </if>+        <else>+          <group delimiter=", ">+            <text macro="citation-author-date-item"/>+            <text macro="source-locator-author-date"/>+          </group>+        </else>+      </choose>+    </layout>+  </citation>+  <!-- Bibliography -->+  <macro name="bibliography-author-date">+    <group delimiter=". ">+      <choose>+        <if match="any" type="bill hearing legal_case legislation regulation treaty">+          <!-- Legal items have different orders and delimiters -->+          <text macro="legal-reference"/>+          <text macro="source-date-accessed-DOI-URL-bib"/>+          <text variable="references"/>+        </if>+        <else>+          <text macro="author-bib"/>+          <text macro="date"/>+          <text macro="title-and-source-bib"/>+          <text variable="references"/>+        </else>+      </choose>+    </group>+  </macro>+  <bibliography et-al-min="7" et-al-use-first="3" hanging-indent="true">+    <sort>+      <key macro="author-sort"/>+      <key macro="date-sort-group"/>+      <key macro="date-sort-year"/>+      <key macro="date"/>+      <key macro="title-and-descriptions-bib"/>+      <key macro="source-bib"/>+      <key variable="volume"/>+      <key variable="part-number"/>+      <key variable="event-date"/>+      <key variable="issued"/>+      <key macro="source-archive-bib"/>+    </sort>+    <layout suffix=".">+      <choose>+        <if type="classic">+          <choose>+            <if match="any" variable="archive editor translator publisher">+              <text macro="bibliography-author-date"/>+            </if>+          </choose>+        </if>+        <else-if match="any" type="entry entry-dictionary entry-encyclopedia">+          <choose>+            <if variable="author">+              <!-- Signed reference entries appear in the bibliography (CMOS18 14.132) -->+              <text macro="bibliography-author-date"/>+            </if>+            <else-if match="any" variable="DOI URL">+              <!-- Provide a bibliography if necessary identifying information is not in text -->+              <text macro="bibliography-author-date"/>+            </else-if>+          </choose>+        </else-if>+        <else-if match="any" type="interview personal_communication">+          <choose>+            <if match="any" variable="archive archive-place container-title DOI number publisher references URL">+              <!-- Personal communications only appear in the bibliography if the reader can retrieve them (CMOS18 14.13, 14.111) -->+              <text macro="bibliography-author-date"/>+            </if>+          </choose>+        </else-if>+        <else>+          <text macro="bibliography-author-date"/>+        </else>+      </choose>     </layout>   </bibliography> </style>
data/docx/word/styles.xml view
@@ -3,10 +3,10 @@   <w:docDefaults>     <w:rPrDefault>       <w:rPr>-        <w:rFonts w:asciiTheme="minorHAnsi" w:eastAsiaTheme="minorHAnsi" w:hAnsiTheme="minorHAnsi" w:cstheme="minorBidi" />+        <w:rFonts w:asciiTheme="minorHAnsi" w:eastAsiaTheme="minorEastAsia" w:hAnsiTheme="minorHAnsi" w:cstheme="minorBidi" />         <w:sz w:val="24" />         <w:szCs w:val="24" />-        <w:lang w:val="en-US" w:eastAsia="en-US" w:bidi="ar-SA" />+        <w:lang w:val="en-US" w:eastAsia="zh-CN" w:bidi="ar-SA" />       </w:rPr>     </w:rPrDefault>     <w:pPrDefault>@@ -604,13 +604,6 @@       </w:tblCellMar>     </w:tblPr>     <w:tblStylePr w:type="firstRow">-      <w:tblPr>-        <w:jc w:val="left"/>-        <w:tblInd w:w="0" w:type="dxa"/>-      </w:tblPr>-      <w:trPr>-        <w:jc w:val="left"/>-      </w:trPr>       <w:tcPr>         <w:tcBorders>           <w:bottom w:val="single"/>
data/templates/common.latex view
@@ -234,6 +234,12 @@   \newenvironment{RTL}{\beginR}{\endR}   \newenvironment{LTR}{\beginL}{\endL} \fi+\ifluatex+  \newcommand{\RL}[1]{\bgroup\textdir TRT#1\egroup}+  \newcommand{\LR}[1]{\bgroup\textdir TLT#1\egroup}+  \newenvironment{RTL}{\textdir TRT\pardir TRT\bodydir TRT}{}+  \newenvironment{LTR}{\textdir TLT\pardir TLT\bodydir TLT}{}+\fi $endif$ $-- $-- bibliography support support for natbib and biblatex
data/templates/default.latex view
@@ -24,6 +24,9 @@ \usepackage[$for(geometry)$$geometry$$sep$,$endfor$]{geometry} $endif$ \usepackage{amsmath,amssymb}+$if(cancel)$+\usepackage{cancel}+$endif$ $-- $-- section numbering $--@@ -40,7 +43,20 @@ $endfor$ $after-header-includes.latex()$ $hypersetup.latex()$+$if(pdf-trailer-id)$ +\ifXeTeX+\special{pdf:trailerid [ $pdf-trailer-id$ ]}+\fi+\ifPDFTeX+\pdftrailerid{}+\pdftrailer{/ID [ $pdf-trailer-id$ ]}+\fi+\ifLuaTeX+\pdfvariable trailerid {[ $pdf-trailer-id$ ]}+\fi+$endif$+ $if(title)$ \title{$title$$if(thanks)$\thanks{$thanks$}$endif$} $endif$@@ -79,7 +95,9 @@ $endif$ { $if(colorlinks)$-\hypersetup{linkcolor=$if(toccolor)$$toccolor$$else$$endif$}+$if(toccolor)$+\hypersetup{linkcolor=$toccolor$}+$endif$ $endif$ \setcounter{tocdepth}{$toc-depth$} \tableofcontents
data/templates/default.org view
@@ -9,6 +9,12 @@ #+date: $date$  $endif$+$if(options/pairs)$+$for(options/pairs)$+#+options: ${it.key}:${it.value}+$endfor$++$endif$ $for(header-includes)$ $header-includes$ 
data/templates/default.typst view
@@ -71,9 +71,15 @@ $if(region)$   region: "$region$", $endif$+$if(abstract-title)$+  abstract-title: [$abstract-title$],+$endif$ $if(abstract)$   abstract: [$abstract$], $endif$+$if(thanks)$+  thanks: [$thanks$],+$endif$ $if(margin)$   margin: ($for(margin/pairs)$$margin.key$: $margin.value$,$endfor$), $endif$@@ -86,10 +92,28 @@ $if(fontsize)$   fontsize: $fontsize$, $endif$+$if(mathfont)$+  mathfont: ($for(mathfont)$"$mathfont$",$endfor$),+$endif$+$if(codefont)$+  codefont: ($for(codefont)$"$codefont$",$endfor$),+$endif$+$if(linestretch)$+  linestretch: $linestretch$,+$endif$ $if(section-numbering)$   sectionnumbering: "$section-numbering$", $endif$   pagenumbering: $if(page-numbering)$"$page-numbering$"$else$none$endif$,+$if(linkcolor)$+  linkcolor: [$linkcolor$],+$endif$+$if(citecolor)$+  citecolor: [$citecolor$],+$endif$+$if(filecolor)$+  filecolor: [$filecolor$],+$endif$   cols: $if(columns)$$columns$$else$1$endif$,   doc, )@@ -108,6 +132,9 @@ $body$  $if(citations)$+$for(nocite-ids)$+#cite(label("${it}"), form: none)+$endfor$ $if(csl)$  #set bibliography(style: "$csl$")@@ -117,7 +144,7 @@ $endif$ $if(bibliography)$ -#bibliography($for(bibliography)$"$bibliography$"$sep$,$endfor$)+#bibliography($for(bibliography)$"$bibliography$"$sep$,$endfor$$if(full-bibliography)$, full: true$endif$) $endif$ $endif$ $for(include-after)$
data/templates/styles.html view
@@ -1,3 +1,6 @@+/* Default styles provided by pandoc.+** See https://pandoc.org/MANUAL.html#variables-for-html for config info.+*/ $if(document-css)$ html { $if(mainfont)$
data/templates/template.typst view
@@ -15,7 +15,9 @@   authors: (),   keywords: (),   date: none,+  abstract-title: none,   abstract: none,+  thanks: none,   cols: 1,   margin: (x: 1.25in, y: 1.25in),   paper: "us-letter",@@ -23,66 +25,92 @@   region: "US",   font: (),   fontsize: 11pt,+  mathfont: none,+  codefont: none,+  linestretch: 1,   sectionnumbering: none,+  linkcolor: none,+  citecolor: none,+  filecolor: none,   pagenumbering: "1",   doc, ) = {   set document(     title: title,-    author: authors.map(author => content-to-string(author.name)),     keywords: keywords,   )+  set document(+      author: authors.map(author => content-to-string(author.name)).join(", ", last: " & "),+  ) if authors != none and authors != ()   set page(     paper: paper,     margin: margin,     numbering: pagenumbering,-    columns: cols,-    )-  set par(justify: true)+  )++  set par(+    justify: true,+    leading: linestretch * 0.65em+  )   set text(lang: lang,            region: region,            font: font,            size: fontsize)++  show math.equation: set text(font: mathfont) if mathfont != none+  show raw: set text(font: codefont) if codefont != none+   set heading(numbering: sectionnumbering) -  place(top, float: true, scope: "parent", clearance: 4mm)[-  #if title != none {-    align(center)[#block(inset: 2em)[-      #text(weight: "bold", size: 1.5em)[#title]-      #(if subtitle != none {-        parbreak()-        text(weight: "bold", size: 1.25em)[#subtitle]-      })-    ]]+  show link: set text(fill: rgb(content-to-string(linkcolor))) if linkcolor != none+  show ref: set text(fill: rgb(content-to-string(citecolor))) if citecolor != none+  show link: this => {+    if filecolor != none and type(this.dest) == label {+      text(this, fill: rgb(content-to-string(filecolor)))+    }   } -  #if authors != none and authors != [] {-    let count = authors.len()-    let ncols = calc.min(count, 3)-    grid(-      columns: (1fr,) * ncols,-      row-gutter: 1.5em,-      ..authors.map(author =>-          align(center)[-            #author.name \-            #author.affiliation \-            #author.email-          ]+  block(below: 4mm)[+    #if title != none {+      align(center)[#block(inset: 2em)[+          #text(weight: "bold", size: 1.5em)[#title #if thanks != none {+              footnote(thanks, numbering: "*")+              counter(footnote).update(n => n - 1)+            }]+          #(+            if subtitle != none {+              parbreak()+              text(weight: "bold", size: 1.25em)[#subtitle]+            }+          )+        ]]+    }++    #if authors != none and authors != [] {+      let count = authors.len()+      let ncols = calc.min(count, 3)+      grid(+        columns: (1fr,) * ncols,+        row-gutter: 1.5em,+        ..authors.map(author => align(center)[+          #author.name \+          #author.affiliation \+          #author.email+        ])       )-    )-  }+    } -  #if date != none {-    align(center)[#block(inset: 1em)[-      #date-    ]]-  }+    #if date != none {+      align(center)[#block(inset: 1em)[+          #date+        ]]+    } -  #if abstract != none {-    block(inset: 2em)[-    #text(weight: "semibold")[Abstract] #h(1em) #abstract-    ]-  }+    #if abstract != none {+      block(inset: 2em)[+        #text(weight: "semibold")[#abstract-title] #h(1em) #abstract+      ]+    }   ]    doc
pandoc.cabal view
@@ -1,6 +1,6 @@ cabal-version:   2.4 name:            pandoc-version:         3.7.0.2+version:         3.8 build-type:      Simple license:         GPL-2.0-or-later license-file:    COPYING.md@@ -218,10 +218,12 @@                  test/command/*.md                  test/command/*.csl                  test/command/*.svg+                 test/command/7691.docx                  test/command/9391.docx                  test/command/9358.docx                  test/command/9002.docx                  test/command/9603.docx+                 test/command/11113.docx                  test/command/biblio.bib                  test/command/averroes.bib                  test/command/A.txt@@ -231,6 +233,7 @@                  test/command/file1.txt                  test/command/file2.txt                  test/command/three.txt+                 test/command/11090/ch1.typ                  test/command/01.csv                  test/command/chap1/spider.png                  test/command/chap2/spider.png@@ -450,7 +453,7 @@                     -Wpartial-fields                     -Wmissing-signatures                     -fhide-source-paths-                    -- -Wmissing-export-lists+                    -Wmissing-export-lists    if impl(ghc >= 8.10)     ghc-options:    -Wunused-packages@@ -495,7 +498,7 @@                  blaze-markup          >= 0.8      && < 0.9,                  bytestring            >= 0.9      && < 0.13,                  case-insensitive      >= 1.2      && < 1.3,-                 citeproc              >= 0.9.0.1  && < 0.10,+                 citeproc              >= 0.10     && < 0.11,                  commonmark            >= 0.2.6.1  && < 0.3,                  commonmark-extensions >= 0.2.6    && < 0.3,                  commonmark-pandoc     >= 0.2.3    && < 0.3,@@ -505,7 +508,7 @@                  data-default          >= 0.4      && < 0.9,                  deepseq               >= 1.3      && < 1.6,                  directory             >= 1.2.3    && < 1.4,-                 doclayout             >= 0.5      && < 0.6,+                 doclayout             >= 0.5.0.1  && < 0.6,                  doctemplates          >= 0.11     && < 0.12,                  emojis                >= 0.1.4.1  && < 0.2,                  exceptions            >= 0.8      && < 0.11,@@ -530,24 +533,25 @@                  random                >= 1.2      && < 1.4,                  safe                  >= 0.3.18   && < 0.4,                  scientific            >= 0.3      && < 0.4,-                 skylighting           >= 0.14.5   && < 0.15,-                 skylighting-core      >= 0.14.5   && < 0.15,+                 skylighting           >= 0.14.7   && < 0.15,+                 skylighting-core      >= 0.14.7   && < 0.15,                  split                 >= 0.2      && < 0.3,                  syb                   >= 0.1      && < 0.8,                  tagsoup               >= 0.14.6   && < 0.15,                  temporary             >= 1.1      && < 1.4,-                 texmath               >= 0.12.10.3 && < 0.13,+                 texmath               >= 0.13     && < 0.14,                  text                  >= 1.1.1.0  && < 2.2,                  text-conversions      >= 0.3      && < 0.4,-                 time                  >= 1.5      && < 1.15,+                 time                  >= 1.5      && < 1.16,                  unicode-collation     >= 0.1.1    && < 0.2,+                 unicode-data          >= 0.6      && < 0.7,                  unicode-transforms    >= 0.3      && < 0.5,                  yaml                  >= 0.11     && < 0.12,                  libyaml               >= 0.1.4    && < 0.2,                  zip-archive           >= 0.4.3.1  && < 0.5,                  zlib                  >= 0.5      && < 0.8,                  xml                   >= 1.3.12   && < 1.4,-                 typst                 >= 0.8.0.1  && < 0.9,+                 typst                 >= 0.8.0.2  && < 0.9,                  vector                >= 0.12     && < 0.14,                  djot                  >= 0.1.2.2  && < 0.2,                  tls                   >= 2.0.1    && < 2.2,@@ -613,6 +617,7 @@                    Text.Pandoc.Readers.Pod,                    Text.Pandoc.Writers,                    Text.Pandoc.Writers.Native,+                   Text.Pandoc.Writers.XML,                    Text.Pandoc.Writers.DocBook,                    Text.Pandoc.Writers.JATS,                    Text.Pandoc.Writers.OPML,@@ -743,6 +748,7 @@                    Text.Pandoc.Readers.Metadata,                    Text.Pandoc.Readers.Roff,                    Text.Pandoc.Readers.Roff.Escape,+                   Text.Pandoc.Readers.XML,                    Text.Pandoc.Writers.Docx.OpenXML,                    Text.Pandoc.Writers.Docx.StyleMap,                    Text.Pandoc.Writers.Docx.Table,@@ -768,6 +774,7 @@                    Text.Pandoc.Char,                    Text.Pandoc.TeX,                    Text.Pandoc.URI,+                   Text.Pandoc.XMLFormat,                    Text.Pandoc.CSS,                    Text.Pandoc.CSV,                    Text.Pandoc.RoffChar,@@ -806,7 +813,7 @@                   tasty-quickcheck  >= 0.8     && < 0.12,                   text              >= 1.1.1.0 && < 2.2,                   temporary         >= 1.1     && < 1.4,-                  time              >= 1.5     && < 1.15,+                  time              >= 1.5     && < 1.16,                   xml               >= 1.3.12  && < 1.4,                   zip-archive       >= 0.4.3   && < 0.5   other-modules:  Tests.Old@@ -814,6 +821,7 @@                   Tests.Helpers                   Tests.Shared                   Tests.MediaBag+                  Tests.XML                   Tests.Readers.LaTeX                   Tests.Readers.HTML                   Tests.Readers.JATS
src/Text/Pandoc/App.hs view
@@ -26,6 +26,7 @@           , parseOptionsFromArgs           , options           , applyFilters+          , versionInfo           ) where import qualified Control.Exception as E import Control.Monad ( (>=>), when, forM, forM_ )@@ -41,11 +42,12 @@ import qualified Data.Text.Lazy.Encoding as TE import qualified Data.Text.Encoding.Error as TE import Data.Char (toLower)-import System.Directory (doesDirectoryExist, createDirectory)+import System.Directory (doesDirectoryExist, createDirectory,+                         createDirectoryIfMissing) import Codec.Archive.Zip (toArchiveOrFail,                           extractFilesFromArchive, ZipOption(..)) import System.Exit (exitSuccess)-import System.FilePath ( takeBaseName, takeExtension)+import System.FilePath ( takeBaseName, takeExtension, takeDirectory) import System.IO (nativeNewline, stdout) import qualified System.IO as IO (Newline (..)) import Text.Pandoc@@ -55,7 +57,7 @@ import Text.Pandoc.App.Opt (Opt (..), LineEnding (..), defaultOpts,                             IpynbOutput (..), OptInfo(..)) import Text.Pandoc.App.CommandLineOptions (parseOptions, parseOptionsFromArgs,-                                           options, handleOptInfo)+                                           options, handleOptInfo, versionInfo) import Text.Pandoc.App.Input (InputParameters (..), readInput) import Text.Pandoc.App.OutputSettings (OutputSettings (..), optToOutputSettings,                                        sandbox')@@ -115,11 +117,14 @@                      CRLF   -> IO.CRLF                      LF     -> IO.LF                      Native -> nativeNewline+      let outputFileDir = takeDirectory outputFile+      createDirectoryIfMissing True outputFileDir       case output of         TextOutput t    -> writerFn eol outputFile t         BinaryOutput bs -> writeFnBinary outputFile bs         ZipOutput bs-          | null (takeExtension outputFile) -> do+          | null (takeExtension outputFile)+          , outputFile /= "-" -> do              -- create directory and unzip              createDirectory outputFile -- will fail if directory exists              let zipopts = [OptRecursive, OptDestination outputFile] ++
src/Text/Pandoc/App/CommandLineOptions.hs view
@@ -21,6 +21,7 @@           , options           , engines           , setVariable+          , versionInfo           ) where import Control.Monad.Trans import Control.Monad.State.Strict@@ -46,6 +47,7 @@ import Text.DocTemplates (Context (..), ToContext (toVal), Val (..)) import Text.Pandoc import Text.Pandoc.Builder (setMeta)+import Data.Version (showVersion) import Text.Pandoc.App.Opt (Opt (..), LineEnding (..), IpynbOutput (..),                             DefaultsState (..), applyDefaults,                             fullDefaultsPath, OptInfo(..))@@ -193,14 +195,7 @@                      ,"text-styles"])                   ,confNumFormat = Generic                   ,confTrailingNewline = True} sty-    VersionInfo -> do-      prg <- getProgName-      defaultDatadir <- defaultUserDataDir-      UTF8.hPutStrLn stdout-       $ T.pack-       $ prg ++ " " ++ T.unpack pandocVersionText ++-         "\nUser data directory: " ++ defaultDatadir ++-         ('\n':copyrightMessage)+    VersionInfo -> versionInfo [] Nothing ""     Help -> do       prg <- getProgName       UTF8.hPutStr stdout (T.pack $ usageMessage prg options)@@ -210,7 +205,8 @@ -- | Supported LaTeX engines; the first item is used as default engine -- when going through LaTeX. latexEngines :: [String]-latexEngines  = ["pdflatex", "lualatex", "xelatex", "latexmk", "tectonic"]+latexEngines  = [ "pdflatex", "lualatex", "xelatex", "latexmk", "tectonic"+                , "pdflatex-dev", "lualatex-dev" ]  -- | Supported HTML PDF engines; the first item is used as default -- engine when going through HTML.@@ -524,13 +520,18 @@      , Option "" ["no-highlight"]                 (NoArg-                 (\opt -> return opt { optHighlightStyle = Nothing }))+                 (\opt -> do+                     deprecatedOption "--no-highlight"+                       "Use --syntax-highlighting=none instead."+                     return opt { optSyntaxHighlighting = NoHighlightingString }))                  "" -- "Don't highlight source code"      , Option "" ["highlight-style"]                 (ReqArg-                 (\arg opt ->-                     return opt{ optHighlightStyle = Just $+                 (\arg opt -> do+                     deprecatedOption "--highlight-style"+                       "Use --syntax-highlighting instead."+                     return opt{ optSyntaxHighlighting =                                  T.pack $ normalizePath arg })                  "STYLE|FILE")                  "" -- "Style for highlighted code"@@ -543,6 +544,14 @@                  "FILE")                 "" -- "Syntax definition (xml) file" +    , Option "" ["syntax-highlighting"]+                (ReqArg+                 (\arg opt -> return opt{ optSyntaxHighlighting =+                                 T.pack $ normalizePath arg })+                 "none|default|idiomatic|<stylename>|<themepath>")+                 "" -- "syntax highlighting method for code"++     , Option "" ["dpi"]                  (ReqArg                   (\arg opt ->@@ -602,8 +611,8 @@                         then return opt { optPdfEngine = Just arg }                         else optError $                               PandocOptionError $ T.pack $-                              "Argument of --pdf-engine must be one of "-                               ++ intercalate ", " pdfEngines)+                              "Argument of --pdf-engine must be one of\n"+                               ++ concatMap (\e -> "\t" <> e <> "\n") pdfEngines)                   "PROGRAM")                  "" -- "Name of program to use in generating PDF" @@ -813,8 +822,14 @@     , Option "" ["listings"]                  (OptArg                   (\arg opt -> do-                        boolValue <- readBoolFromOptArg "--listings" arg-                        return opt { optListings = boolValue })+                      deprecatedOption "--listings"+                        "Use --syntax-highlighting=idiomatic instead."+                      boolValue <- readBoolFromOptArg "--listings" arg+                      return $+                        if boolValue+                        then opt { optSyntaxHighlighting =+                                   IdiomaticHighlightingString }+                        else opt)                   "true|false")                  "" -- "Use listings package for LaTeX code blocks" @@ -1027,8 +1042,8 @@     , Option "" ["webtex"]                  (OptArg                   (\arg opt -> do-                      let url' = fromMaybe "https://latex.codecogs.com/png.latex?" arg-                      return opt { optHTMLMathMethod = WebTeX $ T.pack url' })+                      let url' = maybe defaultWebTeXURL T.pack arg+                      return opt { optHTMLMathMethod = WebTeX url' })                   "URL")                  "" -- "Use web service for HTML math" @@ -1172,7 +1187,7 @@  copyrightMessage :: String copyrightMessage = intercalate "\n" [- "Copyright (C) 2006-2024 John MacFarlane. Web:  https://pandoc.org",+ "Copyright (C) 2006-2025 John MacFarlane. Web:  https://pandoc.org",  "This is free software; see the source for copying conditions. There is no",  "warranty, not even for merchantability or fitness for a particular purpose." ] @@ -1270,3 +1285,21 @@ #else normalizePath = id #endif++-- | Print version information with customizable features and scripting engine+versionInfo :: [String] -> Maybe String -> String -> IO ()+versionInfo features mbScriptingEngineName suffix = do+  defaultDatadir <- defaultUserDataDir+  let featuresLine = if null features+                       then []+                       else ["Features: " ++ unwords features]+  let scriptingLine = case mbScriptingEngineName of+                        Nothing -> []+                        Just name -> ["Scripting engine: " ++ name]+  UTF8.putStr $ T.unlines $ map T.pack $+    ["pandoc " ++ showVersion pandocVersion ++ suffix] +++    featuresLine +++    scriptingLine +++    ["User data directory: " ++ defaultDatadir,+     copyrightMessage]+  exitSuccess
src/Text/Pandoc/App/Input.hs view
@@ -14,7 +14,7 @@   , readInput   ) where -import Control.Monad ((>=>))+import Control.Monad ((>=>), when) import Control.Monad.Except (throwError, catchError) import Data.Text (Text) import Network.URI (URI (..), parseURI)@@ -109,12 +109,29 @@                            (toTextM fp bs)                            (\case                               PandocUTF8DecodingError{} -> do+                                when (hasKnownSignature bs) $+                                  throwError $+                                    PandocInputNotTextError (T.pack fp)                                 report $ NotUTF8Encoded                                   (if null fp                                       then "input"                                       else fp)                                 return $ T.pack $ B8.unpack bs                               e -> throwError e)+ where+  -- "50 4B 03 04" is zip file signature+  isZip bs' = "\x50\x4B\x03\x04" `BS.isPrefixOf` bs'+  -- "25 50 44 46 2D" is PDF file signature+  isPDF bs' = "\x25\x50\x44\x46\x2D" `BS.isPrefixOf` bs'+  -- "D0 CF 11 E0 A1 B1 1A E1" is Compound File Binary Format signature used in+  -- variety of old Microsoft formats (.doc and .xls among others)+  isCFBF bs' = "\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1" `BS.isPrefixOf` bs'+  -- "41 54 26 54 46 4F 52 4D ?? ?? ?? ?? 44 4A 56" is DjVu signature+  isDjVu bs' = case BS.stripPrefix "\x41\x54\x26\x54\x46\x4F\x52\x4D" bs' of+    Nothing -> False+    Just x -> BS.isPrefixOf "\x44\x4A\x56" $ BS.drop 4 x++  hasKnownSignature bs' = any ($ bs') [isZip, isPDF, isCFBF, isDjVu]  inputToLazyByteString :: (FilePath, (BS.ByteString, Maybe MimeType))                       -> BL.ByteString
src/Text/Pandoc/App/Opt.hs view
@@ -2,6 +2,7 @@ {-# LANGUAGE OverloadedStrings   #-} {-# LANGUAGE CPP                 #-} {-# LANGUAGE DeriveGeneric       #-}+{-# LANGUAGE PatternSynonyms     #-} {-# LANGUAGE TemplateHaskell     #-} {-# LANGUAGE FlexibleInstances   #-} {-# LANGUAGE FlexibleContexts    #-}@@ -43,7 +44,8 @@                             ReferenceLocation (EndOfDocument),                             CaptionPosition (..),                             ObfuscationMethod (NoObfuscation),-                            CiteMethod (Citeproc))+                            CiteMethod (Citeproc),+                            pattern DefaultHighlightingString) import Text.Pandoc.Class (readFileStrict, fileExists, setVerbosity, report,                           PandocMonad(lookupEnv), getUserDataDir) import Text.Pandoc.Error (PandocError (PandocParseError, PandocSomeError))@@ -124,8 +126,8 @@     , optEmbedResources        :: Bool    -- ^ Make HTML accessible offline     , optLinkImages            :: Bool    -- ^ Link ODT images rather than embedding     , optHtmlQTags             :: Bool    -- ^ Use <q> tags in HTML-    , optHighlightStyle        :: Maybe Text -- ^ Style to use for highlighted code     , optSyntaxDefinitions     :: [FilePath]  -- ^ xml syntax defs to load+    , optSyntaxHighlighting    :: Text -- ^ Syntax highlighting method for code     , optTopLevelDivision      :: TopLevelDivision -- ^ Type of the top-level divisions     , optHTMLMathMethod        :: HTMLMathMethod -- ^ Method to print HTML math     , optAbbreviations         :: Maybe FilePath -- ^ Path to abbrevs file@@ -157,7 +159,6 @@     , optIndentedCodeClasses   :: [Text] -- ^ Default classes for indented code blocks     , optDataDir               :: Maybe FilePath     , optCiteMethod            :: CiteMethod -- ^ Method to output cites-    , optListings              :: Bool       -- ^ Use listings package for code blocks     , optPdfEngine             :: Maybe String -- ^ Program to use for latex/html -> pdf     , optPdfEngineOpts         :: [String]   -- ^ Flags to pass to the engine     , optSlideLevel            :: Maybe Int  -- ^ Header level that creates slides@@ -211,8 +212,8 @@        <*> o .:? "embed-resources" .!= optEmbedResources defaultOpts        <*> o .:? "link-images" .!= optLinkImages defaultOpts        <*> o .:? "html-q-tags" .!= optHtmlQTags defaultOpts-       <*> o .:? "highlight-style"        <*> o .:? "syntax-definitions" .!= optSyntaxDefinitions defaultOpts+       <*> o .:? "syntax-highlighting" .!= optSyntaxHighlighting defaultOpts        <*> o .:? "top-level-division" .!= optTopLevelDivision defaultOpts        <*> o .:? "html-math-method" .!= optHTMLMathMethod defaultOpts        <*> o .:? "abbreviations"@@ -245,7 +246,6 @@        <*> o .:? "indented-code-classes" .!= optIndentedCodeClasses defaultOpts        <*> o .:? "data-dir"        <*> o .:? "cite-method" .!= optCiteMethod defaultOpts-       <*> o .:? "listings" .!= optListings defaultOpts        <*> o .:? "pdf-engine"        <*> o .:? "pdf-engine-opts" .!= optPdfEngineOpts defaultOpts        <*> o .:? "slide-level"@@ -319,6 +319,7 @@     , optOutputFile            = oOutputFile     , optInputFiles            = oInputFiles     , optSyntaxDefinitions     = oSyntaxDefinitions+    , optSyntaxHighlighting    = oSyntaxHighlighting     , optAbbreviations         = oAbbreviations     , optReferenceDoc          = oReferenceDoc     , optEpubMetadata          = oEpubMetadata@@ -337,7 +338,6 @@     , optBibliography          = oBibliography     , optCitationAbbreviations = oCitationAbbreviations     , optPdfEngine             = oPdfEngine-    , optHighlightStyle        = oHighlightStyle     }   = do       oTo' <- mapM (fmap T.pack . resolveVars . T.unpack) oTo@@ -365,7 +365,7 @@       oBibliography' <- mapM resolveVars oBibliography       oCitationAbbreviations' <- mapM resolveVars oCitationAbbreviations       oPdfEngine' <- mapM resolveVars oPdfEngine-      oHighlightStyle' <- mapM (fmap T.pack . resolveVars . T.unpack) oHighlightStyle+      oSyntaxHighlighting' <- T.pack <$> resolveVars (T.unpack oSyntaxHighlighting)       return opt{ optTo                    = oTo'                 , optFrom                  = oFrom'                 , optTemplate              = oTemplate'@@ -373,6 +373,7 @@                 , optOutputFile            = oOutputFile'                 , optInputFiles            = oInputFiles'                 , optSyntaxDefinitions     = oSyntaxDefinitions'+                , optSyntaxHighlighting    = oSyntaxHighlighting'                 , optAbbreviations         = oAbbreviations'                 , optReferenceDoc          = oReferenceDoc'                 , optEpubMetadata          = oEpubMetadata'@@ -391,7 +392,6 @@                 , optBibliography          = oBibliography'                 , optCitationAbbreviations = oCitationAbbreviations'                 , optPdfEngine             = oPdfEngine'-                , optHighlightStyle        = oHighlightStyle'                 }   where@@ -555,8 +555,9 @@       parseJSON v >>= \x -> return (\o -> o{ optLinkImages = x })     "html-q-tags" ->       parseJSON v >>= \x -> return (\o -> o{ optHtmlQTags = x })+    -- Deprecated     "highlight-style" ->-      parseJSON v >>= \x -> return (\o -> o{ optHighlightStyle = x })+      parseJSON v >>= \x -> return (\o -> o{ optSyntaxHighlighting = x })     "syntax-definition" ->       (parseJSON v >>= \x ->                 return (\o -> o{ optSyntaxDefinitions =@@ -569,6 +570,8 @@       parseJSON v >>= \x ->              return (\o -> o{ optSyntaxDefinitions =                                 optSyntaxDefinitions o <> map unpack x })+    "syntax-highlighting" ->+      parseJSON v >>= \x -> return (\o -> o{ optSyntaxHighlighting = x })     "top-level-division" ->       parseJSON v >>= \x -> return (\o -> o{ optTopLevelDivision = x })     "html-math-method" ->@@ -647,7 +650,10 @@     "cite-method" ->       parseJSON v >>= \x -> return (\o -> o{ optCiteMethod = x })     "listings" ->-      parseJSON v >>= \x -> return (\o -> o{ optListings = x })+      parseJSON v >>= \x ->+        if x+        then return (\o -> o{ optSyntaxHighlighting = "idiomatic" })+        else return id     "pdf-engine" ->       parseJSON v >>= \x -> return (\o -> o{ optPdfEngine = unpack <$> x })     "pdf-engine-opts" ->@@ -773,8 +779,8 @@     , optEmbedResources        = False     , optLinkImages            = False     , optHtmlQTags             = False-    , optHighlightStyle        = Just "pygments"     , optSyntaxDefinitions     = []+    , optSyntaxHighlighting    = DefaultHighlightingString     , optTopLevelDivision      = TopLevelDefault     , optHTMLMathMethod        = PlainMath     , optAbbreviations         = Nothing@@ -806,7 +812,6 @@     , optIndentedCodeClasses   = []     , optDataDir               = Nothing     , optCiteMethod            = Citeproc-    , optListings              = False     , optPdfEngine             = Nothing     , optPdfEngineOpts         = []     , optSlideLevel            = Nothing
src/Text/Pandoc/App/OutputSettings.hs view
@@ -2,6 +2,7 @@ {-# LANGUAGE FlexibleContexts    #-} {-# LANGUAGE LambdaCase          #-} {-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE PatternSynonyms     #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TupleSections       #-} {- |@@ -165,8 +166,11 @@   syntaxMap <- foldM addSyntaxMap defaultSyntaxMap                      (optSyntaxDefinitions opts) -  hlStyle <- traverse (lookupHighlightingStyle . T.unpack) $-               optHighlightStyle opts+  hlStyle <- case optSyntaxHighlighting opts of+    NoHighlightingString        -> pure NoHighlighting+    DefaultHighlightingString   -> pure DefaultHighlighting+    IdiomaticHighlightingString -> pure IdiomaticHighlighting+    style       -> Skylighting <$> lookupHighlightingStyle (T.unpack style)    let setListVariableM _ [] ctx = return ctx       setListVariableM k vs ctx = do@@ -251,9 +255,8 @@         , writerIdentifierPrefix = optIdentifierPrefix opts         , writerHtmlQTags        = optHtmlQTags opts         , writerTopLevelDivision = optTopLevelDivision opts-        , writerListings         = optListings opts         , writerSlideLevel       = optSlideLevel opts-        , writerHighlightStyle   = hlStyle+        , writerHighlightMethod  = hlStyle         , writerSetextHeaders    = optSetextHeaders opts         , writerListTables       = optListTables opts         , writerEpubSubdirectory = T.pack $ optEpubSubdirectory opts
src/Text/Pandoc/Citeproc.hs view
@@ -299,6 +299,8 @@  where   getCitation (Cite cs _fallback) = Seq.singleton $     Citeproc.Citation { Citeproc.citationId = Nothing+                      , Citeproc.citationPrefix = Nothing+                      , Citeproc.citationSuffix = Nothing                       , Citeproc.citationNoteNumber =                           case cs of                             []    -> Nothing@@ -318,7 +320,7 @@  where   locmap = toLocatorMap locale   go c =-    let (mblocinfo, suffix) = parseLocator locmap (citationSuffix c)+    let (mblocinfo, suffix) = parseLocator locmap (Pandoc.citationSuffix c)         cit = CitationItem                { citationItemId = fromMaybe                    (ItemId $ Pandoc.citationId c)@@ -326,7 +328,7 @@                , citationItemLabel = locatorLabel <$> mblocinfo                , citationItemLocator = locatorLoc <$> mblocinfo                , citationItemType = NormalCite-               , citationItemPrefix = case citationPrefix c of+               , citationItemPrefix = case Pandoc.citationPrefix c of                                         [] -> Nothing                                         ils -> Just $ B.fromList ils <>                                                       B.space@@ -408,14 +410,14 @@ mvPunct moveNotes locale (q : s : x@(Cite _ [il]) : ys)   | isSpacy s   , isNote il-  = let spunct = T.takeWhile isPunctuation $ stringify ys+  = let spunct = T.takeWhile isPunct $ stringify ys     in  if moveNotes            then if T.null spunct                    then q : x : mvPunct moveNotes locale ys                    else movePunctInsideQuotes locale                         [q , Str spunct , x] ++ mvPunct moveNotes locale                         (B.toList-                          (dropTextWhile isPunctuation (B.fromList ys)))+                          (dropTextWhile isPunct (B.fromList ys)))            else q : x : mvPunct moveNotes locale ys -- 'x[^1],' -> 'x,[^1]' mvPunct moveNotes locale (Cite cs ils@(_:_) : ys)@@ -423,13 +425,13 @@    , startWithPunct ys    , moveNotes    = let s = stringify ys-         spunct = T.takeWhile isPunctuation s+         spunct = T.takeWhile isPunct s      in  Cite cs (movePunctInsideQuotes locale $                     init ils                     ++ [Str spunct | not (endWithPunct False (init ils))]                     ++ [last ils]) :          mvPunct moveNotes locale-           (B.toList (dropTextWhile isPunctuation (B.fromList ys)))+           (B.toList (dropTextWhile isPunct (B.fromList ys))) mvPunct moveNotes locale (s : x@(Cite _ [il]) : ys)   | isSpacy s   , isNote il@@ -442,13 +444,18 @@ mvPunct moveNotes locale (x:xs) = x : mvPunct moveNotes locale xs mvPunct _ _ [] = [] +-- We don't treat an em-dash or en-dash as punctuation here, because we don't+-- want notes and quotes to move around them.+isPunct :: Char -> Bool+isPunct c = isPunctuation c && c /= '\x2014' && c /= '\x2013'+ endWithPunct :: Bool -> [Inline] -> Bool endWithPunct _ [] = False endWithPunct onlyFinal xs@(_:_) =   case reverse (T.unpack $ stringify xs) of        []                       -> True        -- covers .), .", etc.:-       (d:c:_) | isPunctuation d+       (d:c:_) | isPunct d                  && not onlyFinal                  && isEndPunct c -> True        (c:_) | isEndPunct c      -> True@@ -478,7 +485,10 @@  -- if document contains a Div with id="refs", insert -- references as its contents.  Otherwise, insert references--- at the end of the document in a Div with id="refs"+-- at the end of the document in a Div with id="refs" or+-- id=".*__refs" (where .* stands for any string -- this is+-- because --file-scope will add such a prefix based on the filename,+-- see #11072.) insertRefs :: [(Text,Text)] -> [Text] -> [Block] -> Pandoc -> Pandoc insertRefs _ _ [] d = d insertRefs refkvs refclasses refs (Pandoc meta bs) =@@ -503,12 +513,13 @@    refDiv = Div ("refs", refclasses, refkvs) refs    addUnNumbered cs = "unnumbered" : [c | c <- cs, c /= "unnumbered"]    go :: Block -> State Bool Block-   go (Div ("refs",cs,kvs) xs) = do-     put True-     -- refHeader isn't used if you have an explicit references div-     let cs' = nubOrd $ cs ++ refclasses-     let kvs' = nubOrd $ kvs ++ refkvs-     return $ Div ("refs",cs',kvs') (xs ++ refs)+   go (Div (ident,cs,kvs) xs)+     | ident == "refs" || "__refs" `T.isSuffixOf` ident = do+       put True+       -- refHeader isn't used if you have an explicit references div+       let cs' = nubOrd $ cs ++ refclasses+       let kvs' = nubOrd $ kvs ++ refkvs+       return $ Div (ident,cs',kvs') (xs ++ refs)    go x = return x  refTitle :: Meta -> Maybe [Inline]
src/Text/Pandoc/Citeproc/BibTeX.hs view
@@ -57,6 +57,7 @@ import           Text.Printf            (printf) import           Text.DocLayout         (literal, hsep, nest, hang, Doc(..),                                          braces, ($$), cr)+ data Variant = Bibtex | Biblatex   deriving (Show, Eq, Ord) @@ -967,7 +968,7 @@ getPeriodicalTitle :: Text -> Bib Inlines getPeriodicalTitle f = do   ils <- getField f-  return ils+  return $ protectCase id ils  protectCase :: (Inlines -> Inlines) -> (Inlines -> Inlines) protectCase f = Walk.walk unprotect . f . Walk.walk protect
src/Text/Pandoc/Class.hs view
@@ -23,7 +23,9 @@   , Translations   ) where -import Text.Pandoc.Class.CommonState (CommonState (..))+-- We export CommonState as an opaque object.  Accessors for+-- its fields are provided in Text.Pandoc.Class.PandocMonad.+import Text.Pandoc.Class.CommonState (CommonState) import Text.Pandoc.Class.PandocMonad import Text.Pandoc.Class.PandocIO import Text.Pandoc.Class.PandocPure
src/Text/Pandoc/Class/CommonState.hs view
@@ -23,6 +23,7 @@ import Text.Pandoc.MediaBag (MediaBag) import Text.Pandoc.Logging (LogMessage, Verbosity (WARNING)) import Text.Pandoc.Translations.Types (Translations)+import Network.HTTP.Client (Manager)  -- | 'CommonState' represents state that is used by all -- instances of 'PandocMonad'.  Normally users should not@@ -50,6 +51,9 @@   , stResourcePath :: [FilePath]     -- ^ Path to search for resources like     -- included images+  , stManager      :: Maybe Manager+    -- ^ Manager for HTTP client; this needs to persist across many requests+    -- for efficiency.   , stVerbosity    :: Verbosity     -- ^ Verbosity level   , stTrace        :: Bool@@ -75,6 +79,7 @@   , stInputFiles = []   , stOutputFile = Nothing   , stResourcePath = ["."]+  , stManager = Nothing   , stVerbosity = WARNING   , stTrace = False   }
src/Text/Pandoc/Class/IO.hs view
@@ -45,7 +45,7 @@ import qualified Network.TLS as TLS import qualified Network.TLS.Extra as TLS import Network.HTTP.Client-       (httpLbs, responseBody, responseHeaders,+       (httpLbs, Manager, responseBody, responseHeaders,         Request(port, host, requestHeaders), parseRequest, newManager) import Network.HTTP.Client.Internal (addProxy) import Network.HTTP.Client.TLS (mkManagerSettings)@@ -61,7 +61,8 @@ import System.Random (StdGen) import Text.Pandoc.Class.CommonState (CommonState (..)) import Text.Pandoc.Class.PandocMonad-       (PandocMonad, getsCommonState, getMediaBag, report, extractURIData)+       (PandocMonad, getsCommonState, modifyCommonState,+        getMediaBag, report, extractURIData) import Text.Pandoc.Definition (Pandoc, Inline (Image)) import Text.Pandoc.Error (PandocError (..)) import Text.Pandoc.Logging (LogMessage (..), messageVerbosity, showLogMessage)@@ -70,7 +71,6 @@ import Text.Pandoc.Walk (walk) import qualified Control.Exception as E import qualified Data.ByteString as B-import qualified Data.ByteString.Char8 as B8 import qualified Data.ByteString.Lazy as BL import qualified Data.CaseInsensitive as CI import qualified Data.Text as T@@ -124,6 +124,36 @@ newUniqueHash :: MonadIO m => m Int newUniqueHash = hashUnique <$> liftIO Data.Unique.newUnique +getManager :: (PandocMonad m, MonadIO m) => m Manager+getManager = do+  mbManager <- getsCommonState stManager+  disableCertificateValidation <- getsCommonState stNoCheckCertificate+  case mbManager of+    Just manager -> pure manager+    Nothing -> do+      manager <- liftIO $ do+        certificateStore <- getSystemCertificateStore+        let tlsSettings = TLSSettings $+               (TLS.defaultParamsClient "localhost.localdomain" "80")+                  { TLS.clientSupported = def{ TLS.supportedCiphers =+                                               TLS.ciphersuite_default+                                             , TLS.supportedExtendedMainSecret =+                                                TLS.AllowEMS }+                  , TLS.clientShared = def+                      { TLS.sharedCAStore = certificateStore+                      , TLS.sharedValidationCache =+                          if disableCertificateValidation+                             then TLS.ValidationCache+                                   (\_ _ _ -> return TLS.ValidationCachePass)+                                   (\_ _ _ -> return ())+                             else def+                      }+                  }+        let tlsManagerSettings = mkManagerSettings tlsSettings  Nothing+        newManager tlsManagerSettings+      modifyCommonState $ \st -> st{ stManager = Just manager }+      pure manager+ openURL :: (PandocMonad m, MonadIO m) => Text -> m (B.ByteString, Maybe MimeType) openURL u  | Just (URI{ uriScheme = "data:",@@ -132,8 +162,8 @@  | otherwise = do      let toReqHeader (n, v) = (CI.mk (UTF8.fromText n), UTF8.fromText v)      customHeaders <- map toReqHeader <$> getsCommonState stRequestHeaders-     disableCertificateValidation <- getsCommonState stNoCheckCertificate      report $ Fetching u+     manager <- getManager      res <- liftIO $ E.try $ withSocketsDo $ do        proxy <- tryIOError (getEnv "http_proxy")        let addProxy' x = case proxy of@@ -142,26 +172,7 @@                                 return (addProxy (host r) (port r) x)        req <- parseRequest (unpack u) >>= addProxy'        let req' = req{requestHeaders = customHeaders ++ requestHeaders req}-       certificateStore <- getSystemCertificateStore-       let tlsSettings = TLSSettings $-              (TLS.defaultParamsClient (show $ host req')-                                       (B8.pack $ show $ port req'))-                 { TLS.clientSupported = def{ TLS.supportedCiphers =-                                              TLS.ciphersuite_default-                                            , TLS.supportedExtendedMainSecret =-                                               TLS.AllowEMS }-                 , TLS.clientShared = def-                     { TLS.sharedCAStore = certificateStore-                     , TLS.sharedValidationCache =-                         if disableCertificateValidation-                            then TLS.ValidationCache-                                  (\_ _ _ -> return TLS.ValidationCachePass)-                                  (\_ _ _ -> return ())-                            else def-                     }-                 }-       let tlsManagerSettings = mkManagerSettings tlsSettings  Nothing-       resp <- newManager tlsManagerSettings >>= httpLbs req'+       resp <- httpLbs req' manager        return (B.concat $ toChunks $ responseBody resp,                UTF8.toText `fmap` lookup hContentType (responseHeaders resp)) 
src/Text/Pandoc/Class/PandocMonad.hs view
@@ -28,12 +28,14 @@   , getZonedTime   , readFileFromDirs   , report-  , setTrace+  , runSilently   , setRequestHeader   , setNoCheckCertificate   , getLog   , setVerbosity   , getVerbosity+  , setTrace+  , getTrace   , getMediaBag   , setMediaBag   , insertMedia@@ -47,6 +49,9 @@   , setOutputFile   , setResourcePath   , getResourcePath+  , setRequestHeaders+  , getRequestHeaders+  , getSourceURL   , readMetadataFile   , toTextM   , fillMediaBag@@ -164,6 +169,15 @@ getVerbosity :: PandocMonad m => m Verbosity getVerbosity = getsCommonState stVerbosity +-- | Set tracing. This affects the behavior of 'trace'. If tracing+-- is not enabled, 'trace' does nothing.+setTrace :: PandocMonad m => Bool -> m ()+setTrace enabled = modifyCommonState $ \st -> st{ stTrace = enabled }++-- | Get tracing status.+getTrace :: PandocMonad m => m Bool+getTrace = getsCommonState stTrace+ -- | Get the accumulated log messages (in temporal order). getLog :: PandocMonad m => m [LogMessage] getLog = reverse <$> getsCommonState stLog@@ -179,12 +193,23 @@   when (level <= verbosity) $ logOutput msg   modifyCommonState $ \st -> st{ stLog = msg : stLog st } --- | Determine whether tracing is enabled.  This affects--- the behavior of 'trace'.  If tracing is not enabled,--- 'trace' does nothing.-setTrace :: PandocMonad m => Bool -> m ()-setTrace useTracing = modifyCommonState $ \st -> st{stTrace = useTracing}+-- | Run an action, but suppress the output of any log messages;+-- instead, all messages reported by @action@ are returned separately+-- and not added to the main log.+runSilently :: PandocMonad m => m a -> m (a, [LogMessage])+runSilently action = do+  -- get current settings+  origLog <- getsCommonState stLog+  origVerbosity <- getVerbosity+  -- reset log level and set verbosity to the minimum+  modifyCommonState (\st -> st { stVerbosity = ERROR, stLog = []})+  result <- action+  -- get log messages reported while running `action`+  newLog <- getsCommonState stLog+  modifyCommonState (\st -> st { stVerbosity = origVerbosity, stLog = origLog}) +  return (result, newLog)+ -- | Set request header to use in HTTP requests. setRequestHeader :: PandocMonad m                  => T.Text  -- ^ Header name@@ -248,6 +273,18 @@ setResourcePath :: PandocMonad m => [FilePath] -> m () setResourcePath ps = modifyCommonState $ \st -> st{stResourcePath = ps} +-- | Retrieve the request headers to add for HTTP requests.+getRequestHeaders :: PandocMonad m => m [(T.Text, T.Text)]+getRequestHeaders = getsCommonState stRequestHeaders++-- | Set the request headers to add for HTTP requests.+setRequestHeaders :: PandocMonad m => [(T.Text, T.Text)] -> m ()+setRequestHeaders hs = modifyCommonState $ \st -> st{ stRequestHeaders = hs }++-- | Get the absolute UL or directory of first source file.+getSourceURL :: PandocMonad m => m (Maybe T.Text)+getSourceURL = getsCommonState stSourceURL+ -- | Get the current UTC time. If the @SOURCE_DATE_EPOCH@ environment -- variable is set to a unix time (number of seconds since midnight -- Jan 01 1970 UTC), it is used instead of the current time, to support@@ -371,8 +408,7 @@                           uriPath = "",                           uriQuery = "",                           uriFragment = "" }-         dropFragmentAndQuery = T.takeWhile (\c -> c /= '?' && c /= '#')-         fp = unEscapeString $ T.unpack $ dropFragmentAndQuery s+         fp = unEscapeString $ T.unpack s          mime = getMimeType $ case takeExtension fp of                      ".gz" -> dropExtension fp                      ".svgz" -> dropExtension fp ++ ".svg"
src/Text/Pandoc/Error.hs view
@@ -65,6 +65,7 @@                  | PandocUnsupportedExtensionError Text Text                  | PandocCiteprocError CiteprocError                  | PandocBibliographyError Text Text+                 | PandocInputNotTextError Text                  deriving (Show, Typeable, Generic)  instance Exception PandocError@@ -143,6 +144,13 @@       prettyCiteprocError e'     PandocBibliographyError fp msg ->       "Error reading bibliography file " <> fp <> ":\n" <> msg+    PandocInputNotTextError fp ->+      "Expected text as an input, but received binary data from " <>+      (if T.null fp+        then "stdin"+        else "file " <> fp) <>+      ".\nIf you intended to convert from binary format, verify that it's " <>+      "supported and use\nexplicit -f FORMAT."   -- | Handle PandocError by exiting with an error message.@@ -184,6 +192,7 @@       PandocUTF8DecodingError{} -> 92       PandocIpynbDecodingError{} -> 93       PandocUnsupportedCharsetError{} -> 94+      PandocInputNotTextError{} -> 95       PandocCouldNotFindDataFileError{} -> 97       PandocCouldNotFindMetadataFileError{} -> 98       PandocResourceNotFound{} -> 99
src/Text/Pandoc/Extensions.hs view
@@ -59,8 +59,6 @@     | Ext_blank_before_header     -- ^ Require blank line before a header     | Ext_bracketed_spans         -- ^ Bracketed spans with attributes     | Ext_citations           -- ^ Pandoc/citeproc citations-    | Ext_compact_definition_lists  -- ^ Definition lists without space between items,-                                    --   and disallow laziness     | Ext_definition_lists    -- ^ Definition lists as in pandoc, mmd, php     | Ext_east_asian_line_breaks  -- ^ Newlines in paragraphs are ignored between                                   --   East Asian wide characters. Note: this extension@@ -122,6 +120,8 @@     | Ext_shortcut_reference_links -- ^ Shortcut reference links     | Ext_simple_tables       -- ^ Pandoc-style simple tables     | Ext_smart               -- ^ "Smart" quotes, apostrophes, ellipses, dashes+    | Ext_smart_quotes        -- ^ "Smart" quotes+    | Ext_special_strings     -- ^ Treat certain strings like special characters     | Ext_sourcepos           -- ^ Include source position attributes     | Ext_space_in_atx_header -- ^ Require space between # and header text     | Ext_spaced_reference_links -- ^ Allow space between two parts of ref link@@ -431,6 +431,7 @@   ] getDefaultExtensions "org"             = extensionsFromList                                           [Ext_citations,+                                           Ext_special_strings,                                            Ext_task_lists,                                            Ext_auto_identifiers] getDefaultExtensions "html"            = extensionsFromList@@ -511,7 +512,6 @@        , Ext_mark        , Ext_mmd_link_attributes        , Ext_mmd_header_identifiers-       , Ext_compact_definition_lists        , Ext_gutenberg        , Ext_smart        , Ext_literate_haskell@@ -583,6 +583,8 @@     extensionsFromList     [ Ext_citations     , Ext_smart+    , Ext_smart_quotes+    , Ext_special_strings     , Ext_fancy_lists     , Ext_task_lists     ]
src/Text/Pandoc/Format.hs view
@@ -181,6 +181,7 @@     ".ctx"      -> defFlavor "context"     ".db"       -> defFlavor "docbook"     ".dj"       -> defFlavor "djot"+    ".djvu"     -> defFlavor "djvu" -- so we get an "unknown reader" error     ".doc"      -> defFlavor "doc"  -- so we get an "unknown reader" error     ".docx"     -> defFlavor "docx"     ".dokuwiki" -> defFlavor "dokuwiki"@@ -204,6 +205,9 @@     ".ms"       -> defFlavor "ms"     ".muse"     -> defFlavor "muse"     ".native"   -> defFlavor "native"+    ".ods"      -> defFlavor "ods"  -- so we get an "unknown reader" error+    ".odp"      -> defFlavor "odp"  -- so we get an "unknown reader" error+    ".odf"      -> defFlavor "odf"  -- so we get an "unknown reader" error     ".odt"      -> defFlavor "odt"     ".opml"     -> defFlavor "opml"     ".org"      -> defFlavor "org"@@ -229,6 +233,10 @@     ".typ"      -> defFlavor "typst"     ".wiki"     -> defFlavor "mediawiki"     ".xhtml"    -> defFlavor "html"+    ".xls"      -> defFlavor "xls"   -- so we get an "unknown reader" error+    ".xlsx"     -> defFlavor "xlsx"  -- so we get an "unknown reader" error+    ".xml"      -> defFlavor "xml"+    ".zip"      -> defFlavor "zip"  -- so we get an "unknown reader" error     ['.',y]     | y `elem` ['1'..'9'] -> defFlavor "man"     _           -> Nothing  where
src/Text/Pandoc/Highlighting.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Highlighting-   Copyright   : Copyright (C) 2008-2024 John MacFarlane+   Copyright   : Copyright (C) 2008-2025 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -31,6 +31,7 @@                                 , styleToConTeXt                                 , formatANSI                                 -- * Styles+                                , defaultStyle                                 , pygments                                 , espresso                                 , zenburn@@ -55,6 +56,10 @@ import Control.Monad.Except (throwError) import System.FilePath (takeExtension) import Text.Pandoc.Shared (safeRead)++-- | The default highlighting style used by pandoc (pygments).+defaultStyle :: Style+defaultStyle = pygments  highlightingStyles :: [(T.Text, Style)] highlightingStyles =
src/Text/Pandoc/ImageSize.hs view
@@ -38,7 +38,7 @@ import qualified Data.ByteString.Lazy as BL import Data.Binary.Get import Data.Bits ((.&.), shiftR, shiftL)-import Data.Word (bitReverse32)+import Data.Word (bitReverse32, Word32) import Data.Maybe (isJust, fromJust) import Data.Char (isDigit) import Control.Monad@@ -57,11 +57,12 @@ import qualified Data.Attoparsec.ByteString.Char8 as A import qualified Codec.Picture.Metadata as Metadata import Codec.Picture (decodeImageWithMetadata)+import Codec.Compression.Zlib (decompress)+-- import Debug.Trace  -- quick and dirty functions to get image sizes--- algorithms borrowed from wwwis.pl -data ImageType = Png | Gif | Jpeg | Svg | Pdf | Eps | Emf | Tiff | Webp+data ImageType = Png | Gif | Jpeg | Svg | Pdf | Eps | Emf | Tiff | Webp | Avif                  deriving Show data Direction = Width | Height instance Show Direction where@@ -72,6 +73,8 @@                | Centimeter Double                | Millimeter Double                | Inch Double+               | Point Double+               | Pica Double                | Percent Double                | Em Double                deriving Eq@@ -81,6 +84,8 @@   show (Centimeter a) = T.unpack (showFl a) ++ "cm"   show (Millimeter a) = T.unpack (showFl a) ++ "mm"   show (Inch a)       = T.unpack (showFl a) ++ "in"+  show (Point a)      = T.unpack (showFl a) ++ "pt"+  show (Pica a)       = T.unpack (showFl a) ++ "pc"   show (Percent a)    = show a              ++ "%"   show (Em a)         = T.unpack (showFl a) ++ "em" @@ -113,8 +118,11 @@                      "\x47\x49\x46\x38" -> return Gif                      "\x49\x49\x2a\x00" -> return Tiff                      "\x4D\x4D\x00\x2a" -> return Tiff-                     "\xff\xd8\xff\xe0" -> return Jpeg  -- JFIF-                     "\xff\xd8\xff\xe1" -> return Jpeg  -- Exif+                     "\xff\xd8\xff\xbd" -> return Jpeg  -- JPEG without application segment -- see p.32 in https://www.w3.org/Graphics/JPEG/itu-t81.pdf (and https://gist.github.com/leommoore/f9e57ba2aa4bf197ebc5?permalink_comment_id=3863054#gistcomment-3863054)+                     _ | B.take 3 img == "\xff\xd8\xff"+                          && (let byte4 = B.take 1 (B.drop 3 img)+                              in byte4 >= "\xe0" && byte4 <= "\xef")  -- JPEG with application segment+                                        -> return Jpeg                      "%PDF"             -> return Pdf                      "<svg"             -> return Svg                      "<?xm"@@ -131,6 +139,7 @@                      "RIFF"                        | B.take 4 (B.drop 8 img) == "WEBP"                                         -> return Webp+                     _ | B.take 4 (B.drop 4 img) == "ftyp" -> return Avif                      _ -> mzero  findSvgTag :: ByteString -> Bool@@ -148,6 +157,7 @@        Just Pdf  -> mbToEither "could not determine PDF size" $ pdfSize img        Just Emf  -> mbToEither "could not determine EMF size" $ emfSize img        Just Webp -> mbToEither "could not determine WebP size" $ webpSize opts img+       Just Avif -> mbToEither "could not determine AVIF size" $ avifSize opts img        Nothing   -> Left "could not determine image type"   where mbToEither msg Nothing  = Left msg         mbToEither _   (Just x) = Right x@@ -201,6 +211,8 @@     (Centimeter a) -> a * 0.3937007874     (Millimeter a) -> a * 0.03937007874     (Inch a)       -> a+    (Point a)      -> (a / 72)+    (Pica a)       -> (a / 6)     (Percent _)    -> 0     (Em a)         -> a * (11/64) @@ -208,11 +220,7 @@ inPixel opts dim =   case dim of     (Pixel a)      -> a-    (Centimeter a) -> floor $ dpi * a * 0.3937007874 :: Integer-    (Millimeter a) -> floor $ dpi * a * 0.03937007874 :: Integer-    (Inch a)       -> floor $ dpi * a :: Integer-    (Percent _)    -> 0-    (Em a)         -> floor $ dpi * a * (11/64) :: Integer+    _              -> floor (dpi * inInch opts dim)   where     dpi = fromIntegral $ writerDpi opts @@ -242,6 +250,8 @@         Centimeter x -> Centimeter (factor * x)         Millimeter x -> Millimeter (factor * x)         Inch x       -> Inch (factor * x)+        Point x      -> Point (factor * x)+        Pica x       -> Pica (factor * x)         Percent x    -> Percent (factor * x)         Em x         -> Em (factor * x) @@ -265,8 +275,8 @@     toDim a "%"    = Just $ Percent a     toDim a "px"   = Just $ Pixel (floor a::Integer)     toDim a ""     = Just $ Pixel (floor a::Integer)-    toDim a "pt"   = Just $ Inch (a / 72)-    toDim a "pc"   = Just $ Inch (a / 6)+    toDim a "pt"   = Just $ Point a+    toDim a "pc"   = Just $ Pica a     toDim a "em"   = Just $ Em a     toDim _ _      = Nothing @@ -294,10 +304,10 @@     Right sz -> Just sz  pPdfSize :: A.Parser ImageSize-pPdfSize = do-  A.skipWhile (/='/')-  A.char8 '/'-  (do A.string "MediaBox"+pPdfSize =+  (A.takeWhile1 (/= '/') *> pPdfSize)+  <|>+  (do A.string "/MediaBox"       A.skipSpace       A.char8 '['       A.skipSpace@@ -314,7 +324,27 @@             , pxY  = y2 - y1             , dpiX = 72             , dpiY = 72 }-   ) <|> pPdfSize+  )+  <|> -- if we encounter a compressed object stream, uncompress it (#10902)+  (do A.string "/Type"+      A.skipSpace+      A.string "/ObjStm"+      _ <- A.manyTill pLine (A.string "stream" *> pEol)+      stream <- BL.pack <$> A.manyTill+                        (AW.satisfy (const True))+                        (pEol *> A.string "endstream" *> pEol)+      let contents = BL.toStrict (decompress stream)+      case A.parseOnly pPdfSize contents of+        Left _ -> pPdfSize+        Right is -> pure is)+  <|>+  (A.char '/' *> pPdfSize)+ where+   iseol '\r' = True+   iseol '\n' = True+   iseol _ = False+   pEol = A.satisfy iseol *> A.skipMany (A.satisfy iseol)+   pLine = A.takeWhile (not . iseol) <* pEol  getSize :: ByteString -> Either T.Text ImageSize getSize img =@@ -451,3 +481,173 @@   case AW.parseOnly pWebpSize img of     Left _   -> Nothing     Right sz -> Just sz { dpiX = fromIntegral $ writerDpi opts, dpiY = fromIntegral $ writerDpi opts}++avifSize :: WriterOptions -> ByteString -> Maybe ImageSize+avifSize _opts img =+  case runGetOrFail (verifyFtyp >> findAvifDimensions) (BL.fromStrict img) of+    Left (_, _, _err) -> Nothing+    Right (_, _, (width, height)) ->+      Just $ ImageSize { pxX = fromIntegral width+                       , pxY = fromIntegral height+                       , dpiX = 72+                       , dpiY = 72 }++---- AVIF parsing:++verifyFtyp :: Get ()+verifyFtyp = do+  ftypSize <- getWord32be+  when (ftypSize < 16) $ fail "Invalid ftyp size"++  ftyp <- getByteString 4+  unless (ftyp == "ftyp") $ fail "ftyp signature not found"++  brand <- getByteString 4+  unless (brand == "avif" || brand == "avis") $ fail "Not an AVIF file"++  -- Skip minor version and compatible brands+  -- (we've read 12 bytes: size+type+brand)+  let remaining_ftyp = fromIntegral ftypSize - 12+  when (remaining_ftyp > 0) $ skip remaining_ftyp++findAvifDimensions :: Get (Word32, Word32)+findAvifDimensions = searchAvifBoxes []++searchAvifBoxes :: [B.ByteString] -> Get (Word32, Word32)+searchAvifBoxes path = do+  isempty <- isEmpty+  if isempty+    then fail $ "No dimensions found. Searched: " ++ show (reverse path)+    else do+      boxSize <- getWord32be+      boxType <- getByteString 4++      let contentSize = fromIntegral boxSize - 8+      let newPath = boxType : path++      -- If it's a container box, search inside it+      if isContainerBox boxType+        then searchInsideBox contentSize newPath+        else do+          -- Try to parse dimensions from this box+          result <- tryParseDimensions boxType contentSize+          case result of+            Just dims -> return dims+            Nothing -> do+              -- Skip this box and continue+              when (contentSize > 0 && contentSize < 10000000) $+                skip contentSize+              searchAvifBoxes path++tryParseDimensions :: B.ByteString -> Int -> Get (Maybe (Word32, Word32))+tryParseDimensions boxType size = do+  pos <- bytesRead+  result <- case boxType of+    "ispe" -> parseIspeBox+    "tkhd" -> parseTkhdBox+    "stsd" -> parseStsdBox+    "av01" -> parseAv01Box+    _ -> return Nothing++  -- Reset position if we didn't find dimensions+  case result of+    Nothing -> do+      newPos <- bytesRead+      let consumed = fromIntegral (newPos - pos)+      case size - consumed of+        n | n > 0 -> skip n+        _ -> return ()+    Just _ -> return ()++  return result++parseIspeBox :: Get (Maybe (Word32, Word32))+parseIspeBox = do+  skip 4  -- version/flags+  width <- getWord32be+  height <- getWord32be+  return $ Just (width, height)++parseTkhdBox :: Get (Maybe (Word32, Word32))+parseTkhdBox = do+  version <- getWord8+  skip 3  -- flags++  -- Skip to width/height based on version+  let skipBytes = if version == 1 then 76 else 64+  skip skipBytes++  width <- getWord32be+  height <- getWord32be+  -- Convert from 16.16 fixed point+  return $ Just (width `shiftR` 16, height `shiftR` 16)++parseStsdBox :: Get (Maybe (Word32, Word32))+parseStsdBox = do+  skip 8  -- version, flags, entry count+  findAv01Entry++findAv01Entry :: Get (Maybe (Word32, Word32))+findAv01Entry = do+  entrySize <- getWord32be+  codec <- getByteString 4++  if codec == "av01"+    then do+      skip 6  -- reserved+      skip 2  -- data reference index+      skip 16 -- pre-defined + reserved+      width <- getWord16be+      height <- getWord16be+      return $ Just (fromIntegral width, fromIntegral height)+    else do+      let skipSize = fromIntegral entrySize - 8+      when (skipSize > 0) $ skip skipSize+      findAv01Entry++parseAv01Box :: Get (Maybe (Word32, Word32))+parseAv01Box = do+  skip 6   -- reserved+  skip 2   -- data reference index+  skip 16  -- predefined/reserved+  width <- getWord16be+  height <- getWord16be+  return $ Just (fromIntegral width, fromIntegral height)++searchInsideBox :: Int -> [B.ByteString] -> Get (Word32, Word32)+searchInsideBox size path = do+  -- For meta boxes, skip version/flags+  let isMeta = case path of+                 "meta":_ -> True+                 _ -> False+  when isMeta $ skip 4++  let searchSize = if isMeta then size - 4 else size+  searchAvifBoxesInRange searchSize path++searchAvifBoxesInRange :: Int -> [B.ByteString] -> Get (Word32, Word32)+searchAvifBoxesInRange remaining' path+  | remaining' < 8 = searchAvifBoxes path+  | otherwise = do+      boxSize <- getWord32be+      boxType <- getByteString 4++      let contentSize = fromIntegral boxSize - 8+      let newPath = boxType : path++      when (contentSize < 0 || fromIntegral boxSize > remaining') $ do+        fail $ "Malformed box at path: " ++ show (reverse newPath)++      if isContainerBox boxType+        then searchInsideBox contentSize newPath+        else do+          result <- tryParseDimensions boxType contentSize+          case result of+            Just dims -> return dims+            Nothing -> do+              -- Don't skip here - tryParseDimensions already handled it+              searchAvifBoxesInRange (remaining' - fromIntegral boxSize) path++isContainerBox :: B.ByteString -> Bool+isContainerBox boxType = boxType `elem`+  ["moov", "trak", "mdia", "minf", "stbl", "meta", "dinf", "ipco", "iprp"]
src/Text/Pandoc/Options.hs view
@@ -3,6 +3,7 @@ {-# LANGUAGE DeriveGeneric      #-} {-# LANGUAGE LambdaCase         #-} {-# LANGUAGE OverloadedStrings  #-}+{-# LANGUAGE PatternSynonyms    #-} {-# LANGUAGE TemplateHaskell    #-} {- |    Module      : Text.Pandoc.Options@@ -21,6 +22,10 @@                            , HTMLMathMethod (..)                            , CiteMethod (..)                            , ObfuscationMethod (..)+                           , HighlightMethod (..)+                           , pattern NoHighlightingString+                           , pattern DefaultHighlightingString+                           , pattern IdiomaticHighlightingString                            , HTMLSlideVariant (..)                            , EPUBVersion (..)                            , WrapOption (..)@@ -32,6 +37,7 @@                            , def                            , isEnabled                            , defaultMathJaxURL+                           , defaultWebTeXURL                            , defaultKaTeXURL                            ) where import Control.Applicative ((<|>))@@ -41,13 +47,14 @@ import Data.Char (toLower) import Data.Text (Text) import qualified Data.Set as Set+import qualified Data.Text as T import Data.Typeable (Typeable) import GHC.Generics (Generic) import Skylighting (SyntaxMap, defaultSyntaxMap) import Text.DocTemplates (Context(..), Template) import Text.Pandoc.Extensions import Text.Pandoc.Chunks (PathTemplate)-import Text.Pandoc.Highlighting (Style, pygments)+import Text.Pandoc.Highlighting (Style) import Text.Pandoc.UTF8 (toStringLazy) import Data.Aeson.TH (deriveJSON) import Data.Aeson@@ -114,7 +121,8 @@         mburl <- m .:? "url"         case method :: Text of           "plain" -> return PlainMath-          "webtex" -> return $ WebTeX $ fromMaybe "" mburl+          "webtex" -> return $ WebTeX $+                         fromMaybe defaultWebTeXURL mburl           "gladtex" -> return GladTeX           "mathml" -> return MathML           "mathjax" -> return $ MathJax $@@ -124,7 +132,7 @@           _ -> fail $ "Unknown HTML math method " ++ show method) node        <|> (case node of                String "plain" -> return PlainMath-               String "webtex" -> return $ WebTeX ""+               String "webtex" -> return $ WebTeX defaultWebTeXURL                String "gladtex" -> return GladTeX                String "mathml" -> return MathML                String "mathjax" -> return $ MathJax defaultMathJaxURL@@ -184,6 +192,43 @@    toJSON ReferenceObfuscation = String "references"    toJSON JavascriptObfuscation = String "javascript" +-- | Method to provide code highlighting.+data HighlightMethod =+    Skylighting Style+  | IdiomaticHighlighting+  | DefaultHighlighting+  | NoHighlighting+  deriving (Show, Read, Eq, Data, Typeable, Generic)++-- | String representation of the idiomatic highlighting option.+pattern IdiomaticHighlightingString :: Text+pattern IdiomaticHighlightingString = "idiomatic"++-- | String representation of the default highlighting option.+pattern DefaultHighlightingString :: Text+pattern DefaultHighlightingString = "default"++-- | String representation of the no highlighting option+pattern NoHighlightingString :: Text+pattern NoHighlightingString = "none"++instance ToJSON HighlightMethod where+  toJSON NoHighlighting        = String NoHighlightingString+  toJSON IdiomaticHighlighting = String IdiomaticHighlightingString+  toJSON DefaultHighlighting   = String DefaultHighlightingString+  toJSON (Skylighting style)   = toJSON style++instance FromJSON HighlightMethod where+  parseJSON = \case+    String NoHighlightingString        -> pure NoHighlighting+    String IdiomaticHighlightingString -> pure IdiomaticHighlighting+    String DefaultHighlightingString   -> pure DefaultHighlighting+    String x           -> fail $ "Unknown highlighting method " <> T.unpack x+    Bool True          -> pure DefaultHighlighting+    Bool False         -> pure NoHighlighting+    Null               -> pure NoHighlighting+    v                  -> Skylighting <$> parseJSON v+ -- | Varieties of HTML slide shows. data HTMLSlideVariant = S5Slides                       | SlidySlides@@ -328,9 +373,7 @@   , writerHtmlQTags         :: Bool       -- ^ Use @<q>@ tags for quotes in HTML   , writerSlideLevel        :: Maybe Int  -- ^ Force header level of slides   , writerTopLevelDivision  :: TopLevelDivision -- ^ Type of top-level divisions-  , writerListings          :: Bool       -- ^ Use listings package for code-  , writerHighlightStyle    :: Maybe Style  -- ^ Style to use for highlighting-                                           -- (Nothing = no highlighting)+  , writerHighlightMethod   :: HighlightMethod  -- ^ Style to use for highlighting   , writerSetextHeaders     :: Bool       -- ^ Use setext headers for levels 1-2 in markdown   , writerListTables        :: Bool       -- ^ Use list tables for RST tables   , writerEpubSubdirectory  :: Text       -- ^ Subdir for epub in OCF@@ -372,8 +415,7 @@                       , writerHtmlQTags        = False                       , writerSlideLevel       = Nothing                       , writerTopLevelDivision = TopLevelDefault-                      , writerListings         = False-                      , writerHighlightStyle   = Just pygments+                      , writerHighlightMethod  = DefaultHighlighting                       , writerSetextHeaders    = False                       , writerListTables       = False                       , writerEpubSubdirectory = "EPUB"@@ -401,6 +443,9 @@  defaultMathJaxURL :: Text defaultMathJaxURL = "https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml-full.js"++defaultWebTeXURL :: Text+defaultWebTeXURL = "https://latex.codecogs.com/png.latex?"  defaultKaTeXURL :: Text defaultKaTeXURL = "https://cdn.jsdelivr.net/npm/katex@latest/dist/"
src/Text/Pandoc/PDF.hs view
@@ -43,6 +43,7 @@ import Text.DocLayout (literal, render, hsep) import Text.Pandoc.Definition import Text.Pandoc.Error (PandocError (PandocPDFProgramNotFoundError))+import Text.Pandoc.SelfContained (makeSelfContained) import Text.Pandoc.MIME (getMimeType) import Text.Pandoc.Options (HTMLMathMethod (..), WriterOptions (..)) import Text.Pandoc.Extensions (disableExtension, Extension(Ext_smart))@@ -57,7 +58,8 @@ import Data.List (intercalate) #endif import Data.List (isPrefixOf, find)-import Text.Pandoc.Class (fillMediaBag, getVerbosity, setVerbosity,+import Text.Pandoc.MediaBag (mediaItems)+import Text.Pandoc.Class (fillMediaBag, getMediaBag, getVerbosity, setVerbosity,                           readFileStrict, fileExists,                           report, extractMedia, PandocMonad, runIOorExplode) import Text.Pandoc.Logging@@ -81,24 +83,36 @@         -> WriterOptions       -- ^ options         -> Pandoc              -- ^ document         -> m (Either ByteString ByteString)-makePDF program pdfargs writer opts doc =+makePDF program pdfargs writer opts doc = withTempDir (program == "typst") "media" $ \mediaDir -> do+#ifdef _WINDOWS+  -- note:  we want / even on Windows, for TexLive+  let tmpdir = changePathSeparators mediaDir+#else+  let tmpdir = mediaDir+#endif+  doc' <- handleImages opts tmpdir doc+  source <- writer opts{ writerExtensions = -- disable use of quote+                            -- ligatures to avoid bad ligatures like ?`+                            disableExtension Ext_smart+                             (writerExtensions opts) } doc'+  verbosity <- getVerbosity+  let compileHTML mkOutArgs = do+        -- check to see if there is anything in mediabag, and if so,+        -- make the HTML self contained+        mediabag <- getMediaBag+        source' <- case mediaItems mediabag of+                      [] -> pure source+                      _ -> makeSelfContained source+        liftIO $+          toPdfViaTempFile verbosity program pdfargs mkOutArgs ".html" source'   case takeBaseName program of     "wkhtmltopdf" -> makeWithWkhtmltopdf program pdfargs writer opts doc-    prog | prog `elem` ["pagedjs-cli" ,"weasyprint", "prince"] -> do-      let mkOutArgs f =-            if program `elem` ["pagedjs-cli", "prince"]-               then ["-o", f]-               else [f]-      source <- writer opts doc-      verbosity <- getVerbosity-      liftIO $ toPdfViaTempFile verbosity program pdfargs mkOutArgs ".html" source-    "typst" -> do-      source <- writer opts doc-      verbosity <- getVerbosity-      liftIO $+    "pagedjs-cli" -> compileHTML (\f -> ["-o", f])+    "prince"      -> compileHTML (\f -> ["-o", f])+    "weasyprint"  -> compileHTML (:[])+    "typst" -> liftIO $         toPdfViaTempFile verbosity program ("compile":pdfargs) (:[]) ".typ" source     "pdfroff" -> do-      source <- writer opts doc       let paperargs =             case lookupContext "papersize" (writerVariables opts) of               Just s@@ -112,7 +126,6 @@                     paperargs ++ pdfargs       generic2pdf program args source     "groff" -> do-      source <- writer opts doc       let paperargs =             case lookupContext "papersize" (writerVariables opts) of               Just s@@ -125,33 +138,22 @@                    ["-U" | ".PDFPIC" `T.isInfixOf` source] ++                     paperargs ++ pdfargs       generic2pdf program args source-    baseProg -> do-      withTempDir "tex2pdf." $ \tmpdir' -> do-#ifdef _WINDOWS-        -- note:  we want / even on Windows, for TexLive-        let tmpdir = changePathSeparators tmpdir'-#else-        let tmpdir = tmpdir'-#endif-        doc' <- handleImages opts tmpdir doc-        source <- writer opts{ writerExtensions = -- disable use of quote-                                  -- ligatures to avoid bad ligatures like ?`-                                  disableExtension Ext_smart-                                   (writerExtensions opts) } doc'-        case baseProg of-          "context" -> context2pdf program pdfargs tmpdir source-          "tectonic" -> tectonic2pdf program pdfargs tmpdir source-          prog | prog `elem` ["pdflatex", "lualatex", "xelatex", "latexmk"]-              -> tex2pdf program pdfargs tmpdir source-          _ -> return $ Left $ UTF8.fromStringLazy-                             $ "Unknown program " ++ program+    "context"      -> context2pdf program pdfargs tmpdir source+    "tectonic"     -> tectonic2pdf program pdfargs tmpdir source+    "latexmk"      -> tex2pdf program pdfargs tmpdir source+    "lualatex"     -> tex2pdf program pdfargs tmpdir source+    "lualatex-dev" -> tex2pdf program pdfargs tmpdir source+    "pdflatex"     -> tex2pdf program pdfargs tmpdir source+    "pdflatex-dev" -> tex2pdf program pdfargs tmpdir source+    "xelatex"      -> tex2pdf program pdfargs tmpdir source+    _ -> return $ Left $ UTF8.fromStringLazy $ "Unknown program " ++ program  -- latex has trouble with tildes in paths, which -- you find in Windows temp dir paths with longer -- user names (see #777) withTempDir :: (PandocMonad m, MonadMask m, MonadIO m)-            => FilePath -> (FilePath -> m a) -> m a-withTempDir templ action = do+            => Bool -> FilePath -> (FilePath -> m a) -> m a+withTempDir useWorkingDirectory templ action = do   tmp <- liftIO getTemporaryDirectory   uname <- liftIO $ E.catch     (do (ec, sout, _) <- readProcessWithExitCode "uname" ["-o"] ""@@ -159,9 +161,9 @@            then return $ Just $ filter (not . isSpace) sout            else return Nothing)     (\(_  :: E.SomeException) -> return Nothing)-  if '~' `elem` tmp || uname == Just "Cygwin" -- see #5451-         then withTempDirectory "." templ action-         else withSystemTempDirectory templ action+  if useWorkingDirectory || '~' `elem` tmp || uname == Just "Cygwin" -- see #5451+     then withTempDirectory "." templ action+     else withSystemTempDirectory templ action  makeWithWkhtmltopdf :: (PandocMonad m, MonadIO m)                     => String              -- ^ wkhtmltopdf or path@@ -328,7 +330,7 @@    go (Just msg) ln      | ln == "" = do -- emit report and reset accumulator          report $ MakePDFWarning $ render (Just 60) $-            hsep $ map literal $ T.words $ UTF8.toText $ BC.toStrict msg+            hsep $ map literal $ T.words $ utf8ToText msg          pure Nothing      | otherwise = pure $ Just (msg <> ln) @@ -372,7 +374,7 @@     (exit, out) <- liftIO $ E.catch       (pipeProcess (Just env) program programArgs sourceBL)       (handlePDFProgramNotFound program)-    report $ MakePDFInfo "tectonic output" (UTF8.toText $ BL.toStrict out)+    report $ MakePDFInfo "tectonic output" (utf8ToText out)     let pdfFile = tmpDir ++ "/texput.pdf"     (_, pdf) <- getResultingPDF Nothing pdfFile     return (exit, out, pdf)@@ -435,7 +437,7 @@      (exit, out) <- liftIO $ E.catch        (pipeProcess (Just env'') program programArgs BL.empty)        (handlePDFProgramNotFound program)-     report $ MakePDFInfo "LaTeX output" (UTF8.toText $ BL.toStrict out)+     report $ MakePDFInfo "LaTeX output" (utf8ToText out)      -- parse log to see if we need to rerun LaTeX      let logFile = replaceExtension outfile ".log"      logExists <- fileExists logFile@@ -449,8 +451,7 @@      if not (null rerunWarnings') && runNumber < maxruns         then do           report $ MakePDFInfo "Rerun needed"-                    (T.intercalate "\n"-                      (map (UTF8.toText . BC.toStrict) rerunWarnings'))+                    (T.intercalate "\n" (map utf8ToText rerunWarnings'))           go env'' programArgs (runNumber + 1)        else do           (log', pdf) <- getResultingPDF (Just logFile) outfile@@ -503,7 +504,7 @@         (handlePDFProgramNotFound program)       runIOorExplode $ do         setVerbosity verbosity-        report $ MakePDFInfo "pdf-engine output" (UTF8.toText $ BL.toStrict out)+        report $ MakePDFInfo "pdf-engine output" (utf8ToText out)       pdfExists <- doesFileExist pdfFile       mbPdf <- if pdfExists                 -- We read PDF as a strict bytestring to make sure that the@@ -536,7 +537,7 @@       (handlePDFProgramNotFound program)     runIOorExplode $ do       setVerbosity verbosity-      report $ MakePDFInfo "ConTeXt run output" (UTF8.toText $ BL.toStrict out)+      report $ MakePDFInfo "ConTeXt run output" (utf8ToText out)     let pdfFile = replaceExtension file ".pdf"     pdfExists <- doesFileExist pdfFile     mbPdf <- if pdfExists
src/Text/Pandoc/Parsing/GridTable.hs view
@@ -34,6 +34,7 @@ import Text.Pandoc.Sources import Text.Parsec (Stream (..), ParsecT, optional, sepEndBy1, try) +import Data.Maybe (mapMaybe) import qualified Data.Text as T import qualified Text.GridTable as GT import qualified Text.Pandoc.Builder as B@@ -54,17 +55,17 @@   B.tableWith attr capt colspecs th tb tf  -- | Bundles basic table components into a single value.-toTableComponents :: [Alignment] -> [Double] -> [Blocks] -> [[Blocks]]+toTableComponents :: [Alignment] -> [Double] -> [[Blocks]] -> [[Blocks]]                   -> TableComponents toTableComponents = toTableComponents' NoNormalization  -- | Bundles basic table components into a single value, performing -- normalizations as necessary. toTableComponents' :: TableNormalization-                   -> [Alignment] -> [Double] -> [Blocks] -> [[Blocks]]+                   -> [Alignment] -> [Double] -> [[Blocks]] -> [[Blocks]]                    -> TableComponents toTableComponents' normalization aligns widths heads rows =-  let th = TableHead nullAttr (toHeaderRow normalization heads)+  let th = TableHead nullAttr (mapMaybe (toHeaderRow normalization) heads)       tb = TableBody nullAttr 0 [] (map toRow rows)       tf = TableFoot nullAttr []       colspecs = toColSpecs aligns widths@@ -191,7 +192,7 @@ -- 'lineParser', and 'footerParser'. tableWith :: (Stream s m Char, UpdateSourcePos s Char,               HasReaderOptions st, Monad mf)-          => ParsecT s st m (mf [Blocks], [Alignment], [Int]) -- ^ header parser+          => ParsecT s st m (mf [[Blocks]], [Alignment], [Int]) -- ^ header parser           -> ([Int] -> ParsecT s st m (mf [Blocks]))  -- ^ row parser           -> ParsecT s st m sep                       -- ^ line parser           -> ParsecT s st m end                       -- ^ footer parser@@ -202,7 +203,7 @@ tableWith' :: (Stream s m Char, UpdateSourcePos s Char,                HasReaderOptions st, Monad mf)            => TableNormalization-           -> ParsecT s st m (mf [Blocks], [Alignment], [Int]) -- ^ header parser+           -> ParsecT s st m (mf [[Blocks]], [Alignment], [Int]) -- ^ header parser            -> ([Int] -> ParsecT s st m (mf [Blocks]))  -- ^ row parser            -> ParsecT s st m sep                       -- ^ line parser            -> ParsecT s st m end                       -- ^ footer parser@@ -220,10 +221,10 @@ toRow :: [Blocks] -> Row toRow =  Row nullAttr . map B.simpleCell -toHeaderRow :: TableNormalization -> [Blocks] -> [Row]+toHeaderRow :: TableNormalization -> [Blocks] -> Maybe Row toHeaderRow = \case-  NoNormalization -> \l -> [toRow l | not (null l)]-  NormalizeHeader -> \l -> [toRow l | not (null l) && not (all null l)]+  NoNormalization -> \l -> if not (null l) then Just (toRow l) else Nothing+  NormalizeHeader -> \l -> if not (all null l) then Just (toRow l) else Nothing  -- | Calculate relative widths of table columns, based on indices widthsFromIndices :: Int      -- Number of columns on terminal
src/Text/Pandoc/Readers.hs view
@@ -65,6 +65,7 @@   , readTypst   , readDjot   , readPod+  , readXML   -- * Miscellaneous   , getReader   , getDefaultExtensions@@ -118,6 +119,7 @@ import Text.Pandoc.Readers.RTF import Text.Pandoc.Readers.Typst import Text.Pandoc.Readers.Djot+import Text.Pandoc.Readers.XML import qualified Text.Pandoc.UTF8 as UTF8 import Text.Pandoc.Sources (ToSources(..), sourcesToText) @@ -174,6 +176,7 @@           ,("djot"         , TextReader readDjot)           ,("mdoc"         , TextReader readMdoc)           ,("pod"          , TextReader readPod)+          ,("xml"          , TextReader readXML)           ]  -- | Retrieve reader, extensions based on format spec (format+extensions).
src/Text/Pandoc/Readers/DocBook.hs view
@@ -15,6 +15,7 @@ -} module Text.Pandoc.Readers.DocBook ( readDocBook ) where import Control.Monad (MonadPlus(mplus))+import Control.Applicative () import Control.Monad.State.Strict     ( MonadTrans(lift),       StateT(runStateT),@@ -52,6 +53,7 @@ import qualified Data.Map as M import Text.Pandoc.XML.Light import Text.Pandoc.Walk (query)+import Text.Read (readMaybe)  {- @@ -931,9 +933,7 @@                                "lowerroman" -> LowerRoman                                "upperroman" -> UpperRoman                                _            -> Decimal-          let start = fromMaybe 1 $-                      filterElement (named "listitem") e-                       >>= safeRead . attrValue "override"+          let start = fromMaybe 1 $ safeRead $ attrValue "startingnumber" e           orderedListWith (start,listStyle,DefaultDelim) . handleCompact             <$> listitems         "variablelist" -> definitionList <$> deflistitems@@ -1056,9 +1056,8 @@                                        cs -> mapMaybe (findAttr (unqual "colname" )) cs                       let isRow x = named "row" x || named "tr" x                       headrows <- case filterChild (named "thead") e' of-                                       Just h  -> case filterChild isRow h of-                                                       Just x  -> parseRow colnames x-                                                       Nothing -> return []+                                       Just h  -> mapM (parseRow colnames)+                                                  $ filterChildren isRow h                                        Nothing -> return []                       bodyrows <- case filterChild (named "tbody") e' of                                        Just b  -> mapM (parseRow colnames)@@ -1072,7 +1071,7 @@                                                       || x == '.') w                             if n > 0 then Just n else Nothing                       let numrows = maybe 0 maximum $ nonEmpty-                                                    $ map length bodyrows+                                                    $ map length (bodyrows ++ headrows)                       let aligns = case colspecs of                                      [] -> replicate numrows AlignDefault                                      cs -> map toAlignment cs@@ -1094,11 +1093,10 @@                                                             in  ColWidth . scale <$> ws'                                                 Nothing  -> replicate numrows ColWidthDefault                       let toRow = Row nullAttr-                          toHeaderRow l = [toRow l | not (null l)]                       return $ tableWith (elId,classes,attrs)                                      (simpleCaption $ plain capt)                                      (zip aligns widths)-                                     (TableHead nullAttr $ toHeaderRow headrows)+                                     (TableHead nullAttr $ map toRow headrows)                                      [TableBody nullAttr 0 [] $ map toRow bodyrows]                                      (TableFoot nullAttr [])          sect n = sectWith(attrValue "id" e) [] [] n@@ -1172,7 +1170,7 @@  parseRow :: PandocMonad m => [Text] -> Element -> DB m [Cell] parseRow cn = do-  let isEntry x  = named "entry" x || named "td" x || named "th" x+  let isEntry x = named "entry" x || named "td" x || named "th" x   mapM (parseEntry cn) . filterChildren isEntry  parseEntry :: PandocMonad m => [Text] -> Element -> DB m Cell@@ -1189,9 +1187,18 @@         case (mStrt, mEnd) of           (Just start, Just end) -> colDistance start end           _ -> 1+  let rowDistance mr = do+        case readMaybe $ T.unpack mr :: Maybe Int of+          Just moreRow -> RowSpan $ moreRow + 1+          _ -> 1+  let toRowSpan en = do+        case findAttr (unqual "morerows") en of+          Just moreRow -> rowDistance moreRow+          _ -> 1   let colSpan = toColSpan el+  let rowSpan = toRowSpan el   let align = toAlignment el-  (fmap (cell align 1 colSpan) . parseMixed plain . elContent) el+  (fmap (cell align rowSpan colSpan) . parseMixed plain . elContent) el  getInlines :: PandocMonad m => Element -> DB m Inlines getInlines e' = trimInlines . mconcat <$>
src/Text/Pandoc/Readers/Docx.hs view
@@ -305,7 +305,8 @@             emph . go rPr{isItalic = Nothing, isItalicCTL = Nothing}         | Just True <- bold rPr =             strong . go rPr{isBold = Nothing, isBoldCTL = Nothing}-        | Just _ <- rHighlight rPr =+        | Just v <- rHighlight rPr+        , v /= "none" =             spanWith ("",["mark"],[]) . go rPr{rHighlight = Nothing}         | Just True <- isSmallCaps rPr =             smallcaps . go rPr{isSmallCaps = Nothing}
src/Text/Pandoc/Readers/Docx/Parse.hs view
@@ -92,13 +92,13 @@       filterChild,       filterChildrenName,       filterElementName,+      filterElementsName,       lookupAttrBy,       parseXMLElement,       elChildren,       QName(QName, qName),       Content(Elem),-      Element(..),-      findElements )+      Element(..))  data ReaderEnv = ReaderEnv { envNotes         :: Notes                            , envComments      :: Comments@@ -151,46 +151,26 @@   in    concatMapM handler xs -isAltContentRun :: NameSpaces -> Element -> Bool-isAltContentRun ns element-  | isElem ns "w" "r" element-  , Just _altContentElem <- findChildByName ns "mc" "AlternateContent" element-  = True-  | otherwise-  = False---- Elements such as <w:shape> are not always preferred--- to be unwrapped. Only if they are part of an AlternateContent--- element, they should be unwrapped.--- This strategy prevents VML images breaking.-unwrapAlternateContentElement :: NameSpaces -> Element -> [Element]-unwrapAlternateContentElement ns element-  | isElem ns "mc" "AlternateContent" element-  || isElem ns "mc" "Fallback" element-  || isElem ns "w" "pict" element-  || isElem ns "v" "group" element-  || isElem ns "v" "rect" element-  || isElem ns "v" "roundrect" element-  || isElem ns "v" "shape" element-  || isElem ns "v" "textbox" element-  || isElem ns "w" "txbxContent" element-  = concatMap (unwrapAlternateContentElement ns) (elChildren element)-  | otherwise-  = unwrapElement ns element- unwrapElement :: NameSpaces -> Element -> [Element] unwrapElement ns element   | isElem ns "w" "sdt" element   , Just sdtContent <- findChildByName ns "w" "sdtContent" element   = concatMap (unwrapElement ns) (elChildren sdtContent)-  | isElem ns "w" "r" element-  , Just alternateContentElem <- findChildByName ns "mc" "AlternateContent" element-  = unwrapAlternateContentElement ns alternateContentElem   | isElem ns "w" "smartTag" element   = concatMap (unwrapElement ns) (elChildren element)   | isElem ns "w" "p" element-  , Just (modified, altContentRuns) <- extractChildren element (isAltContentRun ns)-  = (unwrapElement ns modified) ++ concatMap (unwrapElement ns) altContentRuns+  , textboxes@(_:_) <- findChildrenByName ns "w" "r" element >>=+                       findChildrenByName ns "mc" "AlternateContent" >>=+                       findChildrenByName ns "mc" "Fallback" >>=+                       findChildrenByName ns "w" "pict" >>=+                       findChildrenByName ns "v" "shape" >>=+                       findChildrenByName ns "v" "textbox" >>=+                       findChildrenByName ns "w" "txbxContent"+  = concatMap (unwrapElement ns) (concatMap elChildren textboxes) -- handle #9214+  | isElem ns "w" "r" element+  , Just fallback <- findChildByName ns "mc" "AlternateContent" element >>=+                     findChildByName ns "mc" "Fallback"+  = [element{ elContent = concatMap (unwrapContent ns) (elContent fallback) }]   | otherwise   = [element{ elContent = concatMap (unwrapContent ns) (elContent element) }] @@ -453,8 +433,10 @@   entry <- findEntryByPath "_rels/.rels" zf   relsElem <- parseXMLFromEntry entry   let rels = filterChildrenName (\n -> qName n == "Relationship") relsElem-  rel <- find (\e -> findAttr (QName "Type" Nothing Nothing) e ==-                       Just "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument")+  rel <- find (\e ->+                 case findAttr (QName "Type" Nothing Nothing) e of+                   Just u -> isNamespace "officeDocument" "relationships/officeDocument" u+                   Nothing -> False)          rels   fp <- findAttr (QName "Target" Nothing Nothing) rel   -- sometimes there will be a leading slash, which windows seems to@@ -1022,8 +1004,8 @@ elemToParPart' ns element   | isElem ns "w" "r" element   , Just drawingElem <- findChildByName ns "w" "drawing" element-  , pic_ns <- "http://schemas.openxmlformats.org/drawingml/2006/picture"-  , picElems <- findElements (QName "pic" (Just pic_ns) (Just "pic")) drawingElem+  , picElems <- filterElementsName+                 (matchQName "drawingml" "picture" (Just "pic") "pic") drawingElem   = let (title, alt) = getTitleAndAlt ns drawingElem         drawings = map (\el ->                         ((findBlip el >>= findAttrByName ns "r" "embed"), el))@@ -1057,15 +1039,15 @@ elemToParPart' ns element   | isElem ns "w" "r" element   , Just drawingElem <- findChildByName ns "w" "drawing" element-  , d_ns <- "http://schemas.openxmlformats.org/drawingml/2006/diagram"-  , Just _ <- findElement (QName "relIds" (Just d_ns) (Just "dgm")) drawingElem+  , Just _ <- filterElementName+                 (matchQName "drawingml" "diagram" (Just "dgm") "relIds") drawingElem   = return [Diagram] -- Chart elemToParPart' ns element   | isElem ns "w" "r" element   , Just drawingElem <- findChildByName ns "w" "drawing" element-  , c_ns <- "http://schemas.openxmlformats.org/drawingml/2006/chart"-  , Just _ <- findElement (QName "chart" (Just c_ns) (Just "c")) drawingElem+  , Just _ <- filterElementName+                (matchQName "drawingml" "chart" (Just "c") "chart") drawingElem   = return [Chart] elemToParPart' ns element   | isElem ns "w" "r" element = do@@ -1146,8 +1128,8 @@ childElemToRun :: NameSpaces -> Element -> D [Run] childElemToRun ns element   | isElem ns "w" "drawing" element-  , pic_ns <- "http://schemas.openxmlformats.org/drawingml/2006/picture"-  , picElems <- findElements (QName "pic" (Just pic_ns) (Just "pic")) element+  , picElems <- filterElementsName+                 (matchQName "drawingml" "picture" (Just "pic") "pic") element   = let (title, alt) = getTitleAndAlt ns element         drawings = map (\el ->                          ((findBlip el >>= findAttrByName ns "r" "embed"), el))@@ -1161,13 +1143,13 @@        drawings childElemToRun ns element   | isElem ns "w" "drawing" element-  , c_ns <- "http://schemas.openxmlformats.org/drawingml/2006/chart"-  , Just _ <- findElement (QName "chart" (Just c_ns) (Just "c")) element+  , Just _ <- filterElementName+                 (matchQName "drawingml" "chart" (Just "c") "chart") element   = return [InlineChart] childElemToRun ns element   | isElem ns "w" "drawing" element-  , c_ns <- "http://schemas.openxmlformats.org/drawingml/2006/diagram"-  , Just _ <- findElement (QName "relIds" (Just c_ns) (Just "dgm")) element+  , Just _ <- filterElementName+                 (matchQName "drawingml" "diagram" (Just "dgm") "relIds") element   = return [InlineDiagram] childElemToRun ns element   | isElem ns "w" "footnoteReference" element@@ -1190,15 +1172,6 @@ elemToRun :: NameSpaces -> Element -> D [Run] elemToRun ns element   | isElem ns "w" "r" element-  , Just altCont <- findChildByName ns "mc" "AlternateContent" element =-    do let choices = findChildrenByName ns "mc" "Choice" altCont-           choiceChildren = concatMap (take 1 . elChildren) choices-       outputs <- mapD (childElemToRun ns) choiceChildren-       case outputs of-         r : _ -> return r-         []    -> throwError WrongElem-elemToRun ns element-  | isElem ns "w" "r" element   , Just drawingElem <- findChildByName ns "w" "drawing" element =     childElemToRun ns drawingElem elemToRun ns element@@ -1358,11 +1331,9 @@  findBlip :: Element -> Maybe Element findBlip el = do-  blip <- findElement (QName "blip" (Just a_ns) (Just "a")) el+  blip <- filterElementName (matchQName "drawingml" "main" (Just "a") "blip") el   -- return svg if present:   filterElementName (\(QName tag _ _) -> tag == "svgBlip") el `mplus` pure blip- where-  a_ns = "http://schemas.openxmlformats.org/drawingml/2006/main"  hasCaptionStyle :: ParagraphStyle -> Bool hasCaptionStyle parstyle = any (isCaptionStyleName . pStyleName) (pStyle parstyle)@@ -1387,3 +1358,23 @@        (qName name == "instrText" &&           let ws = T.words (strContent el)           in  ("Table" `elem` ws || "Figure" `elem` ws))++isNamespace :: Text -> Text -> Text -> Bool+isNamespace primary secondary url =+  -- first try transitional:+  case T.stripPrefix "http://schemas.openxmlformats.org/" url of+    Just path -> path == primary <> "/2006/" <> secondary+    Nothing -> -- then try strict:+      case T.stripPrefix "http://purl.oclc.org/ooxml/" url of+        Just path -> path == primary <> "/" <> snakeToCamel secondary+        Nothing -> False+ where+   snakeToCamel "custom-properties" = "customProperties"+   snakeToCamel "extended-properties" = "extendedProperties"+   snakeToCamel x = x++matchQName :: Text -> Text -> Maybe Text -> Text -> QName -> Bool+matchQName primary secondary mbprefix name (QName name' mbns' mbprefix') =+  name == name' &&+  (isNothing mbprefix || mbprefix' == mbprefix) &&+  maybe True (isNamespace primary secondary) mbns'
src/Text/Pandoc/Readers/Docx/Parse/Styles.hs view
@@ -239,8 +239,8 @@  stringToInteger :: Text -> Maybe Integer stringToInteger s = case Data.Text.Read.decimal s of-                      Right (x,_) -> Just x-                      Left _      -> Nothing+                      Right (x,t) | T.null t -> Just x+                      _                      -> Nothing  checkOnOff :: NameSpaces -> Element -> QName -> Maybe Bool checkOnOff ns rPr tag
src/Text/Pandoc/Readers/EndNote.hs view
@@ -81,6 +81,8 @@   let items = map toCitationItem $ filterElementsName (name "Cite") tree   return $ Citeproc.Citation{                      Citeproc.citationId = Nothing+                   , Citeproc.citationPrefix = Nothing+                   , Citeproc.citationSuffix = Nothing                    , Citeproc.citationNoteNumber = Nothing                    , Citeproc.citationItems = items                    }
src/Text/Pandoc/Readers/HTML.hs view
@@ -659,14 +659,10 @@                              else v ]   contents <- manyTill pAny (pCloses "pre" <|> eof)   let rawText = T.concat $ map tagToText contents-  -- drop leading newline if any-  let result' = case T.uncons rawText of-                     Just ('\n', xs) -> xs-                     _               -> rawText   -- drop trailing newline if any-  let result = case T.unsnoc result' of+  let result = case T.unsnoc rawText of                     Just (result'', '\n') -> result''-                    _                     -> result'+                    _                     -> rawText   return $ B.codeBlockWith attr result  tagToText :: Tag Text -> Text
src/Text/Pandoc/Readers/LaTeX.hs view
@@ -52,8 +52,8 @@ import Text.Pandoc.TeX (Tok (..), TokType (..)) import Text.Pandoc.Readers.LaTeX.Parsing import Text.Pandoc.Readers.LaTeX.Citation (citationCommands, cites)-import Text.Pandoc.Readers.LaTeX.Math (dollarsMath, inlineEnvironments,-                                       inlineEnvironment,+import Text.Pandoc.Readers.LaTeX.Math (withMathMode, dollarsMath,+                                       inlineEnvironments, inlineEnvironment,                                        mathDisplay, mathInline,                                        newtheorem, theoremstyle, proof,                                        theoremEnvironment)@@ -371,9 +371,11 @@     , ("hbox", rawInlineOr "hbox" $ processHBox <$> tok)     , ("vbox", rawInlineOr "vbox" tok)     , ("lettrine", rawInlineOr "lettrine" lettrine)-    , ("(", mathInline . untokenize <$> manyTill anyTok (controlSeq ")"))-    , ("[", mathDisplay . untokenize <$> manyTill anyTok (controlSeq "]"))-    , ("ensuremath", mathInline . untokenize <$> braced)+    , ("(", withMathMode+        (mathInline . untokenize <$> manyTill anyTok (controlSeq ")")))+    , ("[", withMathMode+        (mathDisplay . untokenize <$> manyTill anyTok (controlSeq "]")))+    , ("ensuremath", withMathMode (mathInline . untokenize <$> braced))     , ("texorpdfstring", const <$> tok <*> tok)     -- old TeX commands     , ("em", extractSpaces emph <$> inlines)@@ -961,6 +963,7 @@    , ("paragraph*", section ("",["unnumbered"],[]) 4)    , ("subparagraph", section nullAttr 5)    , ("subparagraph*", section ("",["unnumbered"],[]) 5)+   , ("minisec", section ("",["unnumbered","unlisted"],[]) 6) -- from KOMA    -- beamer slides    , ("frametitle", section nullAttr 3)    , ("framesubtitle", section nullAttr 4)@@ -1035,8 +1038,8 @@    , ("letter", env "letter" letterContents)    , ("minipage", divWith ("",["minipage"],[]) <$>        env "minipage" (skipopts *> spaces *> optional braced *> spaces *> blocks))-   , ("figure", env "figure" $ skipopts *> figure')-   , ("figure*", env "figure*" $ skipopts *> figure')+   , ("figure", env "figure" figure')+   , ("figure*", env "figure*" figure')    , ("subfigure", env "subfigure" $ skipopts *> tok *> figure')    , ("center", divWith ("", ["center"], []) <$> env "center" blocks)    , ("quote", blockQuote <$> env "quote" blocks)@@ -1208,15 +1211,18 @@  figure' :: PandocMonad m => LP m Blocks figure' = try $ do+  sp+  poshint <- option "" $ untokenize <$> bracketedToks+  sp   resetCaption   innerContent <- many $ try (Left <$> label) <|> (Right <$> block)   let content = walk go $ mconcat $ snd $ partitionEithers innerContent   st <- getState   let caption' = fromMaybe B.emptyCaption $ sCaption st   let mblabel  = sLastLabel st-  let attr     = case mblabel of-                   Just lab -> (lab, [], [])-                   Nothing  -> nullAttr+  let kvs = [("latex-placement", poshint) | not (T.null poshint)]+  let ident = fromMaybe "" mblabel+  let attr  = (ident, [], kvs)   case mblabel of     Nothing   -> pure ()     Just lab  -> do
src/Text/Pandoc/Readers/LaTeX/Inline.hs view
@@ -281,6 +281,7 @@   , ("_", lit "_")   , ("{", lit "{")   , ("}", lit "}")+  , ("-", lit "\x00ad") -- soft hyphen   , ("qed", lit "\a0\x25FB")   , ("lq", return (str "‘"))   , ("rq", return (str "’"))
src/Text/Pandoc/Readers/LaTeX/Math.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} module Text.Pandoc.Readers.LaTeX.Math-  ( dollarsMath+  ( withMathMode+  , dollarsMath   , inlineEnvironments   , inlineEnvironmentNames   , inlineEnvironment@@ -28,11 +29,19 @@ import qualified Data.Map as M import Data.Text (Text) +withMathMode :: PandocMonad m => LP m a -> LP m a+withMathMode p = do+  oldMathMode <- sMathMode <$> getState+  updateState $ \s -> s{ sMathMode = True }+  result <- p+  updateState $ \s -> s{ sMathMode = oldMathMode }+  return result+ dollarsMath :: PandocMonad m => LP m Inlines dollarsMath = do   symbol '$'   display <- option False (True <$ symbol '$')-  (do contents <- try $ untokenize <$> pDollarsMath 0+  (do contents <- try $ untokenize <$> withMathMode (pDollarsMath 0)       if display          then mathDisplay contents <$ symbol '$'          else return $ mathInline contents)@@ -70,7 +79,7 @@                                    "\n\\end{" <> y <> "}"  mathEnv :: PandocMonad m => Text -> LP m Text-mathEnv name = do+mathEnv name = withMathMode $ do   optional blankline   res <- manyTill anyTok (end_ name)   return $ stripTrailingNewlines $ untokenize res@@ -89,20 +98,21 @@ inlineEnvironments = M.fromList [     ("displaymath", mathEnvWith id Nothing "displaymath")   , ("math", math <$> mathEnv "math")-  , ("equation", mathEnvWith id Nothing "equation")-  , ("equation*", mathEnvWith id Nothing "equation*")-  , ("gather", mathEnvWith id (Just "gathered") "gather")-  , ("gather*", mathEnvWith id (Just "gathered") "gather*")-  , ("multline", mathEnvWith id (Just "gathered") "multline")-  , ("multline*", mathEnvWith id (Just "gathered") "multline*")-  , ("eqnarray", mathEnvWith id (Just "aligned") "eqnarray")-  , ("eqnarray*", mathEnvWith id (Just "aligned") "eqnarray*")-  , ("align", mathEnvWith id (Just "aligned") "align")-  , ("align*", mathEnvWith id (Just "aligned") "align*")-  , ("alignat", mathEnvWith id (Just "aligned") "alignat")-  , ("alignat*", mathEnvWith id (Just "aligned") "alignat*")-  , ("flalign", mathEnvWith id (Just "aligned") "flalign")-  , ("flalign*", mathEnvWith id (Just "aligned") "flalign*")+  , ("equation", mathEnvWith id (Just "equation") "equation")+  , ("equation*", mathEnvWith id (Just "equation*") "equation*")+  , ("gather", mathEnvWith id (Just "gather") "gather")+  , ("gather*", mathEnvWith id (Just "gather*") "gather*")+  , ("multline", mathEnvWith id (Just "multline") "multline")+  , ("multline*", mathEnvWith id (Just "multline*") "multline*")+  , ("eqnarray", mathEnvWith id (Just "eqnarray") "eqnarray")+  , ("eqnarray*", mathEnvWith id (Just "eqnarray*") "eqnarray*")+  , ("align", mathEnvWith id (Just "align") "align")+  , ("align*", mathEnvWith id (Just "align*") "align*")+  , ("alignat", mathEnvWith id (Just "alignat") "alignat")+  , ("alignat*", mathEnvWith id (Just "alignat*") "alignat*")+  , ("flalign", mathEnvWith id (Just "flalign") "flalign")+  , ("flalign*", mathEnvWith id (Just "flalign*") "flalign*")+  -- the following are not yet handled by texmath, so we use substitutes:   , ("dmath", mathEnvWith id Nothing "dmath")   , ("dmath*", mathEnvWith id Nothing "dmath*")   , ("dgroup", mathEnvWith id (Just "aligned") "dgroup")
src/Text/Pandoc/Readers/LaTeX/Parsing.hs view
@@ -157,6 +157,7 @@                             , sLogMessages   :: [LogMessage]                             , sIdentifiers   :: Set.Set Text                             , sVerbatimMode  :: Bool+                            , sMathMode      :: Bool                             , sCaption       :: Maybe Caption                             , sInListItem    :: Bool                             , sInTableCell   :: Bool@@ -186,6 +187,7 @@                               , sLogMessages   = []                               , sIdentifiers   = Set.empty                               , sVerbatimMode  = False+                              , sMathMode      = False                               , sCaption       = Nothing                               , sInListItem    = False                               , sInTableCell   = False@@ -650,6 +652,9 @@     _ -> return ts' trySpecialMacro "iftrue" ts = handleIf True ts trySpecialMacro "iffalse" ts = handleIf False ts+trySpecialMacro "ifmmode" ts = do+  mathMode <- sMathMode <$> getState+  handleIf mathMode ts trySpecialMacro _ _ = mzero  handleIf :: PandocMonad m => Bool -> [Tok] -> LP m [Tok]
src/Text/Pandoc/Readers/Man.hs view
@@ -219,7 +219,16 @@   (ControlLine _ args _) <- mmacro "TH"   let adjustMeta =        case args of-         (x:y:z:_) -> setMeta "title" (linePartsToInlines x) .+         (x:y:z:a:b:_) -> setMeta "title" (linePartsToInlines x) .+                          setMeta "section" (linePartsToInlines y) .+                          setMeta "date" (linePartsToInlines z) .+                          setMeta "footer" (linePartsToInlines a) .+                          setMeta "header" (linePartsToInlines b)+         [x,y,z,a] -> setMeta "title" (linePartsToInlines x) .+                      setMeta "section" (linePartsToInlines y) .+                      setMeta "date" (linePartsToInlines z) .+                      setMeta "footer" (linePartsToInlines a)+         [x,y,z]   -> setMeta "title" (linePartsToInlines x) .                       setMeta "section" (linePartsToInlines y) .                       setMeta "date" (linePartsToInlines z)          [x,y]     -> setMeta "title" (linePartsToInlines x) .
src/Text/Pandoc/Readers/Markdown.hs view
@@ -845,7 +845,9 @@        return (num, style, delim))  listStart :: PandocMonad m => MarkdownParser m ()-listStart = bulletListStart <|> Control.Monad.void (orderedListStart Nothing)+listStart = bulletListStart+        <|> Control.Monad.void (orderedListStart Nothing)+        <|> defListStart  listLine :: PandocMonad m => Int -> MarkdownParser m Text listLine continuationIndent = try $ do@@ -967,67 +969,39 @@  -- definition lists -defListMarker :: PandocMonad m => MarkdownParser m ()-defListMarker = do-  sps <- nonindentSpaces+defListStart :: PandocMonad m => MarkdownParser m ()+defListStart = do+  nonindentSpaces   char ':' <|> char '~'-  tabStop <- getOption readerTabStop-  let remaining = tabStop - (T.length sps + 1)-  if remaining > 0-     then try (count remaining (char ' ')) <|> string "\t" <|> many1 spaceChar-     else mzero-  return ()+  gobbleSpaces 1 <|> () <$ lookAhead newline+  try (gobbleAtMostSpaces 3 >> notFollowedBy spaceChar) <|> return () -definitionListItem :: PandocMonad m => Bool -> MarkdownParser m (F (Inlines, [Blocks]))-definitionListItem compact = try $ do+definitionListItem :: PandocMonad m => MarkdownParser m (F (Inlines, [Blocks]))+definitionListItem = try $ do   rawLine' <- anyLine-  raw <- many1 $ defRawBlock compact   term <- parseFromString' (trimInlinesF <$> inlines) rawLine'-  contents <- mapM (parseFromString' parseBlocks . (<> "\n")) raw+  isTight <- (False <$ blanklines) <|> pure True+  fourSpaceRule <- (True <$ guardEnabled Ext_four_space_rule) <|> pure False+  contents <- many1 $ listItem fourSpaceRule defListStart   optional blanklines-  return $ liftM2 (,) term (sequence contents)+  return $ liftM2 (,)+              term+              ((if isTight+                   then fmap (fmap (fmap paraToPlain))+                   else id) (sequence contents)) -defRawBlock :: PandocMonad m => Bool -> MarkdownParser m Text-defRawBlock compact = try $ do-  hasBlank <- option False $ blankline >> return True-  defListMarker-  firstline <- anyLineNewline-  let dline = try-               ( do notFollowedBy blankline-                    notFollowedByHtmlCloser-                    notFollowedByDivCloser-                    if compact -- laziness not compatible with compact-                       then () <$ indentSpaces-                       else (() <$ indentSpaces)-                             <|> notFollowedBy defListMarker-                    anyLine )-  rawlines <- many dline-  cont <- fmap T.concat $ many $ try $ do-            trailing <- option "" blanklines-            ln <- indentSpaces >> notFollowedBy blankline >> anyLine-            lns <- many dline-            return $ trailing <> T.unlines (ln:lns)-  return $ trimr (firstline <> T.unlines rawlines <> cont) <>-            if hasBlank || not (T.null cont) then "\n\n" else ""+paraToPlain :: Block -> Block+paraToPlain (Para ils) = Plain ils+paraToPlain x = x  definitionList :: PandocMonad m => MarkdownParser m (F Blocks) definitionList = try $ do+  guardEnabled Ext_definition_lists   lookAhead (anyLine >>              optional (blankline >> notFollowedBy (Control.Monad.void table)) >>              -- don't capture table caption as def list!-             defListMarker)-  compactDefinitionList <|> normalDefinitionList--compactDefinitionList :: PandocMonad m => MarkdownParser m (F Blocks)-compactDefinitionList = do-  guardEnabled Ext_compact_definition_lists-  items <- fmap sequence $ many1 $ definitionListItem True-  return $ B.definitionList <$> fmap compactifyDL items--normalDefinitionList :: PandocMonad m => MarkdownParser m (F Blocks)-normalDefinitionList = do-  guardEnabled Ext_definition_lists-  items <- fmap sequence $ many1 $ definitionListItem False+             defListStart)+  items <- fmap sequence $ many1 definitionListItem   return $ B.definitionList <$> items  --@@ -1083,8 +1057,12 @@   let alt = case "alt" `lookup` attribs of               Just alt'       -> B.text alt'               _               -> capt-      attribs' = filter ((/= "alt") . fst) attribs-      figattr = (ident, mempty, mempty)+      attribs' = filter ((/= "latex-placement") . fst)+                    (filter ((/= "alt") . fst) attribs)+      figattribs = case lookup "latex-placement" attribs of+        Just p -> [("latex-placement", p)]+        _      -> mempty+      figattr = (ident, mempty, figattribs)       caption = B.simpleCaption $ B.plain capt       figbody = B.plain $ B.imageWith ("", classes, attribs') url title alt   in B.figureWith figattr caption figbody@@ -1230,7 +1208,7 @@ -- one (or zero) line of text. simpleTableHeader :: PandocMonad m                   => Bool  -- ^ Headerless table-                  -> MarkdownParser m (F [Blocks], [Alignment], [Int])+                  -> MarkdownParser m (F [[Blocks]], [Alignment], [Int]) simpleTableHeader headless = try $ do   rawContent  <- if headless                     then return ""@@ -1252,7 +1230,7 @@   heads <- fmap sequence            $             mapM (parseFromString' (mconcat <$> many plain).trim) rawHeads'-  return (heads, aligns, indices)+  return (fmap (:[]) heads, aligns, indices)  -- Returns an alignment type for a table, based on a list of strings -- (the rows of the column header) and a number (the length of the@@ -1346,7 +1324,7 @@  multilineTableHeader :: PandocMonad m                      => Bool -- ^ Headerless table-                     -> MarkdownParser m (F [Blocks], [Alignment], [Int])+                     -> MarkdownParser m (F [[Blocks]], [Alignment], [Int]) multilineTableHeader headless = try $ do   unless headless $      tableSep >> notFollowedBy blankline@@ -1375,7 +1353,7 @@                     else map (T.unlines . map trim) rawHeadsList   heads <- fmap sequence $             mapM (parseFromString' (mconcat <$> many plain).trim) rawHeads-  return (heads, aligns, indices')+  return (fmap (:[]) heads, aligns, indices')  -- Parse a grid table:  starts with row of '-' on top, then header -- (which may be grid), then the rows,@@ -1420,7 +1398,7 @@   (rows :: F [[Blocks]]) <- sequence <$>                             mapM (fmap sequence . mapM cellContents) lines''   return $-    toTableComponents' NormalizeHeader aligns widths <$> headCells <*> rows+    toTableComponents' NormalizeHeader aligns widths <$> fmap (:[]) headCells <*> rows  sepPipe :: PandocMonad m => MarkdownParser m () sepPipe = try $ do@@ -2253,7 +2231,7 @@   rest <- option (return []) $ try $ char ';' >> spnl >> citeList   spnl   char ']'-  notFollowedBy $ oneOf "[("+  notFollowedBy $ oneOf "[({"   return $ do     suff' <- suff     rest' <- rest
src/Text/Pandoc/Readers/ODT/Arrows/State.hs view
@@ -17,7 +17,21 @@ faster and easier to implement this way. -} -module Text.Pandoc.Readers.ODT.Arrows.State where+module Text.Pandoc.Readers.ODT.Arrows.State+  ( ArrowState(..)+  , withState+  , modifyState+  , ignoringState+  , fromState+  , extractFromState+  , tryModifyState+  , withSubStateF+  , withSubStateF'+  , foldS+  , iterateS+  , iterateSL+  , iterateS'+  ) where  import Control.Arrow import qualified Control.Category as Cat
src/Text/Pandoc/Readers/ODT/Arrows/Utils.hs view
@@ -19,7 +19,40 @@ -}  -- We export everything-module Text.Pandoc.Readers.ODT.Arrows.Utils where+module Text.Pandoc.Readers.ODT.Arrows.Utils+  ( and2+  , and3+  , and4+  , and5+  , and6+  , liftA2+  , liftA3+  , liftA4+  , liftA5+  , liftA6+  , liftA+  , duplicate+  , (>>%)+  , keepingTheValue+  , (^|||)+  , (|||^)+  , (^|||^)+  , (^&&&)+  , (&&&^)+  , choiceToMaybe+  , maybeToChoice+  , returnV+  , FallibleArrow+  , liftAsSuccess+  , (>>?)+  , (>>?^)+  , (>>?^?)+  , (^>>?)+  , (>>?!)+  , (>>?%)+  , (>>?%?)+  , ifFailedDo+  ) where  import Prelude hiding (Applicative(..)) import Control.Arrow
src/Text/Pandoc/Readers/ODT/Base.hs view
@@ -10,7 +10,11 @@ Core types of the odt reader. -} -module Text.Pandoc.Readers.ODT.Base where+module Text.Pandoc.Readers.ODT.Base+  ( ODTConverterState+  , XMLReader+  , XMLReaderSafe+  ) where  import Text.Pandoc.Readers.ODT.Generic.XMLConverter import Text.Pandoc.Readers.ODT.Namespaces
src/Text/Pandoc/Readers/ODT/ContentReader.hs view
@@ -795,15 +795,26 @@ read_table        :: BlockMatcher read_table         = matchingElement NsTable "table"                      $ liftA simpleTable'-                     $ matchChildContent'  [ read_table_row-                                           ]+                     $ (matchChildContent' [read_table_header]) &&&+                       (matchChildContent'  [read_table_row]) --- | A simple table without a caption or headers--- | Infers the number of headers from rows-simpleTable' :: [[Blocks]] -> Blocks-simpleTable' []         = simpleTable [] []-simpleTable' (x : rest) = simpleTable (fmap (const defaults) x) (x : rest)-  where defaults = fromList []+-- | A simple table without a caption.+simpleTable' :: ([[Blocks]], [[Blocks]]) -> Blocks+simpleTable' (headers, rows) =+  table emptyCaption (replicate numcols defaults) th [tb] tf+  where+    defaults = (AlignDefault, ColWidthDefault)+    numcols = maximum $ map length $ headers ++ rows+    toRow = Row nullAttr . map simpleCell+    th = TableHead nullAttr $ map toRow headers+    tb = TableBody nullAttr 0 [] $ map toRow rows+    tf = TableFoot nullAttr []++--+read_table_header :: ElementMatcher [[Blocks]]+read_table_header = matchingElement NsTable "table-header-rows"+                      $ matchChildContent' [ read_table_row+                                           ]  -- read_table_row    :: ElementMatcher [[Blocks]]
src/Text/Pandoc/Readers/ODT/Generic/Fallible.hs view
@@ -17,7 +17,21 @@ -}  -- We export everything-module Text.Pandoc.Readers.ODT.Generic.Fallible where+module Text.Pandoc.Readers.ODT.Generic.Fallible+  ( Failure+  , Fallible+  , maybeToEither+  , eitherToMaybe+  , recover+  , failWith+  , failEmpty+  , succeedWith+  , collapseEither+  , chooseMax+  , chooseMaxWith+  , ChoiceVector(..)+  , SuccessList(..)+  ) where  -- | Default for now. Will probably become a class at some point. type Failure = ()
src/Text/Pandoc/Readers/ODT/Generic/Namespaces.hs view
@@ -11,7 +11,11 @@ typesafe Haskell namespace identifiers and unsafe "real world" namespaces. -} -module Text.Pandoc.Readers.ODT.Generic.Namespaces where+module Text.Pandoc.Readers.ODT.Generic.Namespaces+  ( NameSpaceIRI+  , NameSpaceIRIs+  , NameSpaceID(..)+  ) where  import qualified Data.Map as M import Data.Text (Text)
src/Text/Pandoc/Readers/ODT/Generic/SetMap.hs view
@@ -10,7 +10,13 @@ A map of values to sets of values. -} -module Text.Pandoc.Readers.ODT.Generic.SetMap where+module Text.Pandoc.Readers.ODT.Generic.SetMap+  ( SetMap+  , empty+  , fromList+  , insert+  , union3+  ) where  import qualified Data.Map as M import qualified Data.Set as S
src/Text/Pandoc/Readers/Org/Blocks.hs view
@@ -115,7 +115,7 @@  stringyMetaAttribute :: Monad m => OrgParser m (Text, Text) stringyMetaAttribute = try $ do-  metaLineStart+  metaLineStart *> notFollowedBy (stringAnyCase "begin_")   attrName <- T.toLower <$> many1TillChar nonspaceChar (char ':')   skipSpaces   attrValue <- anyLine <|> ("" <$ newline)@@ -184,9 +184,9 @@     case T.toLower blkType of       "export"    -> exportBlock       "comment"   -> rawBlockLines (const mempty)-      "html"      -> rawBlockLines (return . B.rawBlock (lowercase blkType))-      "latex"     -> rawBlockLines (return . B.rawBlock (lowercase blkType))-      "ascii"     -> rawBlockLines (return . B.rawBlock (lowercase blkType))+      "html"      -> rawBlockLines (return . B.rawBlock (T.toLower blkType))+      "latex"     -> rawBlockLines (return . B.rawBlock (T.toLower blkType))+      "ascii"     -> rawBlockLines (return . B.rawBlock (T.toLower blkType))       "example"   -> exampleBlock blockAttrs       "quote"     -> parseBlockLines (fmap B.blockQuote)       "verse"     -> verseBlock@@ -205,10 +205,11 @@                    in fmap $ B.divWith (ident, classes ++ [blkType], kv)  where    blockHeaderStart :: Monad m => OrgParser m Text-   blockHeaderStart = try $ skipSpaces *> stringAnyCase "#+begin_" *> orgArgWord--   lowercase :: Text -> Text-   lowercase = T.toLower+   blockHeaderStart = try $ do+     skipSpaces+     metaLineStart+     stringAnyCase "begin_"+     many1Char (satisfy (not . isSpace))  admonitionBlock :: PandocMonad m                 => Text -> BlockAttributes -> Text -> OrgParser m (F Blocks)@@ -427,10 +428,11 @@   return (argKey, paramValue)  orgParamValue :: Monad m => OrgParser m Text-orgParamValue = try $ fmap T.pack $+orgParamValue = try $   skipSpaces     *> notFollowedBy orgArgKey-    *> noneOf "\n\r" `many1Till` endOfValue+    *> ((char '"' *> manyChar (noneOf "\n\r\"") <* char '"') <|>+        noneOf "\n\r" `many1TillChar` endOfValue)     <* skipSpaces  where   endOfValue = lookAhead $  try (skipSpaces <* oneOf "\n\r")
src/Text/Pandoc/Readers/Org/Inlines.hs view
@@ -2,8 +2,8 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Readers.Org.Inlines-   Copyright   : Copyright (C) 2014-2024 Albert Krewinkel-   License     : GNU GPL, version 2 or above+   Copyright   : Copyright (C) 2014-2025 Albert Krewinkel+   License     : GPL-2.0-or-later     Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com> @@ -88,17 +88,18 @@          , inlineCodeBlock          , str          , endline+         , subscript   -- takes precedence over underlined text+         , superscript          , emphasizedText          , code          , math          , displayMath          , verbatim-         , subscript-         , superscript          , inlineLaTeX          , exportSnippet          , macro-         , smart+         , smartQuotes+         , specialStrings          , symbol          ] <* (guard =<< newlinesCountWithinLimits)   <?> "inline"@@ -199,10 +200,10 @@                                 citationSuffix d <> B.toList aff' }])  citeItems :: PandocMonad m => OrgParser m (F [Citation])-citeItems = sequence <$> citeItem `sepBy1` (char ';')+citeItems = sequence <$> sepBy1' citeItem (char ';' <* void (many spaceChar))  citeItem :: PandocMonad m => OrgParser m (F Citation)-citeItem = do+citeItem = try $ do   pref <- citePrefix   itemKey <- orgCiteKey   suff <- citeSuffix@@ -246,37 +247,36 @@  citeSuffix :: PandocMonad m => OrgParser m (F Inlines) citeSuffix =-  rawAffix False >>= parseFromString parseSuffix- where-   parseSuffix = do-     hasSpace <- option False-              (True <$ try (spaceChar >> skipSpaces >> lookAhead nonspaceChar))-     ils <- trimInlinesF . mconcat <$> many inline-     return $ if hasSpace-                 then (B.space <>) <$> ils-                 else ils+  rawAffix False >>= parseFromString (mconcat <$> many inline)  citeStyle :: PandocMonad m => OrgParser m (CiteStyle, [CiteVariant])-citeStyle = option (DefStyle, []) $ do-  sty <- option DefStyle $ try $ char '/' *> orgCiteStyle+citeStyle = do+  sty <- option NilStyle $ try $ char '/' *> orgCiteStyle   variants <- option [] $ try $ char '/' *> orgCiteVariants   return (sty, variants)  orgCiteStyle :: PandocMonad m => OrgParser m CiteStyle-orgCiteStyle = choice $ map try-  [ NoAuthorStyle <$ string "noauthor"-  , NoAuthorStyle <$ string "na"-  , LocatorsStyle <$ string "locators"-  , LocatorsStyle <$ char 'l'-  , NociteStyle <$ string "nocite"-  , NociteStyle <$ char 'n'-  , TextStyle <$ string "text"-  , TextStyle <$ char 't'-  ]+orgCiteStyle = try $ do+  s <- many1 letter+  case s of+    "author" -> pure AuthorStyle+    "a" -> pure AuthorStyle+    "noauthor" -> pure NoAuthorStyle+    "na" -> pure NoAuthorStyle+    "nocite" -> pure NociteStyle+    "n" -> pure NociteStyle+    "text" -> pure TextStyle+    "t" -> pure TextStyle+    "note" -> pure NoteStyle+    "ft" -> pure NoteStyle+    "numeric" -> pure NumericStyle+    "nb" -> pure NumericStyle+    "nil" -> pure NilStyle+    _ -> fail $ "Unknown org cite style " <> show s  orgCiteVariants :: PandocMonad m => OrgParser m [CiteVariant] orgCiteVariants =-  (fullnameVariant `sepBy1` (char '-')) <|> (many1 onecharVariant)+  (sepBy1' fullnameVariant (char '-')) <|> (many1 onecharVariant)  where   fullnameVariant = choice $ map try      [ Bare <$ string "bare"@@ -290,11 +290,14 @@      ]  data CiteStyle =-    NoAuthorStyle+    AuthorStyle+  | NoAuthorStyle   | LocatorsStyle   | NociteStyle   | TextStyle-  | DefStyle+  | NoteStyle+  | NumericStyle+  | NilStyle   deriving Show  data CiteVariant =@@ -591,11 +594,25 @@ code      :: PandocMonad m => OrgParser m (F Inlines) code      = return . B.code     <$> verbatimBetween '~' +-- | Returns 'True' if the parser position right after a string, and 'False'+-- otherwise.+isAfterString :: PandocMonad m => OrgParser m Bool+isAfterString = do+  pos <- getPosition+  st  <- getState+  pure $ getLastStrPos st == Just pos++-- | Parses subscript markup. Subscripts must be preceded by a string. subscript   :: PandocMonad m => OrgParser m (F Inlines)-subscript   = fmap B.subscript   <$> try (char '_' *> subOrSuperExpr)+subscript   = do+  guard =<< isAfterString+  fmap B.subscript   <$> try (char '_' *> subOrSuperExpr) +-- | Parses superscript markup. Superscript must be preceded by a string. superscript :: PandocMonad m => OrgParser m (F Inlines)-superscript = fmap B.superscript <$> try (char '^' *> subOrSuperExpr)+superscript = do+  guard =<< isAfterString+  fmap B.superscript <$> try (char '^' *> subOrSuperExpr)  math      :: PandocMonad m => OrgParser m (F Inlines) math      = return . B.math      <$> choice [ math1CharBetween '$'@@ -890,29 +907,27 @@   escapedComma = try $ char '\\' *> oneOf ",\\"   eoa = string ")}}}" -smart :: PandocMonad m => OrgParser m (F Inlines)-smart = choice [doubleQuoted, singleQuoted, orgApostrophe, orgDash, orgEllipses]+smartQuotes :: PandocMonad m => OrgParser m (F Inlines)+smartQuotes = do+  guard =<< getExportSetting exportSmartQuotes+  choice [doubleQuoted, singleQuoted, orgApostrophe]   where-    orgDash = do-      guardOrSmartEnabled =<< getExportSetting exportSpecialStrings-      pure <$> dash <* updatePositions '-'-    orgEllipses = do-      guardOrSmartEnabled =<< getExportSetting exportSpecialStrings-      pure <$> ellipses <* updatePositions '.'     orgApostrophe = do-      guardEnabled Ext_smart       (char '\'' <|> char '\8217') <* updateLastPreCharPos                                    <* updateLastForbiddenCharPos       returnF (B.str "\x2019") -guardOrSmartEnabled :: PandocMonad m => Bool -> OrgParser m ()-guardOrSmartEnabled b = do-  smartExtension <- extensionEnabled Ext_smart <$> getOption readerExtensions-  guard (b || smartExtension)+specialStrings :: PandocMonad m => OrgParser m (F Inlines)+specialStrings = do+  guard =<< getExportSetting exportSpecialStrings+  choice [orgDash, orgEllipses, shyHyphen]+  where+    shyHyphen   = pure <$> (B.str "\173" <$ string "\\-") <* updatePositions '-'+    orgDash     = pure <$> dash <* updatePositions '-'+    orgEllipses = pure <$> ellipses <* updatePositions '.'  singleQuoted :: PandocMonad m => OrgParser m (F Inlines) singleQuoted = try $ do-  guardOrSmartEnabled =<< getExportSetting exportSmartQuotes   singleQuoteStart   updatePositions '\''   withQuoteContext InSingleQuote $@@ -924,7 +939,6 @@ -- in the same paragraph. doubleQuoted :: PandocMonad m => OrgParser m (F Inlines) doubleQuoted = try $ do-  guardOrSmartEnabled =<< getExportSetting exportSmartQuotes   doubleQuoteStart   updatePositions '"'   contents <- mconcat <$> many (try $ notFollowedBy doubleQuoteEnd >> inline)
src/Text/Pandoc/Readers/Org/Meta.hs view
@@ -252,7 +252,11 @@   where    todoKeyword :: Monad m => OrgParser m Text-   todoKeyword = many1Char nonspaceChar <* skipSpaces+   todoKeyword = do+     keyword <- many1Char nonspaceChar+     let cleanKeyword = T.takeWhile (/= '(') keyword+     skipSpaces+     return cleanKeyword     todoKeywords :: Monad m => OrgParser m [Text]    todoKeywords = try $
src/Text/Pandoc/Readers/Org/ParserState.hs view
@@ -3,7 +3,7 @@ {-# LANGUAGE OverloadedStrings     #-} {- |    Module      : Text.Pandoc.Readers.Org.ParserState-   Copyright   : Copyright (C) 2014-2024 Albert Krewinkel+   Copyright   : Copyright (C) 2014-2025 Albert Krewinkel    License     : GNU GPL, version 2 or above     Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>@@ -49,7 +49,7 @@ import Text.Pandoc.Builder (Blocks) import Text.Pandoc.Definition (Meta (..), nullMeta) import Text.Pandoc.Logging-import Text.Pandoc.Options (ReaderOptions (..))+import Text.Pandoc.Options (ReaderOptions (..), Extension(..), isEnabled) import Text.Pandoc.Parsing (Future, HasIdentifierList (..),                             HasIncludeFiles (..), HasLastStrPosition (..),                             HasLogMessages (..), HasMacros (..),@@ -193,7 +193,15 @@  optionsToParserState :: ReaderOptions -> OrgParserState optionsToParserState opts =-  def { orgStateOptions = opts }+  let exportSettings = defaultExportSettings+        { exportSmartQuotes = isEnabled Ext_smart opts ||+                              isEnabled Ext_smart_quotes opts+        , exportSpecialStrings = isEnabled Ext_smart opts ||+                                 isEnabled Ext_special_strings opts+        }+  in def { orgStateOptions = opts+         , orgStateExportSettings = exportSettings+         }  registerTodoSequence :: TodoSequence -> OrgParserState -> OrgParserState registerTodoSequence todoSeq st =
src/Text/Pandoc/Readers/Org/Parsing.hs view
@@ -1,6 +1,6 @@ {- |    Module      : Text.Pandoc.Readers.Org.Parsing-   Copyright   : Copyright (C) 2014-2024 Albert Krewinkel+   Copyright   : Copyright (C) 2014-2025 Albert Krewinkel    License     : GNU GPL, version 2 or above     Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>@@ -40,6 +40,7 @@   , many1Till   , many1TillChar   , notFollowedBy'+  , sepBy1'   , spaceChar   , nonspaceChar   , skipSpaces@@ -53,6 +54,7 @@   , guardEnabled   , updateLastStrPos   , notAfterString+  , getLastStrPos   , ParserState (..)   , registerHeader   , QuoteContext (..)
src/Text/Pandoc/Readers/Pod.hs view
@@ -258,7 +258,11 @@     entity (T.stripPrefix "0" -> Just suf)         | Just (n, "") <- oct (T.unpack suf) = lookupEntity $ "#" <> tshow n     entity (TR.decimal @Integer -> Right (x, "")) = lookupEntity $ "#" <> tshow x-    entity x = lookupEntity x+    -- named entities in Commonmark.Entity de facto have to be looked up with+    -- the semicolon at the end. perlpodspec says arguments to E<> must be+    -- alphanumeric, so an argument that already has a trailing semicolon+    -- is bogus anyway, so just paste the semicolon on unconditionally.+    entity x = lookupEntity (x <> ";")  -- god knows there must be a higher order way of writing this thing, where we -- have multiple different possible parser states within the link argument
src/Text/Pandoc/Readers/RST.hs view
@@ -1395,7 +1395,7 @@ -- Parse a table row and return a list of blocks (columns). simpleTableRow :: PandocMonad m => [Int] -> RSTParser m [Blocks] simpleTableRow indices = do-  notFollowedBy' simpleTableFooter+  notFollowedBy' (blanklines <|> simpleTableFooter)   firstLine <- simpleTableRawLine indices   conLines  <- many $ simpleTableRawLineWithInitialEmptyCell indices   let cols = map T.unlines . transpose $ firstLine : conLines ++@@ -1409,12 +1409,12 @@  simpleTableHeader :: PandocMonad m                   => Bool  -- ^ Headerless table-                  -> RSTParser m ([Blocks], [Alignment], [Int])+                  -> RSTParser m ([[Blocks]], [Alignment], [Int]) simpleTableHeader headless = try $ do   optional blanklines   rawContent  <- if headless-                    then return ""-                    else simpleTableSep '=' >> anyLine+                    then return [""]+                    else simpleTableSep '=' >> many1 (notFollowedBy (simpleDashedLines '=') >> anyLine)   dashes      <- if headless                     then simpleDashedLines '='                     else simpleDashedLines '=' <|> simpleDashedLines '-'@@ -1424,8 +1424,8 @@   let aligns   = replicate (length lines') AlignDefault   let rawHeads = if headless                     then []-                    else simpleTableSplitLine indices rawContent-  heads <- mapM ( parseFromString' (mconcat <$> many plain) . trim) rawHeads+                    else map (simpleTableSplitLine indices) rawContent+  heads <- mapM ( mapM $ parseFromString' (mconcat <$> many plain) . trim) rawHeads   return (heads, aligns, indices)  -- Parse a simple table.@@ -1495,7 +1495,7 @@  escapedChar :: Monad m => RSTParser m Inlines escapedChar = do c <- escaped anyChar-                 unless (canPrecedeOpener c) $ updateLastStrPos+                 unless (canPrecedeOpener c) updateLastStrPos                  return $ if c == ' ' || c == '\n' || c == '\r'                              -- '\ ' is null in RST                              then mempty@@ -1509,7 +1509,7 @@ symbol :: Monad m => RSTParser m Inlines symbol = do   c <- oneOf specialChars-  unless (canPrecedeOpener c) $ updateLastStrPos+  unless (canPrecedeOpener c) updateLastStrPos   return $ B.str $ T.singleton c  -- parses inline code, between codeStart and codeEnd
src/Text/Pandoc/Readers/TikiWiki.hs view
@@ -24,8 +24,7 @@ import Data.Text (Text) import qualified Data.Text as T import qualified Text.Pandoc.Builder as B-import Text.Pandoc.Class.CommonState (CommonState (..))-import Text.Pandoc.Class.PandocMonad (PandocMonad (..))+import Text.Pandoc.Class.PandocMonad (PandocMonad (..), getVerbosity) import Text.Pandoc.Definition import Text.Pandoc.Logging (Verbosity (..)) import Text.Pandoc.Options@@ -71,7 +70,7 @@  block :: PandocMonad m => TikiWikiParser m B.Blocks block = do-  verbosity <- getsCommonState stVerbosity+  verbosity <- getVerbosity   pos <- getPosition   res <- mempty <$ skipMany1 blankline          <|> blockElements
src/Text/Pandoc/Readers/Typst.hs view
@@ -50,8 +50,9 @@ import Typst.Methods (formatNumber, applyPureFunction) import Typst.Types import qualified Data.Vector as V---- import Debug.Trace+import System.FilePath (takeDirectory)+import qualified System.FilePath.Windows as Windows+import qualified System.FilePath.Posix as Posix  -- | Read Typst from an input string and return a Pandoc document. readTypst :: (PandocMonad m, ToSources a)@@ -73,9 +74,10 @@       case res of         Left e -> throwError $ PandocParseError $ tshow e         Right content -> do-          let labs = findLabels [content]+          let content' = fixNesting content+          let labs = findLabels [content']           runParserT pPandoc defaultPState{ sLabels = labs }-            inputName [content] >>=+            inputName [content'] >>=               either (throwError . PandocParseError . T.pack . show) pure  pBlockElt :: PandocMonad m => P m B.Blocks@@ -90,7 +92,7 @@           ignored ("unknown block element " <> tname <>                    " at " <> tshow pos)           pure mempty-        Just handler -> handler mbident fields+        Just handler -> handler pos mbident fields     _ -> pure mempty  pInline :: PandocMonad m => P m B.Inlines@@ -120,15 +122,38 @@                ignored ("unknown inline element " <> tname <>                         " at " <> tshow pos)                pure mempty-             Just handler -> handler Nothing (M.mapKeys targetToKey fields)+             Just handler -> handler pos Nothing (M.mapKeys targetToKey fields)          else do           case M.lookup name inlineHandlers of             Nothing -> do               ignored ("unknown inline element " <> tname <>                        " at " <> tshow pos)               pure mempty-            Just handler -> handler Nothing fields+            Just handler -> handler pos Nothing fields +-- Pull block elements out of inline elements, e.g.+-- Elt "smallcaps" [ Elt "heading" [..] ] ->+-- Elt "heading" [ Elt "smallcaps" [..]]. See #11017.+fixNesting :: Content -> Content+fixNesting el@(Elt name pos fields)+  | Just (VContent elts) <- M.lookup "body" fields+  = let elts' = fmap fixNesting elts+        fields' = M.insert "body" (VContent elts') fields+        in if isInline el+              then case getField "body" fields' of+                        Just ([el'@(Elt name' pos' fields'')] :: Seq Content)+                          | isBlock el'+                          , not (isInline el')+                          , "body" `M.member` fields''+                          -> Elt name' pos' $+                               M.insert "body" (VContent+                                                (Seq.singleton+                                                  (Elt name pos fields'')))+                                        fields'+                        _ -> Elt name pos fields'+              else Elt name pos fields'+fixNesting x = x+ pPandoc :: PandocMonad m => P m B.Pandoc pPandoc = do   Elt "document" _ fields <- pTok isDocument@@ -208,31 +233,34 @@ blockKeys :: Set.Set Identifier blockKeys = Set.fromList $ M.keys   (blockHandlers :: M.Map Identifier-     (Maybe Text -> M.Map Identifier Val -> P PandocPure B.Blocks))+     (Maybe SourcePos -> Maybe Text ->+      M.Map Identifier Val -> P PandocPure B.Blocks))  inlineKeys :: Set.Set Identifier inlineKeys = Set.fromList $ M.keys   (inlineHandlers :: M.Map Identifier-     (Maybe Text -> M.Map Identifier Val -> P PandocPure B.Inlines))+     (Maybe SourcePos -> Maybe Text ->+      M.Map Identifier Val -> P PandocPure B.Inlines))  blockHandlers :: PandocMonad m =>                    M.Map Identifier-                   (Maybe Text -> M.Map Identifier Val -> P m B.Blocks)+                   (Maybe SourcePos -> Maybe Text ->+                    M.Map Identifier Val -> P m B.Blocks) blockHandlers = M.fromList-  [("text", \_ fields -> do+  [("text", \_ _ fields -> do       body <- getField "body" fields       -- sometimes text elements include para breaks       notFollowedBy $ void $ pWithContents pInlines body       pWithContents pBlocks body)-  ,("box", \_ fields -> do+  ,("box", \_ _ fields -> do       body <- getField "body" fields       B.divWith ("", ["box"], []) <$> pWithContents pBlocks body)-  ,("heading", \mbident fields -> do+  ,("heading", \_ mbident fields -> do       body <- getField "body" fields       lev <- getField "level" fields <|> pure 1       B.headerWith (fromMaybe "" mbident,[],[]) lev          <$> pWithContents pInlines body)-  ,("quote", \_ fields -> do+  ,("quote", \_ _ fields -> do       getField "block" fields >>= guard       body <- getField "body" fields >>= pWithContents pBlocks       attribution' <- getField "attribution" fields@@ -241,11 +269,11 @@                         else (\x -> B.para ("\x2014\xa0" <> x)) <$>                               (pWithContents pInlines attribution')       pure $ B.blockQuote $ body <> attribution)-  ,("list", \_ fields -> do+  ,("list", \_ _ fields -> do       children <- V.toList <$> getField "children" fields       B.bulletList <$> mapM (pWithContents pBlocks) children)-  ,("list.item", \_ fields -> getField "body" fields >>= pWithContents pBlocks)-  ,("enum", \_ fields -> do+  ,("list.item", \_ _ fields -> getField "body" fields >>= pWithContents pBlocks)+  ,("enum", \_ _ fields -> do       children <- V.toList <$> getField "children" fields       mbstart <- getField "start" fields       start <- case mbstart of@@ -274,8 +302,8 @@               _ -> (B.DefaultStyle, B.DefaultDelim)       let listAttr = (start, sty, delim)       B.orderedListWith listAttr <$> mapM (pWithContents pBlocks) children)-  ,("enum.item", \_ fields -> getField "body" fields >>= pWithContents pBlocks)-  ,("terms", \_ fields -> do+  ,("enum.item", \_ _ fields -> getField "body" fields >>= pWithContents pBlocks)+  ,("terms", \_ _ fields -> do       children <- V.toList <$> getField "children" fields       B.definitionList         <$> mapM@@ -287,38 +315,38 @@               _ -> pure (mempty, [])           )           children)-  ,("terms.item", \_ fields -> getField "body" fields >>= pWithContents pBlocks)-  ,("raw", \mbident fields -> do+  ,("terms.item", \_ _ fields -> getField "body" fields >>= pWithContents pBlocks)+  ,("raw", \_ mbident fields -> do       txt <- T.filter (/= '\r') <$> getField "text" fields       mblang <- getField "lang" fields       let attr = (fromMaybe "" mbident, maybe [] (\l -> [l]) mblang, [])       pure $ B.codeBlockWith attr txt)-  ,("parbreak", \_ _ -> pure mempty)-  ,("block", \mbident fields ->+  ,("parbreak", \_ _ _ -> pure mempty)+  ,("block", \_ mbident fields ->       maybe id (\ident -> B.divWith (ident, [], [])) mbident         <$> (getField "body" fields >>= pWithContents pBlocks))-  ,("place", \_ fields -> do+  ,("place", \_ _ fields -> do       ignored "parameters of place"       getField "body" fields >>= pWithContents pBlocks)-  ,("columns", \_ fields -> do+  ,("columns", \_ _ fields -> do       (cnt :: Integer) <- getField "count" fields       B.divWith ("", ["columns-flow"], [("count", T.pack (show cnt))])         <$> (getField "body" fields >>= pWithContents pBlocks))-  ,("rect", \_ fields ->+  ,("rect", \_ _ fields ->       B.divWith ("", ["rect"], []) <$> (getField "body" fields >>= pWithContents pBlocks))-  ,("circle", \_ fields ->+  ,("circle", \_ _ fields ->       B.divWith ("", ["circle"], []) <$> (getField "body" fields >>= pWithContents pBlocks))-  ,("ellipse", \_ fields ->+  ,("ellipse", \_ _ fields ->       B.divWith ("", ["ellipse"], []) <$> (getField "body" fields >>= pWithContents pBlocks))-  ,("polygon", \_ fields ->+  ,("polygon", \_ _ fields ->       B.divWith ("", ["polygon"], []) <$> (getField "body" fields >>= pWithContents pBlocks))-  ,("square", \_ fields ->+  ,("square", \_ _ fields ->       B.divWith ("", ["square"], []) <$> (getField "body" fields >>= pWithContents pBlocks))-  ,("align", \_ fields -> do+  ,("align", \_ _ fields -> do       alignment <- getField "alignment" fields       B.divWith ("", [], [("align", repr alignment)])         <$> (getField "body" fields >>= pWithContents pBlocks))-  ,("stack", \_ fields -> do+  ,("stack", \_ _ fields -> do       (dir :: Direction) <- getField "dir" fields `mplus` pure Ltr       rawchildren <- getField "children" fields       children <-@@ -333,9 +361,9 @@         B.divWith ("", [], [("stack", repr (VDirection dir))]) $           mconcat $             map (B.divWith ("", [], [])) children)-  ,("grid", \mbident fields -> parseTable mbident fields)-  ,("table", \mbident fields -> parseTable mbident fields)-  ,("figure", \mbident fields -> do+  ,("grid", \_ mbident fields -> parseTable mbident fields)+  ,("table", \_ mbident fields -> parseTable mbident fields)+  ,("figure", \_ mbident fields -> do       body <- getField "body" fields >>= pWithContents pBlocks       (mbCaption :: Maybe (Seq Content)) <- getField "caption" fields       (caption :: B.Blocks) <- maybe mempty (pWithContents pBlocks) mbCaption@@ -345,13 +373,13 @@             (B.Table attr (B.Caption Nothing (B.toList caption)) colspecs thead tbodies tfoot)         _ -> B.figureWith (fromMaybe "" mbident, [], [])                           (B.Caption Nothing (B.toList caption)) body)-  ,("line", \_ fields ->+  ,("line", \_ _ fields ->       case ( M.lookup "start" fields               >> M.lookup "end" fields               >> M.lookup "angle" fields ) of         Nothing -> pure B.horizontalRule         _ -> pure mempty)-  ,("numbering", \_ fields -> do+  ,("numbering", \_ _ fields -> do       numStyle <- getField "numbering" fields       (nums :: V.Vector Integer) <- getField "numbers" fields       let toText v = fromMaybe "" $ fromVal v@@ -364,16 +392,17 @@                   Failure _ -> "?"               _ -> "?"       pure $ B.plain . B.text . mconcat . map toNum $ V.toList nums)-  ,("footnote.entry", \_ fields ->+  ,("footnote.entry", \_ _ fields ->       getField "body" fields >>= pWithContents pBlocks)-  ,("pad", \_ fields ->  -- ignore paddingy+  ,("pad", \_ _ fields ->  -- ignore paddingy       getField "body" fields >>= pWithContents pBlocks)   ]  inlineHandlers :: PandocMonad m =>-    M.Map Identifier (Maybe Text -> M.Map Identifier Val -> P m B.Inlines)+    M.Map Identifier (Maybe SourcePos -> Maybe Text ->+                      M.Map Identifier Val -> P m B.Inlines) inlineHandlers = M.fromList-  [("ref", \_ fields -> do+  [("ref", \_ _ fields -> do       VLabel target <- getField "target" fields       supplement' <- getField "supplement" fields       supplement <- case supplement' of@@ -384,17 +413,17 @@                            pure $ B.text ("[" <> target <> "]")                       _ -> pure mempty       pure $ B.linkWith ("", ["ref"], []) ("#" <> target) "" supplement)-  ,("linebreak", \_ _ -> pure B.linebreak)-  ,("text", \_ fields -> do+  ,("linebreak", \_ _ _ -> pure B.linebreak)+  ,("text", \_ _ fields -> do       body <- getField "body" fields       (mbweight :: Maybe Text) <- getField "weight" fields       case mbweight of         Just "bold" -> B.strong <$> pWithContents pInlines body         _ -> pWithContents pInlines body)-  ,("raw", \_ fields -> B.code . T.filter (/= '\r') <$> getField "text" fields)-  ,("footnote", \_ fields ->+  ,("raw", \_ _ fields -> B.code . T.filter (/= '\r') <$> getField "text" fields)+  ,("footnote", \_ _ fields ->       B.note <$> (getField "body" fields >>= pWithContents pBlocks))-  ,("cite", \_ fields -> do+  ,("cite", \_ _ fields -> do       VLabel key <- getField "key" fields       (form :: Text) <- getField "form" fields <|> pure "normal"       let citation =@@ -409,38 +438,38 @@                 B.citationHash = 0               }       pure $ B.cite [citation] (B.text $ "[" <> key <> "]"))-  ,("lower", \_ fields -> do+  ,("lower", \_ _ fields -> do       body <- getField "text" fields       walk (modString T.toLower) <$> pWithContents pInlines body)-  ,("upper", \_ fields -> do+  ,("upper", \_ _ fields -> do       body <- getField "text" fields       walk (modString T.toUpper) <$> pWithContents pInlines body)-  ,("emph", \_ fields -> do+  ,("emph", \_ _ fields -> do       body <- getField "body" fields       B.emph <$> pWithContents pInlines body)-  ,("strong", \_ fields -> do+  ,("strong", \_ _ fields -> do       body <- getField "body" fields       B.strong <$> pWithContents pInlines body)-  ,("sub", \_ fields -> do+  ,("sub", \_ _ fields -> do       body <- getField "body" fields       B.subscript <$> pWithContents pInlines body)-  ,("super", \_ fields -> do+  ,("super", \_ _ fields -> do       body <- getField "body" fields       B.superscript <$> pWithContents pInlines body)-  ,("strike", \_ fields -> do+  ,("strike", \_ _ fields -> do       body <- getField "body" fields       B.strikeout <$> pWithContents pInlines body)-  ,("smallcaps", \_ fields -> do+  ,("smallcaps", \_ _ fields -> do       body <- getField "body" fields       B.smallcaps <$> pWithContents pInlines body)-  ,("underline", \_ fields -> do+  ,("underline", \_ _ fields -> do       body <- getField "body" fields       B.underline <$> pWithContents pInlines body)-  ,("quote", \_ fields -> do+  ,("quote", \_ _ fields -> do       (getField "block" fields <|> pure False) >>= guard . not       body <- getInlineBody fields >>= pWithContents pInlines       pure $ B.doubleQuoted $ B.trimInlines body)-  ,("link", \_ fields -> do+  ,("link", \_ _ fields -> do       dest <- getField "dest" fields       src <- case dest of         VString t -> pure t@@ -448,7 +477,7 @@         VDict _ -> do           ignored "link to location, linking to #"           pure "#"-        _ -> fail $ "Expected string or label for dest"+        _ -> fail "Expected string or label for dest"       body <- getField "body" fields       description <-         if null body@@ -465,9 +494,15 @@                pWithContents                 (B.fromList . blocksToInlines . B.toList <$> pBlocks) body       pure $ B.link src "" description)-  ,("image", \_ fields -> do+  ,("image", \mbpos _ fields -> do       path <- getField "source" fields <|> getField "path" fields       alt <- (B.text <$> getField "alt" fields) `mplus` pure mempty+      let basedir = maybe "." (takeDirectory . sourceName) mbpos+      let isAbsolutePath p = Posix.isAbsolute p || Windows.isAbsolute p+      let path' = T.pack $+                  if isAbsolutePath path || basedir == "."+                     then path+                     else basedir Posix.</> path       (mbwidth :: Maybe Text) <-         fmap (renderLength False) <$> getField "width" fields       (mbheight :: Maybe Text) <-@@ -478,11 +513,11 @@               maybe [] (\x -> [("width", x)]) mbwidth                 ++ maybe [] (\x -> [("height", x)]) mbheight             )-      pure $ B.imageWith attr path "" alt)-  ,("box", \_ fields -> do+      pure $ B.imageWith attr path' "" alt)+  ,("box", \_ _ fields -> do       body <- getField "body" fields       B.spanWith ("", ["box"], []) <$> pWithContents pInlines body)-  ,("h", \_ fields -> do+  ,("h", \_ _ fields -> do       amount <- getField "amount" fields `mplus` pure (LExact 1 LEm)       let em = case amount of             LExact x LEm -> toRational x@@ -490,21 +525,21 @@               LExact x LPt -> toRational x / 12               _ -> 1 / 3 -- guess!       pure $ B.text $ getSpaceChars em)-  ,("place", \_ fields -> do+  ,("place", \_ _ fields -> do       ignored "parameters of place"       getField "body" fields >>= pWithContents pInlines)-  ,("align", \_ fields -> do+  ,("align", \_ _ fields -> do       alignment <- getField "alignment" fields       B.spanWith ("", [], [("align", repr alignment)])         <$> (getField "body" fields >>= pWithContents pInlines))-  ,("sys.version", \_ _ -> pure $ B.text "typst-hs")-  ,("math.equation", \_ fields -> do+  ,("sys.version", \_ _ _ -> pure $ B.text "typst-hs")+  ,("math.equation", \_ _ fields -> do       body <- getField "body" fields       display <- getField "block" fields       (if display then B.displayMath else B.math) . writeTeX <$> pMathMany body)-  ,("pad", \_ fields ->  -- ignore paddingy+  ,("pad", \_ _ fields ->  -- ignore paddingy       getField "body" fields >>= pWithContents pInlines)-  ,("block", \mbident fields ->+  ,("block", \_ mbident fields ->       maybe id (\ident -> B.spanWith (ident, [], [])) mbident         <$> (getField "body" fields >>= pWithContents pInlines))   ]
+ src/Text/Pandoc/Readers/XML.hs view
@@ -0,0 +1,540 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}++-- |+--   Module      : Text.Pandoc.Readers.XML+--   Copyright   : Copyright (C) 2025- Massimiliano Farinella and John MacFarlane+--   License     : GNU GPL, version 2 or above+--+--   Maintainer  : Massimiliano Farinella <massifrg@gmail.com>+--   Stability   : WIP+--   Portability : portable+--+-- Conversion of (Pandoc specific) xml to 'Pandoc' document.+module Text.Pandoc.Readers.XML (readXML) where++import Control.Monad (msum)+import Control.Monad.Except (throwError)+import Control.Monad.State.Strict (StateT (runStateT), modify)+import Data.Char (isSpace)+import Data.Default (Default (..))+import qualified Data.List as L+import qualified Data.Map as M+import Data.Maybe (catMaybes, fromMaybe, mapMaybe)+import qualified Data.Set as S (Set, fromList, member)+import Data.Text (Text)+import qualified Data.Text as T+import Data.Text.Lazy (fromStrict)+import Data.Version (Version, makeVersion)+import Text.Pandoc.Builder+import Text.Pandoc.Class.PandocMonad+import Text.Pandoc.Error (PandocError (..))+import Text.Pandoc.Options+import Text.Pandoc.Parsing (ToSources, toSources)+import Text.Pandoc.Sources (sourcesToText)+import Text.Pandoc.Version (pandocVersion)+import Text.Pandoc.XML (lookupEntity)+import Text.Pandoc.XML.Light+import Text.Pandoc.XMLFormat+import Text.Read (readMaybe)++-- TODO: use xmlPath state to give better context when an error occurs++type XMLReader m = StateT XMLReaderState m++data XMLReaderState = XMLReaderState+  { xmlApiVersion :: Version,+    xmlMeta :: Meta,+    xmlContent :: [Content],+    xmlPath :: [Text]+  }+  deriving (Show)++instance Default XMLReaderState where+  def =+    XMLReaderState+      { xmlApiVersion = pandocVersion,+        xmlMeta = mempty,+        xmlContent = [],+        xmlPath = ["root"]+      }++readXML :: (PandocMonad m, ToSources a) => ReaderOptions -> a -> m Pandoc+readXML _ inp = do+  let sources = toSources inp+  tree <-+    either (throwError . PandocXMLError "") return $+      parseXMLContents (fromStrict . sourcesToText $ sources)+  (bs, st') <- flip runStateT (def {xmlContent = tree}) $ mapM parseBlock tree+  let blockList = toList $ concatMany bs+  return $ Pandoc (xmlMeta st') blockList++concatMany :: [Many a] -> Many a+concatMany = Many . mconcat . map unMany++parseBlocks :: (PandocMonad m) => [Content] -> XMLReader m Blocks+parseBlocks contents = concatMany <$> mapM parseBlock contents++getBlocks :: (PandocMonad m) => Element -> XMLReader m Blocks+getBlocks e = parseBlocks (elContent e)++elementName :: Element -> Text+elementName e = qName $ elName e++attrValue :: Text -> Element -> Text+attrValue attr =+  fromMaybe "" . maybeAttrValue attr++maybeAttrValue :: Text -> Element -> Maybe Text+maybeAttrValue attr elt =+  lookupAttrBy (\x -> qName x == attr) (elAttribs elt)++parseBlock :: (PandocMonad m) => Content -> XMLReader m Blocks+parseBlock (Text (CData CDataRaw _ _)) = return mempty -- DOCTYPE+parseBlock (Text (CData _ s _)) =+  if T.all isSpace s+    then return mempty+    else do+      throwError $ PandocXMLError "" "non-space characters out of inline context"+parseBlock (CRef x) = do+  throwError $ PandocXMLError "" ("reference \"" <> x <> "\" out of inline context")+parseBlock (Elem e) = do+  let name = elementName e+   in case (name) of+        "Pandoc" -> parsePandoc+        "?xml" -> return mempty+        "blocks" -> getBlocks e+        "meta" ->+          let entry_els = childrenNamed tgNameMetaMapEntry e+           in do+                entries <- catMaybes <$> mapM parseMetaMapEntry entry_els+                mapM_ (uncurry addMeta) entries+                return mempty+        "Para" -> para <$> getInlines (elContent e)+        "Plain" -> do+          ils <- getInlines (elContent e)+          return $ singleton . Plain . toList $ ils+        "Header" -> (headerWith attr level) <$> getInlines (elContent e)+          where+            level = textToInt (attrValue atNameLevel e) 1+            attr = filterAttrAttributes [atNameLevel] $ attrFromElement e+        "HorizontalRule" -> return horizontalRule+        "BlockQuote" -> do+          contents <- getBlocks e+          return $ blockQuote contents+        "Div" -> do+          contents <- getBlocks e+          return $ divWith (attrFromElement e) contents+        "BulletList" -> do+          items <- getListItems e+          return $ bulletList items+        "OrderedList" -> do+          items <- getListItems e+          return $ orderedListWith (getListAttributes e) items+        "DefinitionList" -> do+          let items_contents = getContentsOfElements (isElementNamed tgNameDefListItem) (elContent e)+          items <- mapM parseDefinitionListItem items_contents+          return $ definitionList items+        "Figure" -> do+          let attr = attrFromElement e+              (maybe_caption_el, contents) = partitionFirstChildNamed "Caption" $ elContent e+          figure_caption <- case (maybe_caption_el) of+            Just (caption_el) -> parseCaption $ elContent caption_el+            Nothing -> pure emptyCaption+          blocks <- parseBlocks contents+          return $ figureWith attr figure_caption blocks+        "CodeBlock" -> do+          let attr = attrFromElement e+          return $ codeBlockWith attr $ strContentRecursive e+        "RawBlock" -> do+          let format = (attrValue atNameFormat e)+          return $ rawBlock format $ strContentRecursive e+        "LineBlock" -> do+          lins <- mapM getInlines (contentsOfChildren tgNameLineItem (elContent e))+          return $ lineBlock lins+        "Table" -> do+          -- TODO: check unexpected items+          let attr = attrFromElement e+              (maybe_caption_el, after_caption) = partitionFirstChildNamed "Caption" $ elContent e+              children = elementsWithNames (S.fromList [tgNameColspecs, "TableHead", "TableBody", "TableFoot"]) after_caption+              is_element tag el = tag == elementName el+          colspecs <- getColspecs $ L.find (is_element tgNameColspecs) children+          tbs <- getTableBodies $ filter (is_element "TableBody") children+          th <- getTableHead $ L.find (is_element "TableHead") children+          tf <- getTableFoot $ L.find (is_element "TableFoot") children+          capt <- parseMaybeCaptionElement maybe_caption_el+          case colspecs of+            Nothing -> return mempty+            Just cs -> return $ fromList [Table attr capt cs th tbs tf]+        _ -> do+          throwError $ PandocXMLError "" ("unexpected element \"" <> name <> "\" in blocks context")+  where+    parsePandoc = do+      let version = maybeAttrValue atNameApiVersion e+          apiversion = case (version) of+            Just (v) -> makeVersion $ map (read . T.unpack) $ T.splitOn "," v+            Nothing -> pandocVersion+       in modify $ \st -> st {xmlApiVersion = apiversion}+      getBlocks e++getListItems :: (PandocMonad m) => Element -> XMLReader m [Blocks]+getListItems e =+  let items_els = childrenNamed tgNameListItem e+   in do+        mapM getBlocks items_els++getContentsOfElements :: (Content -> Bool) -> [Content] -> [[Content]]+getContentsOfElements filter_element contents = mapMaybe element_contents $ filter filter_element contents+  where+    element_contents :: Content -> Maybe [Content]+    element_contents c = case (c) of+      Elem e -> Just (elContent e)+      _ -> Nothing++strContentRecursive :: Element -> Text+strContentRecursive =+  strContent+    . (\e' -> e' {elContent = map elementToStr $ elContent e'})++elementToStr :: Content -> Content+elementToStr (Elem e') = Text $ CData CDataText (strContentRecursive e') Nothing+elementToStr x = x++textToInt :: Text -> Int -> Int+textToInt t deflt =+  let safe_to_int :: Text -> Maybe Int+      safe_to_int s = readMaybe $ T.unpack s+   in case (safe_to_int t) of+        Nothing -> deflt+        Just (n) -> n++parseInline :: (PandocMonad m) => Content -> XMLReader m Inlines+parseInline (Text (CData _ s _)) =+  return $ text s+parseInline (CRef ref) =+  return $+    maybe (text $ T.toUpper ref) text $+      lookupEntity ref+parseInline (Elem e) =+  let name = elementName e+   in case (name) of+        "Space" ->+          let count = textToInt (attrValue atNameSpaceCount e) 1+           in return $ fromList $ replicate count Space+        "Str" -> return $ fromList [Str $ attrValue atNameStrContent e]+        "Emph" -> innerInlines emph+        "Strong" -> innerInlines strong+        "Strikeout" -> innerInlines strikeout+        "Subscript" -> innerInlines subscript+        "Superscript" -> innerInlines superscript+        "Underline" -> innerInlines underline+        "SoftBreak" -> return softbreak+        "LineBreak" -> return linebreak+        "SmallCaps" -> innerInlines smallcaps+        "Quoted" -> case (attrValue atNameQuoteType e) of+          "SingleQuote" -> innerInlines singleQuoted+          _ -> innerInlines doubleQuoted+        "Math" -> case (attrValue atNameMathType e) of+          "DisplayMath" -> pure $ displayMath $ strContentRecursive e+          _ -> pure $ math $ strContentRecursive e+        "Span" -> innerInlines $ spanWith (attrFromElement e)+        "Code" -> do+          let attr = attrFromElement e+          return $ codeWith attr $ strContentRecursive e+        "Link" -> innerInlines $ linkWith attr url title+          where+            url = attrValue atNameLinkUrl e+            title = attrValue atNameTitle e+            attr = filterAttrAttributes [atNameLinkUrl, atNameTitle] $ attrFromElement e+        "Image" -> innerInlines $ imageWith attr url title+          where+            url = attrValue atNameImageUrl e+            title = attrValue atNameTitle e+            attr = filterAttrAttributes [atNameImageUrl, atNameTitle] $ attrFromElement e+        "RawInline" -> do+          let format = (attrValue atNameFormat e)+          return $ rawInline format $ strContentRecursive e+        "Note" -> do+          contents <- getBlocks e+          return $ note contents+        "Cite" ->+          let (maybe_citations_el, contents) = partitionFirstChildNamed tgNameCitations $ elContent e+           in case (maybe_citations_el) of+                Just citations_el -> do+                  citations <- parseCitations $ elContent citations_el+                  (innerInlines' contents) $ cite citations+                Nothing -> getInlines contents+        _ -> do+          throwError $ PandocXMLError "" ("unexpected element \"" <> name <> "\" in inline context")+  where+    innerInlines' contents f =+      f . concatMany+        <$> mapM parseInline contents+    innerInlines f = innerInlines' (elContent e) f++getInlines :: (PandocMonad m) => [Content] -> XMLReader m Inlines+getInlines contents = concatMany <$> mapM parseInline contents++getListAttributes :: Element -> ListAttributes+getListAttributes e = (start, style, delim)+  where+    start = textToInt (attrValue atNameStart e) 1+    style = case (attrValue atNameNumberStyle e) of+      "Example" -> Example+      "Decimal" -> Decimal+      "LowerRoman" -> LowerRoman+      "UpperRoman" -> UpperRoman+      "LowerAlpha" -> LowerAlpha+      "UpperAlpha" -> UpperAlpha+      _ -> DefaultStyle+    delim = case (attrValue atNameNumberDelim e) of+      "Period" -> Period+      "OneParen" -> OneParen+      "TwoParens" -> TwoParens+      _ -> DefaultDelim++contentsOfChildren :: Text -> [Content] -> [[Content]]+contentsOfChildren tag contents = mapMaybe childrenElementWithTag contents+  where+    childrenElementWithTag :: Content -> Maybe [Content]+    childrenElementWithTag c = case (c) of+      (Elem e) -> if tag == elementName e then Just (elContent e) else Nothing+      _ -> Nothing++alignmentFromText :: Text -> Alignment+alignmentFromText t = case t of+  "AlignLeft" -> AlignLeft+  "AlignRight" -> AlignRight+  "AlignCenter" -> AlignCenter+  _ -> AlignDefault++getColWidth :: Text -> ColWidth+getColWidth txt = case reads (T.unpack txt) of+  [(value, "")] -> if value == 0.0 then ColWidthDefault else ColWidth value+  _ -> ColWidthDefault++getColspecs :: (PandocMonad m) => Maybe Element -> XMLReader m (Maybe [ColSpec])+getColspecs Nothing = pure Nothing+getColspecs (Just cs) = do+  return $ Just $ map elementToColSpec (childrenNamed "ColSpec" cs)+  where+    elementToColSpec e = (alignmentFromText $ attrValue atNameAlignment e, getColWidth $ attrValue atNameColWidth e)++getTableBody :: (PandocMonad m) => Element -> XMLReader m (Maybe TableBody)+getTableBody body_el = do+  let attr = filterAttrAttributes [atNameRowHeadColumns] $ attrFromElement body_el+      bh = childrenNamed tgNameBodyHeader body_el+      bb = childrenNamed tgNameBodyBody body_el+      headcols = textToInt (attrValue atNameRowHeadColumns body_el) 0+  hrows <- mconcat <$> mapM getRows bh+  brows <- mconcat <$> mapM getRows bb+  return $ Just $ TableBody attr (RowHeadColumns headcols) hrows brows++getTableBodies :: (PandocMonad m) => [Element] -> XMLReader m [TableBody]+getTableBodies body_elements = do+  catMaybes <$> mapM getTableBody body_elements++getTableHead :: (PandocMonad m) => Maybe Element -> XMLReader m TableHead+getTableHead maybe_e = case maybe_e of+  Just e -> do+    let attr = attrFromElement e+    rows <- getRows e+    return $ TableHead attr rows+  Nothing -> return $ TableHead nullAttr []++getTableFoot :: (PandocMonad m) => Maybe Element -> XMLReader m TableFoot+getTableFoot maybe_e = case maybe_e of+  Just e -> do+    let attr = attrFromElement e+    rows <- getRows e+    return $ TableFoot attr rows+  Nothing -> return $ TableFoot nullAttr []++getCell :: (PandocMonad m) => Element -> XMLReader m Cell+getCell c = do+  let alignment = alignmentFromText $ attrValue atNameAlignment c+      rowspan = RowSpan $ textToInt (attrValue atNameRowspan c) 1+      colspan = ColSpan $ textToInt (attrValue atNameColspan c) 1+      attr = filterAttrAttributes [atNameAlignment, atNameRowspan, atNameColspan] $ attrFromElement c+  blocks <- getBlocks c+  return $ Cell attr alignment rowspan colspan (toList blocks)++getRows :: (PandocMonad m) => Element -> XMLReader m [Row]+getRows e = mapM getRow $ childrenNamed "Row" e+  where+    getRow r = do+      cells <- mapM getCell (childrenNamed "Cell" r)+      return $ Row (attrFromElement r) cells++parseCitations :: (PandocMonad m) => [Content] -> XMLReader m [Citation]+parseCitations contents = do+  maybecitations <- mapM getCitation contents+  return $ catMaybes maybecitations+  where+    getCitation :: (PandocMonad m) => Content -> XMLReader m (Maybe Citation)+    getCitation content = case (content) of+      (Elem e) ->+        if qName (elName e) == "Citation"+          then do+            p <- inlinesOfChildrenNamed tgNameCitationPrefix e+            s <- inlinesOfChildrenNamed tgNameCitationSuffix e+            return $+              Just+                ( Citation+                    { citationId = attrValue "id" e,+                      citationPrefix = toList p,+                      citationSuffix = toList s,+                      citationMode = case (attrValue atNameCitationMode e) of+                        "AuthorInText" -> AuthorInText+                        "SuppressAuthor" -> SuppressAuthor+                        _ -> NormalCitation,+                      citationNoteNum = textToInt (attrValue atNameCitationNoteNum e) 0,+                      citationHash = textToInt (attrValue atNameCitationHash e) 0+                    }+                )+          else do+            return Nothing+      _ -> do+        return Nothing+      where+        inlinesOfChildrenNamed tag e = getInlines $ concatMap (\e' -> elContent e') (childrenNamed tag e)++parseMaybeCaptionElement :: (PandocMonad m) => Maybe Element -> XMLReader m Caption+parseMaybeCaptionElement Nothing = pure emptyCaption+parseMaybeCaptionElement (Just e) = parseCaption $ elContent e++parseCaption :: (PandocMonad m) => [Content] -> XMLReader m Caption+parseCaption contents =+  let (maybe_shortcaption_el, caption_contents) = partitionFirstChildNamed tgNameShortCaption contents+   in do+        blocks <- parseBlocks caption_contents+        case (maybe_shortcaption_el) of+          Just shortcaption_el -> do+            short_caption <- getInlines (elContent shortcaption_el)+            return $ caption (Just $ toList short_caption) blocks+          Nothing -> return $ caption Nothing blocks++parseDefinitionListItem :: (PandocMonad m) => [Content] -> XMLReader m (Inlines, [Blocks])+parseDefinitionListItem contents = do+  let term_contents = getContentsOfElements (isElementNamed tgNameDefListTerm) contents+      defs_elements = elementContents $ filter (isElementNamed tgNameDefListDef) contents+  term_inlines <- getInlines (concat term_contents)+  defs <- mapM getBlocks defs_elements+  return (term_inlines, defs)++elementContents :: [Content] -> [Element]+elementContents contents = mapMaybe toElement contents+  where+    toElement :: Content -> Maybe Element+    toElement (Elem e) = Just e+    toElement _ = Nothing++isElementNamed :: Text -> Content -> Bool+isElementNamed t c = case (c) of+  Elem e -> t == elementName e+  _ -> False++childrenNamed :: Text -> Element -> [Element]+childrenNamed tag e = elementContents $ filter (isElementNamed tag) (elContent e)++elementsWithNames :: S.Set Text -> [Content] -> [Element]+elementsWithNames tags contents = mapMaybe isElementWithNameInSet contents+  where+    isElementWithNameInSet c = case (c) of+      Elem el ->+        if (elementName el) `S.member` tags+          then Just el+          else Nothing+      _ -> Nothing++partitionFirstChildNamed :: Text -> [Content] -> (Maybe Element, [Content])+partitionFirstChildNamed tag contents = case (contents) of+  (Text (CData _ s _) : rest) ->+    if T.all isSpace s+      then partitionFirstChildNamed tag rest+      else (Nothing, contents)+  (Elem e : rest) ->+    if tag == elementName e+      then (Just e, rest)+      else (Nothing, contents)+  _ -> (Nothing, contents)++type PandocAttr = (Text, [Text], [(Text, Text)])++filterAttributes :: S.Set Text -> [(Text, Text)] -> [(Text, Text)]+filterAttributes to_be_removed a = filter keep_attr a+  where+    keep_attr (k, _) = not (k `S.member` to_be_removed)++filterAttrAttributes :: [Text] -> PandocAttr -> PandocAttr+filterAttrAttributes to_be_removed (idn, classes, a) = (idn, classes, filtered)+  where+    filtered = filterAttributes (S.fromList to_be_removed) a++attrFromElement :: Element -> PandocAttr+attrFromElement e = filterAttrAttributes ["id", "class"] (idn, classes, attributes)+  where+    idn = attrValue "id" e+    classes = T.words $ attrValue "class" e+    attributes = map (\a -> (qName $ attrKey a, attrVal a)) $ elAttribs e++addMeta :: (PandocMonad m) => (ToMetaValue a) => Text -> a -> XMLReader m ()+addMeta field val = modify (setMeta field val)++instance HasMeta XMLReaderState where+  setMeta field v s = s {xmlMeta = setMeta field v (xmlMeta s)}++  deleteMeta field s = s {xmlMeta = deleteMeta field (xmlMeta s)}++parseMetaMapEntry :: (PandocMonad m) => Element -> XMLReader m (Maybe (Text, MetaValue))+parseMetaMapEntry e =+  let key = attrValue atNameMetaMapEntryKey e+   in case (key) of+        "" -> pure Nothing+        k -> do+          maybe_value <- parseMetaMapEntryContents $ elContent e+          case (maybe_value) of+            Nothing -> return Nothing+            Just v -> return $ Just (k, v)++parseMetaMapEntryContents :: (PandocMonad m) => [Content] -> XMLReader m (Maybe MetaValue)+parseMetaMapEntryContents cs = msum <$> mapM parseMeta cs++parseMeta :: (PandocMonad m) => Content -> XMLReader m (Maybe MetaValue)+parseMeta (Text (CData CDataRaw _ _)) = return Nothing+parseMeta (Text (CData _ s _)) =+  if T.all isSpace s+    then return Nothing+    else do+      throwError $ PandocXMLError "" "non-space characters out of inline context in metadata"+parseMeta (CRef x) =+  throwError $ PandocXMLError "" ("reference \"" <> x <> "\" out of inline context")+parseMeta (Elem e) = do+  let name = elementName e+   in case (name) of+        "MetaBool" -> case (attrValue atNameMetaBoolValue e) of+          "true" -> return $ Just $ MetaBool True+          _ -> return $ Just $ MetaBool False+        "MetaString" -> pure Nothing+        "MetaInlines" -> do+          inlines <- getInlines (elContent e)+          return $ Just $ MetaInlines $ toList inlines+        "MetaBlocks" -> do+          blocks <- getBlocks e+          return $ Just $ MetaBlocks $ toList blocks+        "MetaList" -> do+          maybe_items <- mapM parseMeta $ elContent e+          let items = catMaybes maybe_items+           in -- TODO: report empty MetaList?+              return $ Just $ MetaList items+        "MetaMap" ->+          let entry_els = childrenNamed tgNameMetaMapEntry e+           in do+                entries <- catMaybes <$> mapM parseMetaMapEntry entry_els+                if null entries+                  then+                    -- TODO: report empty MetaMap+                    return Nothing+                  else return $ Just $ MetaMap $ M.fromList entries+        _ -> do+          throwError $ PandocXMLError "" ("unexpected element \"" <> name <> "\" in metadata")
src/Text/Pandoc/SelfContained.hs view
@@ -43,7 +43,6 @@ import Data.Maybe (isNothing) import qualified Data.Map as M import Control.Monad.State--- import Debug.Trace  isOk :: Char -> Bool isOk c = isAscii c && isAlphaNum c@@ -420,17 +419,22 @@                   return res                else return raw'       return $ Fetched (mime, result)-   handler e = case e of-                 PandocResourceNotFound r -> do-                   report $ CouldNotFetchResource r ""-                   return $ CouldNotFetch e-                 PandocHttpError u er -> do-                   report $ CouldNotFetchResource u (tshow er)-                   return $ CouldNotFetch e-                 _ -> throwError e---+   handler e+      -- If fetch failed and we have a fragment and/or query,+      -- try the fetch again without these, since the resource+      -- may be local (see #1477, #11021)+     | T.any (\c -> c == '?' || c == '#') src && not (isURI src)+       = getData mimetype (removeQueryAndFragment src)+     | otherwise+       = case e of+          PandocResourceNotFound r -> do+            report $ CouldNotFetchResource r ""+            return $ CouldNotFetch e+          PandocHttpError u er -> do+            report $ CouldNotFetchResource u (tshow er)+            return $ CouldNotFetch e+          _ -> throwError e+   removeQueryAndFragment = T.takeWhile (\c -> c /= '#' && c /= '?')  -- | Convert HTML into self-contained HTML, incorporating images, -- scripts, and CSS using data: URIs.
src/Text/Pandoc/Templates.hs view
@@ -102,6 +102,7 @@        "native"  -> return ""        "csljson" -> return ""        "json"    -> return ""+       "xml"     -> return ""        "fb2"     -> return ""        "pptx"    -> return ""        "ipynb"   -> return ""
src/Text/Pandoc/Translations.hs view
@@ -20,7 +20,8 @@                          ) where import Text.Pandoc.Translations.Types-import Text.Pandoc.Class (PandocMonad(..), CommonState(..), toTextM, report)+import Text.Pandoc.Class (PandocMonad(..), toTextM, report)+import Text.Pandoc.Class.CommonState (CommonState(..)) import Text.Pandoc.Data (readDataFile) import Text.Pandoc.Error (PandocError(..)) import Text.Pandoc.Logging (LogMessage(..))
src/Text/Pandoc/Writers.hs view
@@ -76,6 +76,7 @@     , writeTexinfo     , writeTextile     , writeTypst+    , writeXML     , writeXWiki     , writeZimWiki     , getWriter@@ -128,6 +129,7 @@ import Text.Pandoc.Writers.Texinfo import Text.Pandoc.Writers.Textile import Text.Pandoc.Writers.Typst+import Text.Pandoc.Writers.XML import Text.Pandoc.Writers.XWiki import Text.Pandoc.Writers.ZimWiki @@ -203,6 +205,7 @@   ,("chunkedhtml"  , ByteStringWriter writeChunkedHTML)   ,("djot"         , TextWriter writeDjot)   ,("ansi"         , TextWriter writeANSI)+  ,("xml"          , TextWriter writeXML)   ]  -- | Retrieve writer, extensions based on formatSpec (format+extensions).
src/Text/Pandoc/Writers/ANSI.hs view
@@ -1,7 +1,8 @@ {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Writers.ANSI-   Copyright   : Copyright (C) 2024 Evan Silberman+   Copyright   : © 2024 Evan Silberman+                 © 2025 Pandoc contributors    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -30,6 +31,7 @@ import qualified Data.Text as T import Data.Text.Lazy (toStrict) import qualified Text.DocLayout as D+import qualified Text.Pandoc.Highlighting as HL  hr :: D.HasChars a => D.Doc a hr = rule 20@@ -76,26 +78,39 @@   metadata <- metaToContext opts                  (blockListToANSI opts)                  (inlineListToANSI opts) meta-  width <- gets stColumns-  let title = titleBlock width metadata+  let colwidth = if writerWrapText opts == WrapAuto+                    then Just $ writerColumns opts+                    else Nothing+  let title = titleBlock colwidth metadata   let blocks' = makeSections (writerNumberSections opts) Nothing blocks   body <- blockListToANSI opts blocks'   notes <- gets $ reverse . stNotes   let notemark x = D.literal (tshow (x :: Int) <> ".") <+> D.space   let marks = map notemark [1..length notes]   let hangWidth = foldr (max . D.offset) 0 marks-  let notepretty | not (null notes) = D.cblock width hr $+$ hangMarks hangWidth marks notes-                 | otherwise = D.empty+  let notepretty+       | not (null notes) =+          (case colwidth of+            Nothing -> hr+            Just w  -> D.cblock w hr)+          $+$ hangMarks hangWidth marks notes+       | otherwise = D.empty   let main = body $+$ notepretty   let context = defField "body" main               $ defField "titleblock" title metadata   return $     case writerTemplate opts of-         Nothing  -> toStrict $ D.renderANSI (Just width) main-         Just tpl -> toStrict $ D.renderANSI (Just width) $ renderTemplate tpl context+         Nothing  -> toStrict $ D.renderANSI colwidth main+         Just tpl -> toStrict $ D.renderANSI colwidth+                              $ renderTemplate tpl context -titleBlock :: Int -> Context Text -> D.Doc Text-titleBlock width meta = if null most then D.empty else D.cblock width $ most $+$ hr+titleBlock :: Maybe Int -> Context Text -> D.Doc Text+titleBlock width meta =+  if null most+     then D.empty+     else (case width of+             Just w -> D.cblock w+             Nothing -> id) $ most $+$ hr   where     title = D.bold (fromMaybe D.empty $ getField "title" meta)     subtitle = fromMaybe D.empty $ getField "subtitle" meta@@ -155,15 +170,20 @@ -- Doc Text. blockToANSI opts (CodeBlock attr str) = do   table <- gets stInTable-  inner <- case (table, writerHighlightStyle opts) of-    (_, Nothing) -> return $ defaultStyle str+  let highlightWithStyle s = do+        let fmt o = formatANSI o s+            result = highlight (writerSyntaxMap opts) fmt attr str+        return $ case result of+          Left _ -> defaultStyle str+          Right f -> D.literal f+  inner <- case (table, writerHighlightMethod opts) of+    (_, NoHighlighting) -> return $ defaultStyle str     (True, _) -> return $ defaultStyle str-    (False, Just s) -> do-      let fmt o = formatANSI o s-          result = highlight (writerSyntaxMap opts) fmt attr str-      return $ case result of-        Left _ -> defaultStyle str-        Right f -> D.literal f+    (False, Skylighting s) -> highlightWithStyle s+    (False, DefaultHighlighting) -> highlightWithStyle HL.defaultStyle+    (False, IdiomaticHighlighting) -> do+      report $ CouldNotHighlight "no idiomatic highlighting in ANSI"+      return $ defaultStyle str   return $ nest table inner   where defaultStyle = (D.fg D.red) . D.literal         nest False = D.nest 4
src/Text/Pandoc/Writers/AsciiDoc.hs view
@@ -416,7 +416,7 @@   let blocksWithTasks = if isLegacy                           then blocks                           else (taskListItemToAsciiDoc blocks)-  contents <- foldM (addBlock opts) empty blocksWithTasks+  contents <- snd <$> foldM (addBlock opts) (False, empty) blocksWithTasks   modify $ \s -> s{ bulletListLevel = lev }   let marker = text (replicate (lev + 1) '*')   return $ marker <> text " " <> listBegin blocksWithTasks <>@@ -433,18 +433,24 @@     listExt = extensionsFromList [Ext_task_lists]  addBlock :: PandocMonad m-         => WriterOptions -> Doc Text -> Block -> ADW m (Doc Text)-addBlock opts d b = do+         => WriterOptions -> (Bool, Doc Text) -> Block -> ADW m (Bool, Doc Text)+addBlock opts (containsContinuation, d) b = do   x <- chomp <$> blockToAsciiDoc opts b   return $     case b of-        BulletList{} -> d <> cr <> x-        OrderedList{} -> d <> cr <> x-        Para (Math DisplayMath _:_) -> d <> cr <> x-        Plain (Math DisplayMath _:_) -> d <> cr <> x-        Para{} | isEmpty d -> x-        Plain{} | isEmpty d -> x-        _ -> d <> cr <> text "+" <> cr <> x+        BulletList{}+          | containsContinuation -> (False, d <> blankline <> x)  -- see #11006+          | otherwise -> (False, d <> cr <> x)+        OrderedList (start, sty, _) _+          | containsContinuation+          , start == 1+          , sty == DefaultStyle -> (False, d <> blankline <> x)  -- see #11006+          | otherwise -> (False, d <> cr <> x)+        Para (Math DisplayMath _:_) -> (containsContinuation, d <> cr <> x)+        Plain (Math DisplayMath _:_) -> (containsContinuation, d <> cr <> x)+        Para{} | isEmpty d -> (containsContinuation, x)+        Plain{} | isEmpty d -> (containsContinuation, x)+        _ -> (True, d <> cr <> text "+" <> cr <> x)  listBegin :: [Block] -> Doc Text listBegin blocks =@@ -464,7 +470,7 @@ orderedListItemToAsciiDoc opts blocks = do   lev <- gets orderedListLevel   modify $ \s -> s{ orderedListLevel = lev + 1 }-  contents <- foldM (addBlock opts) empty blocks+  contents <- snd <$> foldM (addBlock opts) (False, empty) blocks   modify $ \s -> s{ orderedListLevel = lev }   let marker = text (replicate (lev + 1) '.')   return $ marker <> text " " <> listBegin blocks <> contents <> cr
src/Text/Pandoc/Writers/ConTeXt.hs view
@@ -4,7 +4,7 @@ {-# LANGUAGE ViewPatterns        #-} {- |    Module      : Text.Pandoc.Writers.ConTeXt-   Copyright   : Copyright (C) 2007-2024 John MacFarlane+   Copyright   : Copyright (C) 2007-2025 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -20,7 +20,7 @@ import Data.Char (ord, isDigit) import Data.List (intersperse) import Data.List.NonEmpty (NonEmpty ((:|)))-import Data.Maybe (isNothing, mapMaybe, catMaybes)+import Data.Maybe (mapMaybe, catMaybes) import Data.Monoid (Any (Any, getAny)) import Data.Text (Text) import qualified Data.Text as T@@ -131,10 +131,10 @@                         _                     -> id)                 $ defField "emphasis-commands"                     (mconcat $ Map.elems (stEmphasisCommands st))-                $ (case writerHighlightStyle options of-                        Just sty | stHighlighting st ->-                          defField "highlighting-commands" (styleToConTeXt sty)-                        _ -> id)+                $ (case writerHighlightMethod options of+                      Skylighting sty | stHighlighting st ->+                        defField "highlighting-commands" (styleToConTeXt sty)+                      _ -> id)                 $ (case T.toLower $ lookupMetaString "pdfa" meta of                         "true" -> resetField "pdfa" (T.pack "1b:2005")                         _                     -> id) metadata@@ -233,9 +233,9 @@             return (literal h)   -- blankline because \stoptyping can't have anything after it, inc. '}'   ($$ blankline) . flush <$>-    if null classes || isNothing (writerHighlightStyle opts)-    then pure unhighlighted-    else highlighted+    case writerHighlightMethod opts of+      Skylighting _ | not (null classes) -> pure unhighlighted+      _ -> highlighted blockToConTeXt b@(RawBlock f str)   | f == Format "context" || f == Format "tex" = return $ literal str <> blankline   | otherwise = empty <$ report (BlockNotRendered b)@@ -625,9 +625,9 @@           Right h -> do             modify (\st -> st{ stHighlighting = True })             return (text (T.unpack h))-  if isNothing (writerHighlightStyle opts) || null classes-    then rawCode-    else highlightCode+  case writerHighlightMethod opts of+    Skylighting _ | not (null classes) -> highlightCode+    _ -> rawCode inlineToConTeXt (Quoted SingleQuote lst) = do   contents <- inlineListToConTeXt lst   return $ "\\quote" <> braces contents
src/Text/Pandoc/Writers/Djot.hs view
@@ -100,7 +100,8 @@ blockToDjot (Header lev attr ils) =   fmap (D.addAttr (toDjotAttr attr)) . D.heading lev <$> inlinesToDjot ils blockToDjot HorizontalRule = pure D.thematicBreak-blockToDjot (Div (ident,"section":cls,kvs) bls@(Header _ _ ils : _)) = do+blockToDjot (Div (ident,"section":cls,kvs)+              (Header lev (_,hcls,hkvs) ils : bls)) = do   ilsBs <- D.inlinesToByteString <$> inlinesToDjot ils   let ident' = toIdentifier ilsBs   let label = D.normalizeLabel ilsBs@@ -112,8 +113,10 @@   fmap     (D.addAttr (toDjotAttr (if autoid then "" else ident,                          filter (/= "section") cls,-                         filter (\(k,_) -> k /= "wrapper") kvs))) . D.section-     <$> blocksToDjot bls+                         filter (\(k,_) -> k /= "wrapper") kvs) <>+                toDjotAttr ("", [c | c <- hcls, c `notElem` cls], hkvs)))+         . D.section+     <$> blocksToDjot (Header lev mempty ils : bls) blockToDjot (Div attr@(ident,cls,kvs) bls)   | Just "1" <- lookup "wrapper" kvs     = fmap (D.addAttr
src/Text/Pandoc/Writers/DocBook.hs view
@@ -265,7 +265,7 @@   let attribs = [("spacing", "compact") | isTightList lst]   inTags True "itemizedlist" attribs <$> listItemsToDocBook opts lst blockToDocBook _ (OrderedList _ []) = return empty-blockToDocBook opts (OrderedList (start, numstyle, _) (first:rest)) = do+blockToDocBook opts (OrderedList (start, numstyle, _) items) = do   let numeration = case numstyle of                        DefaultStyle -> []                        Decimal      -> [("numeration", "arabic")]@@ -274,17 +274,10 @@                        LowerAlpha   -> [("numeration", "loweralpha")]                        UpperRoman   -> [("numeration", "upperroman")]                        LowerRoman   -> [("numeration", "lowerroman")]-      spacing    = [("spacing", "compact") | isTightList (first:rest)]-      attribs    = numeration <> spacing-  items <- if start == 1-              then listItemsToDocBook opts (first:rest)-              else do-                first' <- blocksToDocBook opts (map plainToPara first)-                rest' <- listItemsToDocBook opts rest-                return $-                  inTags True "listitem" [("override",tshow start)] first' $$-                   rest'-  return $ inTags True "orderedlist" attribs items+      spacing    = [("spacing", "compact") | isTightList items]+      startnum   = [("startingnumber", tshow start) | start /= 1]+      attribs    = numeration <> spacing <> startnum+  inTags True "orderedlist" attribs <$> listItemsToDocBook opts items blockToDocBook opts (DefinitionList lst) = do   let attribs = [("spacing", "compact") | isTightList $ concatMap snd lst]   inTags True "variablelist" attribs <$> deflistItemsToDocBook opts lst
src/Text/Pandoc/Writers/Docx.hs view
@@ -6,7 +6,7 @@ {-# LANGUAGE OverloadedStrings   #-} {- |    Module      : Text.Pandoc.Writers.Docx-   Copyright   : Copyright (C) 2012-2024 John MacFarlane+   Copyright   : Copyright (C) 2012-2025 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -48,6 +48,7 @@ import qualified Text.Pandoc.UTF8 as UTF8 import Text.Pandoc.Definition import Text.Pandoc.Error+import Text.Pandoc.Highlighting (defaultStyle) import Text.Pandoc.MIME (getMimeTypeDef) import Text.Pandoc.Options import Text.Pandoc.Readers.Docx.Parse (extractTarget)@@ -350,7 +351,11 @@    let newstyles = map newParaPropToOpenXml newDynamicParaProps ++                   map newTextPropToOpenXml newDynamicTextProps ++-                  maybe [] (styleToOpenXml styleMaps) (writerHighlightStyle opts)+                  (case writerHighlightMethod opts of+                     Skylighting sty -> styleToOpenXml styleMaps sty+                     DefaultHighlighting -> styleToOpenXml styleMaps+                                              defaultStyle+                     _ -> [])   let styledoc' = styledoc{ elContent = elContent styledoc ++                                            map Elem newstyles }   let styleEntry = toEntry stylepath epochtime $ renderXml styledoc'
src/Text/Pandoc/Writers/Docx/OpenXML.hs view
@@ -9,7 +9,7 @@ {-# LANGUAGE TypeApplications    #-} {- |    Module      : Text.Pandoc.Writers.Docx-   Copyright   : Copyright (C) 2012-2024 John MacFarlane+   Copyright   : Copyright (C) 2012-2025 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -20,7 +20,7 @@ -} module Text.Pandoc.Writers.Docx.OpenXML ( writeOpenXML, maxListLevel ) where -import Control.Monad (when, unless)+import Control.Monad ((>=>), when, unless) import Control.Applicative ((<|>)) import Control.Monad.Except (catchError) import Crypto.Hash (hashWith, SHA1(SHA1))@@ -30,7 +30,7 @@ import Data.Ord (comparing) import Data.String (fromString) import qualified Data.Map as M-import Data.Maybe (fromMaybe, isNothing, maybeToList, isJust)+import Data.Maybe (fromMaybe, maybeToList, isJust) import Control.Monad.State ( gets, modify, MonadTrans(lift) ) import Control.Monad.Reader ( asks, MonadReader(local) ) import qualified Data.Set as Set@@ -220,6 +220,15 @@       ]) -- w:sdtContent     ]] -- w:sdt +-- | Separator element between sections+sectionSeparator :: PandocMonad m => WS m (Maybe Content)+sectionSeparator = do+  asks envSectPr >>= \case+    Just sectPrElem -> pure $+      Just $ Elem (mknode "w:p" [] (mknode "w:pPr" [] [sectPrElem]))+    Nothing -> pure+      Nothing+ -- | Convert Pandoc document to rendered document contents plus two lists of -- OpenXML elements (footnotes and comments). writeOpenXML :: PandocMonad m@@ -317,7 +326,17 @@  -- | Convert a list of Pandoc blocks to OpenXML. blocksToOpenXML :: (PandocMonad m) => WriterOptions -> [Block] -> WS m [Content]-blocksToOpenXML opts = fmap concat . mapM (blockToOpenXML opts) . separateTables . filter (not . isForeignRawBlock)+blocksToOpenXML opts =+  fmap concat . mapM (blockToOpenXML opts)+  . separateTables . filter (not . isForeignRawBlock)+  >=>+  \case+    a@(x:xs) -> do+      sep <- sectionSeparator+      if Just x == sep+        then pure xs+        else pure a+    [] -> pure []  isForeignRawBlock :: Block -> Bool isForeignRawBlock (RawBlock format _) = format /= "openxml"@@ -395,13 +414,9 @@                 Nothing -> return []            else return []   contents <- (number ++) <$> inlinesToOpenXML opts lst-  sectpr <- asks envSectPr-  let addSectionBreak-       | isSection-       , Just sectPrElem <- sectpr-        = (Elem (mknode "w:p" []-                   (mknode "w:pPr" [] [sectPrElem])) :)-       | otherwise = id+  addSectionBreak <- sectionSeparator >>= \case+    Just sep | isSection -> pure (sep:)+    _  -> pure id   addSectionBreak <$>     if T.null ident        then return [Elem $ mknode "w:p" [] (map Elem paraProps ++ contents)]@@ -874,14 +889,14 @@             maybeToList (lookup toktype tokTypesMap)             , mknode "w:t" [("xml:space","preserve")] tok ]   withTextPropM (rStyleM "Verbatim Char")-    $ if isNothing (writerHighlightStyle opts)-          then unhighlighted-          else case highlight (writerSyntaxMap opts)-                      formatOpenXML attrs str of-                    Right h  -> return (map Elem h)-                    Left msg -> do-                      unless (T.null msg) $ report $ CouldNotHighlight msg-                      unhighlighted+    $ case writerHighlightMethod opts of+        Skylighting _ ->+          case highlight (writerSyntaxMap opts) formatOpenXML attrs str of+            Right h  -> return (map Elem h)+            Left msg -> do+              unless (T.null msg) $ report $ CouldNotHighlight msg+              unhighlighted+        _ -> unhighlighted inlineToOpenXML' opts (Note bs) = do   notes <- gets stFootnotes   notenum <- getUniqueId@@ -1041,6 +1056,7 @@             Just Emf  -> ".emf"             Just Tiff -> ".tiff"             Just Webp -> ".webp"+            Just Avif -> ".avif"             Nothing   -> ""         imgpath = "media/" <> ident <> imgext         mbMimeType = mt <|> getMimeType (T.unpack imgpath)
src/Text/Pandoc/Writers/HTML.hs view
@@ -53,7 +53,7 @@ import Text.Blaze.Html hiding (contents) import Text.Pandoc.Definition import Text.Pandoc.Highlighting (formatHtmlBlock, formatHtml4Block,-                 formatHtmlInline, highlight, styleToCss)+                 formatHtmlInline, highlight, styleToCss, defaultStyle) import Text.Pandoc.ImageSize import Text.Pandoc.Options import Text.Pandoc.Shared@@ -356,10 +356,14 @@   let mCss :: Maybe [Text] = lookupContext "css" metadata   let context :: Context Text       context =   (if stHighlighting st-                      then case writerHighlightStyle opts of-                                Just sty -> defField "highlighting-css"-                                            (literal $ T.pack $ styleToCss sty)-                                Nothing  -> id+                      then case writerHighlightMethod opts of+                             Skylighting sty ->+                               defField "highlighting-css"+                                 (literal $ T.pack $ styleToCss sty)+                             DefaultHighlighting ->+                               defField "highlighting-css"+                                 (literal $ T.pack $ styleToCss defaultStyle)+                             _  -> id                       else id) .                   (if stCsl st                       then defField "csl-css" True .@@ -845,6 +849,11 @@                      if null innerSecs                         then mempty                         else nl <> innerContents+blockToHtmlInner opts (Div (ident, classes, kvs) [b])+  | Just "1" <- lookup "wrapper" kvs+    -- unwrap "wrapper" div, putting attr on child+  = blockToHtmlInner opts b >>=+      addAttrs opts (ident, classes, [(k,v) | (k,v) <- kvs, k /= "wrapper"]) blockToHtmlInner opts (Div attr@(ident, classes, kvs') bs) = do   html5 <- gets stHtml5   slideVariant <- gets stSlideVariant@@ -943,11 +952,13 @@       adjCode  = if tolhs                     then T.unlines . map ("> " <>) . T.lines $ rawCode                     else rawCode-      hlCode   = if isJust (writerHighlightStyle opts)-                    then highlight (writerSyntaxMap opts)-                         (if html5 then formatHtmlBlock else formatHtml4Block)-                            (id'',classes',keyvals) adjCode-                    else Left ""+      highlighted = highlight (writerSyntaxMap opts)+                      (if html5 then formatHtmlBlock else formatHtml4Block)+                      (id'',classes',keyvals) adjCode+      hlCode   = case writerHighlightMethod opts of+                   Skylighting _ -> highlighted+                   DefaultHighlighting -> highlighted+                   _ -> Left ""   case hlCode of          Left msg -> do            unless (T.null msg) $@@ -1437,11 +1448,12 @@                                modify $ \st -> st{ stHighlighting = True }                                addAttrs opts (ids,[],kvs) $                                  fromMaybe id sampOrVar h-                        where hlCode = if isJust (writerHighlightStyle opts)-                                          then highlight-                                                 (writerSyntaxMap opts)-                                                 formatHtmlInline attr str-                                          else Left ""+                        where hlCode = case writerHighlightMethod opts of+                                          Skylighting _ -> highlighted+                                          DefaultHighlighting -> highlighted+                                          _ -> Left ""+                              highlighted =  highlight (writerSyntaxMap opts)+                                                       formatHtmlInline attr str                               (sampOrVar,cs')                                 | "sample" `elem` cs =                                       (Just H.samp,"sample" `delete` cs)
src/Text/Pandoc/Writers/LaTeX.hs view
@@ -7,7 +7,7 @@ {-# LANGUAGE ViewPatterns        #-} {- |    Module      : Text.Pandoc.Writers.LaTeX-   Copyright   : Copyright (C) 2006-2024 John MacFarlane+   Copyright   : Copyright (C) 2006-2025 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -30,8 +30,9 @@       liftM,       when,       unless )+import Crypto.Hash (hashWith, MD5(MD5)) import Data.Containers.ListUtils (nubOrd)-import Data.Char (isDigit)+import Data.Char (isDigit, isAscii) import Data.List (intersperse, (\\)) import Data.Maybe (catMaybes, fromMaybe, isJust, mapMaybe, isNothing) import Data.Monoid (Any (..))@@ -40,10 +41,11 @@ import Network.URI (unEscapeString) import Text.DocTemplates (FromContext(lookupContext), Val(..), renderTemplate) import Text.Collate.Lang (renderLang)-import Text.Pandoc.Class.PandocMonad (PandocMonad, report, toLang)+import Text.Pandoc.Class.PandocMonad (PandocMonad, getPOSIXTime, lookupEnv,+                                      report, toLang) import Text.Pandoc.Definition import Text.Pandoc.Highlighting (formatLaTeXBlock, formatLaTeXInline, highlight,-                                 styleToLaTeX)+                                 defaultStyle, styleToLaTeX) import Text.Pandoc.ImageSize import Text.Pandoc.Logging import Text.Pandoc.Options@@ -63,7 +65,11 @@                                        wrapDiv, hypertarget, labelFor,                                        getListingsLanguage, mbBraced) import Text.Pandoc.Writers.Shared+import qualified Data.Attoparsec.Text as A+import qualified Text.Pandoc.UTF8 as UTF8 import qualified Text.Pandoc.Writers.AnnotatedTable as Ann+import Data.Char (isLetter)+import Control.Applicative ((<|>))  -- Work around problems with notes inside emphasis (see #8982) isolateBigNotes :: ([Inline] -> Inline) -> [Inline] -> [Inline]@@ -176,8 +182,22 @@   main <- blockListToLaTeX blocks'''   biblioTitle <- inlineListToLaTeX lastHeader   st <- get-  titleMeta <- stringToLaTeX TextString $ stringify $ docTitle meta+  titleMeta <- escapeCommas <$> -- see #10501+                stringToLaTeX TextString (stringify $ docTitle meta)   authorsMeta <- mapM (stringToLaTeX TextString . stringify) $ docAuthors meta+  -- The trailer ID is as hash used to identify the PDF. Taking control of its+  -- value is important when aiming for reproducible PDF generation. Setting+  -- `SOURCE_DATE_EPOCH` is the traditional method used to control+  -- reproducible builds. There are no cryptographic requirements for the ID,+  -- so the 128bits (16 bytes) of MD5 are appropriate.+  reproduciblePDF <- isJust <$> lookupEnv "SOURCE_DATE_EPOCH"+  trailerID <- do+    time <- getPOSIXTime+    let hash = T.pack . show . hashWith MD5 $ mconcat+               [ UTF8.fromString $ show time+               , UTF8.fromText $ render Nothing main+               ]+    pure $ mconcat [ "<", hash, "> <", hash, ">" ]   -- we need a default here since lang is used in template conditionals   let hasStringValue x = isJust (getField x metadata :: Maybe (Doc Text))   let geometryFromMargins = mconcat $ intersperse ("," :: Doc Text) $@@ -212,6 +232,7 @@                   defField "verbatim-in-note" (stVerbInNote st) $                   defField "tables" (stTable st) $                   defField "multirow" (stMultiRow st) $+                  defField "cancel" (stCancel st) $                   defField "strikeout" (stStrikeout st) $                   defField "url" (stUrl st) $                   defField "numbersections" (writerNumberSections options) $@@ -221,15 +242,20 @@                   defField "svg" (stSVG st) $                   defField "has-chapters" (stHasChapters st) $                   defField "has-frontmatter" (documentClass `elem` frontmatterClasses) $-                  defField "listings" (writerListings options || stLHS st) $+                  defField "listings" (writerHighlightMethod options ==+                                       IdiomaticHighlighting+                                       || stLHS st) $                   defField "zero-width-non-joiner" (stZwnj st) $                   defField "beamer" beamer $                   (if stHighlighting st-                      then case writerHighlightStyle options of-                                Just sty ->+                      then case writerHighlightMethod options of+                             Skylighting sty ->                                    defField "highlighting-macros"                                       (T.stripEnd $ styleToLaTeX sty)-                                Nothing -> id+                             DefaultHighlighting ->+                                   defField "highlighting-macros"+                                      (T.stripEnd $ styleToLaTeX defaultStyle)+                             _ -> id                       else id) $                   (case writerCiteMethod options of                          Natbib   -> defField "biblio-title" biblioTitle .@@ -254,7 +280,10 @@                       Just (Just ('A', ds))                         | not (T.null ds) && T.all isDigit ds                           -> resetField "papersize" ("a" <> ds)-                      _   -> id)+                      _   -> id) .+                  (if reproduciblePDF+                    then defField "pdf-trailer-id" trailerID+                    else id) $                   metadata   let babelLang = mblang >>= toBabel   let context' =@@ -282,6 +311,10 @@        Nothing  -> main        Just tpl -> renderTemplate tpl context' +-- Commas in title-meta need to be put in braces; see #10501+escapeCommas :: Text -> Text+escapeCommas = T.replace "," "{,}"+ toSlides :: PandocMonad m => [Block] -> LW m [Block] toSlides bs = do   opts <- gets stOptions@@ -469,7 +502,8 @@         ref <- toLabel identifier         kvs <- mapM (\(k,v) -> (k,) <$>                        stringToLaTeX TextString v) keyvalAttr-        let params = if writerListings (stOptions st)+        let params = if writerHighlightMethod (stOptions st)+                        == IdiomaticHighlighting                      then (case getListingsLanguage classes of                                 Just l  -> [ "language=" <> mbBraced l ]                                 Nothing -> []) ++@@ -506,9 +540,12 @@   case () of      _ | isEnabled Ext_literate_haskell opts && "haskell" `elem` classes &&          "literate" `elem` classes           -> lhsCodeBlock-       | writerListings opts                 -> listingsCodeBlock-       | not (null classes) && isJust (writerHighlightStyle opts)+       | writerHighlightMethod opts == IdiomaticHighlighting+                                             -> listingsCodeBlock+       | not (null classes), Skylighting _ <- writerHighlightMethod opts                                              -> highlightedCodeBlock+       | not (null classes), DefaultHighlighting <- writerHighlightMethod opts+                                             -> highlightedCodeBlock        -- we don't want to use \begin{verbatim} if our code        -- contains \end{verbatim}:        | inNote@@ -616,11 +653,14 @@ blockToLaTeX (Table attr blkCapt specs thead tbodies tfoot) =   tableToLaTeX inlineListToLaTeX blockListToLaTeX                (Ann.toTable attr blkCapt specs thead tbodies tfoot)-blockToLaTeX (Figure (ident, _, _) captnode body) = do+blockToLaTeX (Figure (ident, _, kvs) captnode body) = do   opts <- gets stOptions   (capt, captForLof, footnotes) <- getCaption inlineListToLaTeX True captnode   lab <- labelFor ident   let caption = "\\caption" <> captForLof <> braces capt <> lab+      placement = case lookup "latex-placement" kvs of+        Just p -> brackets (text (T.unpack p))+        _      -> text ""    isSubfigure <- gets stInFigure   modify $ \st -> st{ stInFigure = True }@@ -652,7 +692,7 @@           cr <> "\\begin{center}" $$ contents $+$ capt $$ "\\end{center}"     _ | isSubfigure ->           innards-    _ ->  cr <> "\\begin{figure}" $$ innards $$ "\\end{figure}")+    _ ->  cr <> "\\begin{figure}" <> placement $$ innards $$ "\\end{figure}")     $$ footnotes  toSubfigure :: PandocMonad m => Int -> Block -> LW m (Doc Text)@@ -960,12 +1000,14 @@   -- incorrect results if there is a space (see #5529).   let inMbox x = "\\mbox" <> braces x   (if inSoul then inMbox else id) <$>-   case () of+   case writerHighlightMethod opts of      _ | inHeading || inItem  -> rawCode  -- see #5574-       | writerListings opts  -> listingsCode-       | isJust (writerHighlightStyle opts) && not (null classes)+     IdiomaticHighlighting    -> listingsCode+     Skylighting _ | not (null classes)                               -> highlightCode-       | otherwise            -> rawCode+     DefaultHighlighting | not (null classes)+                              -> highlightCode+     _noHighlighting          -> rawCode inlineToLaTeX (Quoted qt lst) = do   contents <- inlineListToLaTeX lst   csquotes <- liftM stCsquotes get@@ -1002,10 +1044,16 @@ inlineToLaTeX (Str str) = do   setEmptyLine False   liftM literal $ stringToLaTeX TextString str+inlineToLaTeX (Math _ str)+  | isMathEnv str -- see #9711+  = do setEmptyLine False+       when (needsCancel str) $ modify $ \st -> st{ stCancel = True }+       pure $ literal str inlineToLaTeX (Math InlineMath str) = do   setEmptyLine False   inSoul <- gets stInSoulCommand   let contents = literal (handleMathComment str)+  when (needsCancel str) $ modify $ \st -> st{ stCancel = True }   return $     if inSoul -- #9597        then "$" <> contents <> "$"@@ -1014,6 +1062,7 @@   setEmptyLine False   inSoul <- gets stInSoulCommand   let contents = literal (handleMathComment str)+  when (needsCancel str) $ modify $ \st -> st{ stCancel = True }   return $     if inSoul -- # 9597        then "$$" <> contents <> "$$"@@ -1053,7 +1102,9 @@                      then "\\hyperlink" <> braces (literal lab) <> braces contents                      else "\\hyperref" <> brackets (literal lab) <> braces contents      _ -> case txt of-          [Str x] | unEscapeString (T.unpack x) == unEscapeString (T.unpack src) ->  -- autolink+          [Str x] | T.all isAscii x  -- see #8802+                  , unEscapeString (T.unpack x) ==+                    unEscapeString (T.unpack src) ->  -- autolink                do modify $ \s -> s{ stUrl = True }                   src' <- stringToLaTeX URLString (escapeURI src)                   return $ literal $ "\\url{" <> src' <> "}"@@ -1289,3 +1340,40 @@   , "galician"   , "slovene"   ]++isMathEnv :: Text -> Bool+isMathEnv t =+  case T.stripPrefix "\\begin{" t of+    Nothing -> False+    Just t' -> T.takeWhile (/= '}') t' `elem`+      [ "align", "align*"+      , "flalign", "flalign*"+      , "alignat", "alignat*"+      , "dmath", "dmath*"+      , "dgroup", "dgroup*"+      , "darray", "darray*"+      , "gather", "gather*"+      , "multline", "multline*"+      , "split"+      , "subequations"+      , "equation", "equation*"+      , "eqnarray"+      , "displaymath"+      ]++-- True if the math needs the cancel package+needsCancel :: Text -> Bool+needsCancel t =+  case A.parseOnly pCancel t of+    Right True -> True+    _ -> False+ where+  pCancel = (False <$ A.endOfInput) <|> do+    c <- A.anyChar+    case c of+      '\\' -> do+        x <- A.takeWhile isLetter+        if x == "cancel" || x == "xcancel" || x == "bcancel"+           then return True+           else pCancel+      _ -> pCancel
src/Text/Pandoc/Writers/LaTeX/Types.hs view
@@ -53,6 +53,7 @@   , stIsFirstInDefinition :: Bool    -- ^ first block in a defn list   , stLang          :: Maybe Lang    -- ^ lang specified in metadata   , stInSoulCommand :: Bool          -- ^ in a soul command like ul+  , stCancel        :: Bool          -- ^ true if document uses \cancel   }  startingState :: WriterOptions -> WriterState@@ -93,4 +94,5 @@   , stIsFirstInDefinition = False   , stLang = Nothing   , stInSoulCommand = False+  , stCancel = False   }
src/Text/Pandoc/Writers/LaTeX/Util.hs view
@@ -134,6 +134,7 @@          ']'  -> emits "{]}"  -- optional arguments          '\'' -> emitcseq "\\textquotesingle"          '\160' -> emits "~"+         '\x00AD' -> emits "\\-"  -- shy hyphen          '\x200B' -> emits "\\hspace{0pt}"  -- zero-width space          '\x202F' -> emits "\\,"          '\x2026' | ligatures -> emitcseq "\\ldots"
src/Text/Pandoc/Writers/Man.hs view
@@ -362,7 +362,10 @@ formatTok :: WriterOptions -> FormatOptions -> (TokenType, Text) -> Doc Text formatTok wopts _fopts (toktype, t) =   let txt = literal (escString wopts t)-      styleMap = tokenStyles <$> writerHighlightStyle wopts+      styleMap = case writerHighlightMethod wopts of+        Skylighting style   -> Just $ tokenStyles style+        DefaultHighlighting -> Just $ tokenStyles defaultStyle+        _ -> Nothing       tokStyle = fromMaybe defStyle $ styleMap >>= M.lookup toktype   in  if toktype == NormalTok          then txt
src/Text/Pandoc/Writers/Markdown.hs view
@@ -25,7 +25,7 @@ import Control.Monad.Reader ( asks, MonadReader(local) ) import Control.Monad.State.Strict ( gets, modify ) import Data.Default-import Data.List (intersperse, sortOn, union)+import Data.List (intersperse, sortOn, union, find) import Data.List.NonEmpty (nonEmpty, NonEmpty(..)) import qualified Data.Map as M import Data.Maybe (fromMaybe, mapMaybe, isNothing)@@ -369,6 +369,10 @@                  -> Block         -- ^ Block element                  -> MD m (Doc Text) blockToMarkdown' opts (Div attrs@(_,classes,_) bs)+  | ("sourceCode":_) <- classes+  , [CodeBlock (_,"sourceCode":_,_) _] <- bs+     -- skip pandoc-generated Div wrappers around code blocks+   = blockListToMarkdown opts bs   | isEnabled Ext_alerts opts   , (cls:_) <- classes   , cls `elem` ["note", "tip", "warning", "caution", "important"]@@ -396,8 +400,7 @@                          | (take 3 (T.unpack id')) == "ref"                            -> contents <> blankline                          | otherwise -> contents <> blankline-             | isEnabled Ext_fenced_divs opts &&-               attrs /= nullAttr ->+             | isEnabled Ext_fenced_divs opts ->                   let attrsToMd = if variant == Commonmark                                   then attrsToMarkdown opts                                   else classOrAttrsToMarkdown opts@@ -589,9 +592,11 @@      attrs  = if isEnabled Ext_fenced_code_attributes opts ||                  isEnabled Ext_attributes opts                  then nowrap $ " " <> classOrAttrsToMarkdown opts attribs-                 else case attribs of-                            (_,cls:_,_) -> " " <> literal cls-                            _             -> empty+                 else+                   let (_,cls,_) = attribs+                    in case getLangFromClasses cls of+                              Just l -> " " <> literal l+                              Nothing -> empty blockToMarkdown' opts (BlockQuote blocks) = do   variant <- asks envVariant   -- if we're writing literate haskell, put a space before the bird tracks@@ -851,26 +856,21 @@        let tabStop = writerTabStop opts        variant <- asks envVariant        let leader  = case variant of-                        PlainText -> "   "-                        Markua -> ":"-                        _ -> ":  "-       let sps = case writerTabStop opts - 3 of-                      n | n > 0   -> literal $ T.replicate n " "-                      _ -> literal " "+                        PlainText -> " "+                        _ -> ":"+       let leadingChars = case tabStop of+                            -- Always use two leading characters for Markua+                            n | n >= 2 && variant /= Markua -> n+                            _ -> 2+       let sps = literal $ T.replicate (leadingChars - 1) " "        let isTight = case defs of                         ((Plain _ : _): _) -> True                         _                  -> False-       if isEnabled Ext_compact_definition_lists opts-          then do-            let contents = vcat $ map (\d -> hang tabStop (leader <> sps)-                                $ vcat d <> cr) defs'-            return $ nowrap labelText <> cr <> contents <> cr-          else do-            let contents = (if isTight then vcat else vsep) $ map-                            (\d -> hang tabStop (leader <> sps) $ vcat d)-                            defs'-            return $ blankline <> nowrap labelText $$-                     (if isTight then empty else blankline) <> contents <> blankline+       let contents = (if isTight then vcat else vsep) $ map+                       (\d -> hang leadingChars (leader <> sps) $ vcat d)+                       defs'+       return $ blankline <> nowrap labelText $$+                (if isTight then empty else blankline) <> contents <> blankline      else        return $ nowrap (chomp labelText <> literal "  " <> cr) <>                 vsep (map vsep defs') <> blankline@@ -948,3 +948,14 @@  where    go (Div _ bls') n = max (n + 1) (foldr go (n + 1) bls')    go _ n = n++-- Identify the class in a list of classes that corresponds to+-- the language syntax.  language-X turns to X.+getLangFromClasses :: [Text] -> Maybe Text+getLangFromClasses cs =+  case find ("language-" `T.isPrefixOf`) cs of+    Just x -> Just (T.drop 9 x)+    Nothing ->+      case filter (/= "sourceCode") cs of+        (x:_) -> Just x+        [] -> Nothing
src/Text/Pandoc/Writers/Ms.hs view
@@ -76,7 +76,9 @@   let authorsMeta = map (escapeStr opts . stringify) $ docAuthors meta   hasHighlighting <- gets stHighlighting   let highlightingMacros = if hasHighlighting-                              then maybe mempty styleToMs $ writerHighlightStyle opts+                              then case writerHighlightMethod opts of+                                     Skylighting sty -> styleToMs sty+                                     _ -> mempty                               else mempty    let context = defField "body" main
src/Text/Pandoc/Writers/ODT.hs view
@@ -34,7 +34,8 @@ import Text.Pandoc.ImageSize import Text.Pandoc.Logging import Text.Pandoc.MIME (extensionFromMimeType, getMimeType)-import Text.Pandoc.Options (WrapOption (..), WriterOptions (..))+import Text.Pandoc.Options (WrapOption (..), WriterOptions (..),+                            HighlightMethod(Skylighting)) import Text.DocLayout import Text.Pandoc.Shared (stringify, tshow) import Text.Pandoc.Version (pandocVersionText)@@ -211,7 +212,9 @@                 . maybe id addLang mbLang                 . transformElement (\qn -> qName qn == "styles" &&                                       qPrefix qn == Just "office" )-                     (maybe id addHlStyles (writerHighlightStyle opts))+                     (case writerHighlightMethod opts of+                        Skylighting style -> addHlStyles style+                        _ -> id)                 $ d )         | otherwise = pure e   entries <- mapM goEntry (zEntries arch)
src/Text/Pandoc/Writers/OpenDocument.hs view
@@ -21,7 +21,6 @@ import Data.Foldable (find) import Data.List (sortOn, sortBy, foldl') import qualified Data.Map as Map-import Data.Maybe (isNothing) import Data.Ord (comparing) import qualified Data.Set as Set import Data.Text (Text)@@ -390,15 +389,16 @@     OrderedList  a b -> setFirstPara >> orderedList a b     CodeBlock attrs s -> do       setFirstPara-      if isNothing (writerHighlightStyle o)-         then unhighlighted s-         else case highlight (writerSyntaxMap o) formatOpenDocument attrs s of+      case writerHighlightMethod o of+        Skylighting {} ->+          case highlight (writerSyntaxMap o) formatOpenDocument attrs s of                 Right h  -> return $ flush . vcat $ map (inTags True "text:p"                                           [("text:style-name",                                             "Preformatted_20_Text")] . hcat) h                 Left msg -> do                   unless (T.null msg) $ report $ CouldNotHighlight msg                   unhighlighted s+        _ -> unhighlighted s     Table a bc s th tb tf -> setFirstPara >>                               table o (Ann.toTable a bc s th tb tf)     HorizontalRule   -> setFirstPara >> return (selfClosingTag "text:p"@@ -630,14 +630,14 @@     Subscript   l -> withTextStyle Sub    $ inlinesToOpenDocument o l     SmallCaps   l -> withTextStyle SmallC $ inlinesToOpenDocument o l     Quoted    t l -> inQuotes t <$> inlinesToOpenDocument o l-    Code      attrs s -> if isNothing (writerHighlightStyle o)-      then unhighlighted s-      else case highlight (writerSyntaxMap o)-                  formatOpenDocument attrs s of+    Code      attrs s -> case writerHighlightMethod o of+      Skylighting {} ->+        case highlight (writerSyntaxMap o) formatOpenDocument attrs s of                 Right h  -> inlinedCode $ mconcat $ mconcat h                 Left msg -> do                   unless (T.null msg) $ report $ CouldNotHighlight msg                   unhighlighted s+      _ -> unhighlighted s     Math      t s -> lift (texMathToInlines t s) >>=                          inlinesToOpenDocument o     Cite      _ l -> inlinesToOpenDocument o l
src/Text/Pandoc/Writers/Org.hs view
@@ -3,8 +3,8 @@ {- |    Module      : Text.Pandoc.Writers.Org    Copyright   : © 2010-2015 Puneeth Chaganti <punchagan@gmail.com>-                   2010-2024 John MacFarlane <jgm@berkeley.edu>-                   2016-2024 Albert Krewinkel <albert+pandoc@tarleb.com>+                   2010-2025 John MacFarlane <jgm@berkeley.edu>+                   2016-2025 Albert Krewinkel <albert+pandoc@tarleb.com>    License     : GNU GPL, version 2 or above     Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>@@ -71,6 +71,17 @@   let main = body $+$ notes   let context = defField "body" main               . defField "math" hasMath+              . defField "options"+                         (M.fromList+                          ((if isEnabled Ext_smart_quotes opts+                            then (("'", "t"):)+                            else id) .+                           (if not (isEnabled Ext_special_strings opts)+                            then (("-", "nil"):)+                            else id)+                           $ ([] :: [(Text, Text)])))+              . defField "option-special-strings"+                         (isEnabled Ext_special_strings opts)               $ metadata   return $ render colwidth $     case writerTemplate opts of@@ -89,20 +100,28 @@   let marker = "[fn:" ++ show num ++ "] "   return $ hang (length marker) (text marker) contents +-- | Replace Unicode characters with their ASCII representation+replaceSpecialStrings :: Text -> Text+replaceSpecialStrings =+  let expand c = case c of+        '\x00ad' -> "\\-"+        '\x2013' -> "--"+        '\x2014' -> "---"+        '\x2019' -> "'"+        '\x2026' -> "..."+        _        -> T.singleton c+  in T.concatMap expand+ -- | Escape special characters for Org. escapeString :: Text -> Doc Text escapeString t   | T.all isAlphaNum t = literal t   | otherwise = mconcat $ map escChar (T.unpack t)   where-   escChar '\x2013' = "--"-   escChar '\x2014' = "---"-   escChar '\x2019' = "'"-   escChar '\x2026' = "..."-   escChar c-     -- escape special chars with ZERO WIDTH SPACE as org manual suggests-     | c == '*' || c == '#' || c == '|' = afterBreak "\x200B" <> char c-     | otherwise = char c+    -- escape special chars with ZERO WIDTH SPACE as org manual suggests+   escChar c = if c == '*' || c == '#' || c == '|'+     then afterBreak "\x200B" <> char c+     else char c  isRawFormat :: Format -> Bool isRawFormat f =@@ -488,10 +507,18 @@ inlineToOrg (SmallCaps lst) = inlineListToOrg lst inlineToOrg (Quoted SingleQuote lst) = do   contents <- inlineListToOrg lst-  return $ "'" <> contents <> "'"+  opts <- gets stOptions+  return $+    if isEnabled Ext_smart opts || isEnabled Ext_smart_quotes opts+    then "'" <> contents <> "'"+    else "‘" <> contents <> "’" inlineToOrg (Quoted DoubleQuote lst) = do   contents <- inlineListToOrg lst-  return $ "\"" <> contents <> "\""+  opts <- gets stOptions+  return $+    if isEnabled Ext_smart opts || isEnabled Ext_smart_quotes opts+    then "\"" <> contents <> "\""+    else "“" <> contents <> "”" inlineToOrg (Cite cs lst) = do   opts <- gets stOptions   if isEnabled Ext_citations opts@@ -522,7 +549,12 @@        return $ "[cite" <> sty <> ":" <> citeItems <> "]"      else inlineListToOrg lst inlineToOrg (Code _ str) = return $ "=" <> literal str <> "="-inlineToOrg (Str str) = return $ escapeString str+inlineToOrg (Str str) = do+  opts <- gets stOptions+  let str' = if isEnabled Ext_smart opts || isEnabled Ext_special_strings opts+             then replaceSpecialStrings str+             else str+  return $ escapeString str' inlineToOrg (Math t str) = do   modify $ \st -> st{ stHasMath = True }   return $ if t == InlineMath@@ -547,7 +579,7 @@   case txt of         [Str x] | escapeURI x == src ->  -- autolink              return $ "[[" <> literal (orgPath x) <> "]]"-        _ -> do contents <- inlineListToOrg txt+        _ -> do contents <- nowrap <$> inlineListToOrg txt                 return $ "[[" <> literal (orgPath src) <> "][" <> contents <> "]]" inlineToOrg (Image _ _ (source, _)) =   return $ "[[" <> literal (orgPath source) <> "]]"
src/Text/Pandoc/Writers/Powerpoint/Output.hs view
@@ -915,6 +915,7 @@                  Just Emf  -> Just ".emf"                  Just Tiff -> Just ".tiff"                  Just Webp -> Just ".webp"+                 Just Avif -> Just ".avif"                  Nothing   -> Nothing    let newGlobalId = fromMaybe (maxGlobalId + 1) (M.lookup fp globalIds)
src/Text/Pandoc/Writers/Powerpoint/Presentation.hs view
@@ -460,15 +460,17 @@                                     , pPropIndent = Just 0                                     }                 , envRunProps = (envRunProps r){rPropCode = True}}) $ do-    mbSty <- writerHighlightStyle <$> asks envOpts+    highlightOpt <- writerHighlightMethod <$> asks envOpts     synMap <- writerSyntaxMap <$> asks envOpts-    case mbSty of-      Just sty ->-        case highlight synMap (formatSourceLines sty) attr str of-          Right pElems -> do pPropsNew <- asks envParaProps-                             return [Paragraph pPropsNew pElems]-          Left _ -> blockToParagraphs $ Para [Str str]-      Nothing -> blockToParagraphs $ Para [Str str]+    let highlightWithStyle style = do+          case highlight synMap (formatSourceLines style) attr str of+            Right pElems -> do pPropsNew <- asks envParaProps+                               return [Paragraph pPropsNew pElems]+            Left _ -> blockToParagraphs $ Para [Str str]+    case highlightOpt of+      Skylighting sty -> highlightWithStyle sty+      DefaultHighlighting -> highlightWithStyle defaultStyle+      _ -> blockToParagraphs $ Para [Str str] -- We can't yet do incremental lists, but we should render a -- (BlockQuote List) as a list to maintain compatibility with other -- formats.
src/Text/Pandoc/Writers/Shared.hs view
@@ -568,6 +568,8 @@  -- | Retrieve the metadata value for a given @key@ -- and extract blocks.+--+-- Note that an empty list is returned for maps, lists, and booleans. lookupMetaBlocks :: Text -> Meta -> [Block] lookupMetaBlocks key meta =   case lookupMeta key meta of@@ -578,6 +580,8 @@  -- | Retrieve the metadata value for a given @key@ -- and extract inlines.+--+-- Note that an empty list is returned for maps and lists. lookupMetaInlines :: Text -> Meta -> [Inline] lookupMetaInlines key meta =   case lookupMeta key meta of@@ -589,6 +593,8 @@  -- | Retrieve the metadata value for a given @key@ -- and convert to String.+--+-- Note that an empty list is returned for maps, lists, and booleans. lookupMetaString :: Text -> Meta -> Text lookupMetaString key meta =   case lookupMeta key meta of
src/Text/Pandoc/Writers/Typst.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE OverloadedStrings   #-} {-# LANGUAGE BangPatterns        #-}+{-# LANGUAGE LambdaCase          #-} {-# LANGUAGE ScopedTypeVariables #-} {- |    Module      : Text.Pandoc.Writers.Typst@@ -28,9 +29,12 @@ import Network.URI (unEscapeString) import qualified Data.Text as T import Control.Monad.State ( StateT, evalStateT, gets, modify )-import Text.Pandoc.Writers.Shared ( metaToContext, defField, resetField,-                                    lookupMetaString )+import Text.Pandoc.Writers.Shared ( lookupMetaInlines, lookupMetaString,+                                    metaToContext, defField, resetField,+                                    setupTranslations ) import Text.Pandoc.Shared (isTightList, orderedListMarkers, tshow)+import Text.Pandoc.Translations (Term(Abstract), translateTerm)+import Text.Pandoc.Walk (query) import Text.Pandoc.Writers.Math (convertMath) import qualified Text.TeXMath as TM import Text.DocLayout@@ -38,8 +42,9 @@ import Text.Pandoc.Extensions (Extension(..)) import Text.Collate.Lang (Lang(..), parseLang) import Text.Printf (printf)-import Data.Char (isAlphaNum, isDigit)+import Data.Char (isDigit) import Data.Maybe (fromMaybe)+import Unicode.Char (isXIDContinue)  -- | Convert Pandoc to Typst. writeTypst :: PandocMonad m => WriterOptions -> Pandoc -> m Text@@ -64,18 +69,27 @@   let colwidth = if writerWrapText options == WrapAuto                     then Just $ writerColumns options                     else Nothing+  setupTranslations meta   metadata <- metaToContext options               blocksToTypst               (fmap chomp . inlinesToTypst)               meta   main <- blocksToTypst blocks+  abstractTitle <- translateTerm Abstract   let toPosition :: CaptionPosition -> Text       toPosition CaptionAbove = "top"       toPosition CaptionBelow = "bottom"+  let nociteIds = query (\case+                           Cite cs _ -> map citationId cs+                           _         -> [])+                  $ lookupMetaInlines "nocite" meta+   let context = defField "body" main               $ defField "toc" (writerTableOfContents options)               $ (if isEnabled Ext_citations options                     then defField "citations" True+                       . defField "nocite-ids" (filter (/= "*") nociteIds)+                       . defField "full-bibliography" ("*" `elem` nociteIds)                     else id)               $ (case lookupMetaString "lang" meta of                     "" -> id@@ -87,6 +101,7 @@                           maybe id (resetField "region") (langRegion l))               $ defField "csl" (lookupMetaString "citation-style" meta) -- #10661               $ defField "smart" (isEnabled Ext_smart options)+              $ defField "abstract-title" abstractTitle               $ defField "toc-depth" (tshow $ writerTOCDepth options)               $ defField "figure-caption-position"                    (toPosition $ writerFigureCaptionPosition options)@@ -94,9 +109,9 @@                    (toPosition $ writerTableCaptionPosition options)               $ defField "page-numbering" ("1" :: Text)               $ (if writerNumberSections options-                    then defField "numbering" ("1.1.1.1.1" :: Text)+                    then defField "section-numbering" ("1.1.1.1.1" :: Text)                     else id)-              $ metadata+              metadata   return $ render colwidth $     case writerTemplate options of        Nothing  -> main@@ -107,15 +122,15 @@   where     go (k,v) =       case T.splitOn ":" k of-        "typst":"text":x:[] -> second ((x,v):)-        "typst":x:[] -> first ((x,v):)+        ["typst", "text", x] -> second ((x,v):)+        ["typst", x] -> first ((x,v):)         _ -> id  formatTypstProp :: (Text, Text) -> Text formatTypstProp (k,v) = k <> ": " <> v  toTypstPropsListSep :: [(Text, Text)] -> Doc Text-toTypstPropsListSep = hsep . intersperse "," . (map $ literal . formatTypstProp)+toTypstPropsListSep = hsep . intersperse "," . map (literal . formatTypstProp)  toTypstPropsListTerm :: [(Text, Text)] -> Doc Text toTypstPropsListTerm [] = ""@@ -147,12 +162,9 @@ blockToTypst :: PandocMonad m => Block -> TW m (Doc Text) blockToTypst block =   case block of-    Plain inlines -> do-      opts <- gets stOptions-      inlinesToTypst (addLineStartEscapes opts inlines)+    Plain inlines -> inlinesToTypst inlines     Para inlines -> do-      opts <- gets stOptions-      ($$ blankline) <$> inlinesToTypst (addLineStartEscapes opts inlines)+      ($$ blankline) <$> inlinesToTypst inlines     Header level (ident,cls,_) inlines -> do       contents <- inlinesToTypst inlines       let lab = toLabel FreestandingLabel ident@@ -342,9 +354,17 @@     Div (ident,_,kvs) blocks -> do       let lab = toLabel FreestandingLabel ident       let (typstAttrs,typstTextAttrs) = pickTypstAttrs kvs+      -- Handle lang attribute for Div elements+      let langAttrs = case lookup "lang" kvs of+                        Nothing -> []+                        Just lang -> case parseLang lang of+                                       Left _ -> []+                                       Right l -> [("lang",+                                                    tshow (langLanguage l))]+      let allTypstTextAttrs = typstTextAttrs ++ langAttrs       contents <- blocksToTypst blocks       return $ "#block" <> toTypstPropsListParens typstAttrs <> "["-        $$ toTypstPoundSetText typstTextAttrs <> contents+        $$ toTypstPoundSetText allTypstTextAttrs <> contents         $$ ("]" <+> lab)  defListItemToTypst :: PandocMonad m => ([Inline], [[Block]]) -> TW m (Doc Text)@@ -483,23 +503,17 @@  textstyle :: PandocMonad m => Doc Text -> [Inline] -> TW m (Doc Text) textstyle s inlines = do-  opts <-  gets stOptions-  (<> endCode) . (s <>) . brackets-    <$> inlinesToTypst (addLineStartEscapes opts inlines)+  (<> endCode) . (s <>) . brackets . fixInitialAfterBreakEscape+    <$> inlinesToTypst inlines -addLineStartEscapes :: WriterOptions -> [Inline] -> [Inline]-addLineStartEscapes opts = go True- where-   go True (Str t : xs)-        | isOrderedListMarker t = RawInline "typst" "\\" : Str t : go False xs-        | Just (c, t') <- T.uncons t-        , needsEscapeAtLineStart c-        , T.null t' = RawInline "typst" "\\" : Str t : go False xs-   go _ (SoftBreak : xs)-        | writerWrapText opts == WrapPreserve = SoftBreak : go True xs-   go _ (LineBreak : xs) = LineBreak : go True xs-   go _ (x : xs) = x : go False xs-   go _ [] = []+fixInitialAfterBreakEscape :: Doc Text -> Doc Text+fixInitialAfterBreakEscape (Concat x y) =+  Concat (fixInitialAfterBreakEscape x) y+-- make an initial AfterBreak escape unconditional (it will be rendered+-- in a block [..] and there won't be an actual break to trigger it, but+-- typst still needs the escape)+fixInitialAfterBreakEscape (AfterBreak "\\") = Text 1 "\\"+fixInitialAfterBreakEscape x = x  isOrderedListMarker :: Text -> Bool isOrderedListMarker t = not (T.null ds) && rest == "."@@ -509,7 +523,7 @@ escapeTypst smart context t =   (case T.uncons t of     Just (c, _)-      | needsEscapeAtLineStart c+      | needsEscapeAtLineStart c || isOrderedListMarker t         -> afterBreak "\\"     _ -> mempty) <>   (literal (T.replace "//" "\\/\\/"@@ -570,7 +584,7 @@    ident' = T.pack $ unEscapeString $ T.unpack ident  isIdentChar :: Char -> Bool-isIdentChar c = isAlphaNum c || c == '_' || c == '-' || c == '.' || c == ':'+isIdentChar c = isXIDContinue c || c == '_' || c == '-' || c == '.' || c == ':'  toCite :: PandocMonad m => Citation -> TW m (Doc Text) toCite cite = do@@ -596,7 +610,10 @@                   [] -> pure mempty                   suff -> (", supplement: " <>) . brackets                              <$> inlinesToTypst (eatComma suff)-       pure $ "#cite" <> parens (label <> form <> suppl) <> endCode+       pure $ (if citationMode cite == SuppressAuthor  -- see #11044+                  then parens+                  else id)+            $ "#cite" <> parens (label <> form <> suppl) <> endCode  doubleQuoted :: Text -> Doc Text doubleQuoted = doubleQuotes . literal . escape
+ src/Text/Pandoc/Writers/XML.hs view
@@ -0,0 +1,365 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}++-- |+--   Module      : Text.Pandoc.Writers.XML+--   Copyright   : Copyright (C) 2025- Massimiliano Farinella and John MacFarlane+--   License     : GNU GPL, version 2 or above+--+--   Maintainer  : Massimiliano Farinella <massifrg@gmail.com>+--   Stability   : WIP+--   Portability : portable+--+-- Conversion of 'Pandoc' documents to (pandoc specific) xml markup.+module Text.Pandoc.Writers.XML (writeXML) where++import Data.Map (Map, toList)+import Data.Maybe (mapMaybe)+import qualified Data.Text as T+import Data.Version (versionBranch)+import Text.Pandoc.Class.PandocMonad (PandocMonad)+import Text.Pandoc.Definition+import Text.Pandoc.Options (WriterOptions (..))+import Text.Pandoc.XML.Light+import qualified Text.Pandoc.XML.Light as XML+import Text.Pandoc.XMLFormat+import Text.XML.Light (xml_header)++type PandocAttr = Text.Pandoc.Definition.Attr++writeXML :: (PandocMonad m) => WriterOptions -> Pandoc -> m T.Text+writeXML _ doc = do+  return $ pandocToXmlText doc++text_node :: T.Text -> Content+text_node text = Text (CData CDataText text Nothing)++emptyElement :: T.Text -> Element+emptyElement tag =+  Element+    { elName = unqual tag,+      elAttribs = [],+      elContent = [],+      elLine = Nothing+    }++elementWithContents :: T.Text -> [Content] -> Element+elementWithContents tag contents =+  Element+    { elName = unqual tag,+      elAttribs = [],+      elContent = contents,+      elLine = Nothing+    }++elementWithAttributes :: T.Text -> [XML.Attr] -> Element+elementWithAttributes tag attributes =+  Element+    { elName = unqual tag,+      elAttribs = attributes,+      elContent = [],+      elLine = Nothing+    }++elementWithAttrAndContents :: T.Text -> PandocAttr -> [Content] -> Element+elementWithAttrAndContents tag attr contents = addAttrAttributes attr $ elementWithContents tag contents++asBlockOfInlines :: Element -> [Content]+asBlockOfInlines el = [Elem el, text_node "\n"]++asBlockOfBlocks :: Element -> [Content]+asBlockOfBlocks el = [Elem newline_before_first, newline]+  where+    newline = text_node "\n"+    newline_before_first = if null (elContent el) then el else prependContents [newline] el++itemName :: (Show a) => a -> T.Text+itemName a = T.pack $ takeWhile (/= ' ') (show a)++intAsText :: Int -> T.Text+intAsText i = T.pack $ show i++itemAsEmptyElement :: (Show a) => a -> Element+itemAsEmptyElement item = emptyElement $ itemName item++pandocToXmlText :: Pandoc -> T.Text+pandocToXmlText (Pandoc (Meta meta) blocks) = with_header . with_blocks . with_meta . with_version $ el+  where+    el = prependContents [text_node "\n"] $ emptyElement "Pandoc"+    with_version = addAttribute atNameApiVersion (T.intercalate "," $ map (T.pack . show) $ versionBranch pandocTypesVersion)+    with_meta = appendContents (metaMapToXML meta "meta")+    with_blocks = appendContents (asBlockOfBlocks $ elementWithContents "blocks" $ blocksToXML blocks)+    with_header :: Element -> T.Text+    with_header e = T.concat [T.pack xml_header, "\n", showElement e]++metaMapToXML :: Map T.Text MetaValue -> T.Text -> [Content]+metaMapToXML mmap tag = asBlockOfBlocks $ elementWithContents tag entries+  where+    entries = concatMap to_entry $ toList mmap+    to_entry :: (T.Text, MetaValue) -> [Content]+    to_entry (text, metavalue) = asBlockOfBlocks with_key+      where+        entry = elementWithContents tgNameMetaMapEntry $ metaValueToXML metavalue+        with_key = addAttribute atNameMetaMapEntryKey text entry++metaValueToXML :: MetaValue -> [Content]+metaValueToXML value =+  let name = itemName value+      el = itemAsEmptyElement value+   in case (value) of+        MetaBool b -> asBlockOfInlines $ addAttribute atNameMetaBoolValue bool_value el+          where+            bool_value = if b then "true" else "false"+        MetaString s -> asBlockOfInlines $ appendContents [text_node s] el+        MetaInlines inlines -> asBlockOfInlines $ appendContents (inlinesToXML inlines) el+        MetaBlocks blocks -> asBlockOfBlocks $ appendContents (blocksToXML blocks) el+        MetaList items -> asBlockOfBlocks $ appendContents (concatMap metaValueToXML items) el+        MetaMap mm -> metaMapToXML mm name++blocksToXML :: [Block] -> [Content]+blocksToXML blocks = concatMap blockToXML blocks++inlinesToXML :: [Inline] -> [Content]+inlinesToXML inlines = concatMap inlineContentToContents (ilsToIlsContent inlines [])++data InlineContent+  = NormalInline Inline+  | ElSpace Int+  | ElStr T.Text++ilsToIlsContent :: [Inline] -> [InlineContent] -> [InlineContent]+ilsToIlsContent (Space : xs) [] = ilsToIlsContent xs [ElSpace 1]+ilsToIlsContent (Space : xs) (NormalInline Space : cs) = ilsToIlsContent xs (ElSpace 2 : cs)+ilsToIlsContent (Space : xs) (ElSpace n : cs) = ilsToIlsContent xs (ElSpace (n + 1) : cs)+-- empty Str are always encoded as <Str />+ilsToIlsContent (Str "" : xs) ilct = ilsToIlsContent xs (ElStr "" : ilct)+-- Str s1, Str s2 -> s1<Str content="s2">+ilsToIlsContent (Str s2 : xs) (NormalInline str1@(Str _) : ilct) = ilsToIlsContent xs (ElStr s2 : NormalInline str1 : ilct)+--+ilsToIlsContent (Str s : xs) ilct =+  if T.any (== ' ') s+    then ilsToIlsContent xs (ElStr s : ilct)+    else ilsToIlsContent xs (NormalInline (Str s) : ilct)+ilsToIlsContent (x : xs) ilct = ilsToIlsContent xs (NormalInline x : ilct)+ilsToIlsContent [] ilct = reverse $ lastSpaceAsElem ilct+  where+    lastSpaceAsElem :: [InlineContent] -> [InlineContent]+    lastSpaceAsElem (NormalInline Space : xs) = ElSpace 1 : xs+    lastSpaceAsElem ilcts = ilcts++inlineContentToContents :: InlineContent -> [Content]+inlineContentToContents (NormalInline il) = inlineToXML il+inlineContentToContents (ElSpace 1) = [Elem $ emptyElement "Space"]+inlineContentToContents (ElSpace n) = [Elem $ addAttribute atNameSpaceCount (intAsText n) (emptyElement "Space")]+inlineContentToContents (ElStr "") = [Elem $ emptyElement "Str"]+inlineContentToContents (ElStr s) = [Elem $ addAttribute atNameStrContent s (emptyElement "Str")]++asContents :: Element -> [Content]+asContents el = [Elem el]++wrapBlocks :: T.Text -> [Block] -> [Content]+wrapBlocks tag blocks = asBlockOfBlocks $ elementWithContents tag $ blocksToXML blocks++wrapArrayOfBlocks :: T.Text -> [[Block]] -> [Content]+wrapArrayOfBlocks tag array = concatMap (wrapBlocks tag) array++-- wrapInlines :: T.Text -> [Inline] -> [Content]+-- wrapInlines tag inlines = asBlockOfInlines $ element_with_contents tag $ inlinesToXML inlines++blockToXML :: Block -> [Content]+blockToXML block =+  let el = itemAsEmptyElement block+   in case (block) of+        Para inlines -> asBlockOfInlines $ appendContents (inlinesToXML inlines) el+        Header level (idn, cls, attrs) inlines -> asBlockOfInlines $ appendContents (inlinesToXML inlines) with_attr+          where+            with_attr = addAttrAttributes (idn, cls, attrs ++ [(atNameLevel, intAsText level)]) el+        Plain inlines -> asBlockOfInlines $ appendContents (inlinesToXML inlines) el+        Div attr blocks -> asBlockOfBlocks $ appendContents (blocksToXML blocks) with_attr+          where+            with_attr = addAttrAttributes attr el+        BulletList items -> asBlockOfBlocks $ appendContents (wrapArrayOfBlocks tgNameListItem items) el+        OrderedList (start, style, delim) items -> asBlockOfBlocks $ with_contents . with_attrs $ el+          where+            with_attrs =+              addAttributes+                ( validAttributes+                    [ (atNameStart, intAsText start),+                      (atNameNumberStyle, itemName style),+                      (atNameNumberDelim, itemName delim)+                    ]+                )+            with_contents = appendContents (wrapArrayOfBlocks tgNameListItem items)+        BlockQuote blocks -> asBlockOfBlocks $ appendContents (blocksToXML blocks) el+        HorizontalRule -> asBlockOfInlines el+        CodeBlock attr text -> asBlockOfInlines $ with_contents . with_attr $ el+          where+            with_contents = appendContents [text_node text]+            with_attr = addAttrAttributes attr+        LineBlock lins -> asBlockOfBlocks $ appendContents (concatMap wrapInlines lins) el+          where+            wrapInlines inlines = asContents $ appendContents (inlinesToXML inlines) $ emptyElement tgNameLineItem+        Table attr caption colspecs thead tbodies tfoot -> asBlockOfBlocks $ with_foot . with_bodies . with_head . with_colspecs . with_caption . with_attr $ el+          where+            with_attr = addAttrAttributes attr+            with_caption = appendContents (captionToXML caption)+            with_colspecs = appendContents (colSpecsToXML colspecs)+            with_head = appendContents (tableHeadToXML thead)+            with_bodies = appendContents (concatMap tableBodyToXML tbodies)+            with_foot = appendContents (tableFootToXML tfoot)+        Figure attr caption blocks -> asBlockOfBlocks $ with_contents . with_caption . with_attr $ el+          where+            with_attr = addAttrAttributes attr+            with_caption = appendContents (captionToXML caption)+            with_contents = appendContents (blocksToXML blocks)+        RawBlock (Format format) text -> asContents $ appendContents [text_node text] raw+          where+            raw = addAttribute atNameFormat format el+        DefinitionList items -> asBlockOfBlocks $ appendContents (map definitionListItemToXML items) el++inlineToXML :: Inline -> [Content]+inlineToXML inline =+  let el = itemAsEmptyElement inline+      wrapInlines inlines = asContents $ appendContents (inlinesToXML inlines) el+   in case (inline) of+        Space -> [text_node " "]+        Str s -> [text_node s]+        Emph inlines -> wrapInlines inlines+        Strong inlines -> wrapInlines inlines+        Quoted quote_type inlines -> asContents $ appendContents (inlinesToXML inlines) quoted+          where+            quoted = addAttribute atNameQuoteType (itemName quote_type) el+        Underline inlines -> wrapInlines inlines+        Strikeout inlines -> wrapInlines inlines+        SmallCaps inlines -> wrapInlines inlines+        Superscript inlines -> wrapInlines inlines+        Subscript inlines -> wrapInlines inlines+        SoftBreak -> asContents el+        LineBreak -> asContents el+        Span attr inlines -> asContents $ appendContents (inlinesToXML inlines) with_attr+          where+            with_attr = addAttrAttributes attr el+        Link (idn, cls, attrs) inlines (url, title) -> asContents $ appendContents (inlinesToXML inlines) with_attr+          where+            with_attr = addAttrAttributes (idn, cls, attrs ++ [(atNameLinkUrl, url), (atNameTitle, title)]) el+        Image (idn, cls, attrs) inlines (url, title) -> asContents $ appendContents (inlinesToXML inlines) with_attr+          where+            with_attr = addAttrAttributes (idn, cls, attrs ++ [(atNameImageUrl, url), (atNameTitle, title)]) el+        RawInline (Format format) text -> asContents $ appendContents [text_node text] raw+          where+            raw = addAttribute atNameFormat format el+        Math math_type text -> asContents $ appendContents [text_node text] math+          where+            math = addAttribute atNameMathType (itemName math_type) el+        Code attr text -> asContents $ appendContents [text_node text] with_attr+          where+            with_attr = addAttrAttributes attr el+        Note blocks -> asContents $ appendContents (blocksToXML blocks) el+        Cite citations inlines -> asContents $ appendContents (inlinesToXML inlines) with_citations+          where+            with_citations = addCitations citations el++-- TODO: don't let an attribute overwrite id or class+maybeAttribute :: (T.Text, T.Text) -> Maybe XML.Attr+maybeAttribute (_, "") = Nothing+maybeAttribute ("", _) = Nothing+maybeAttribute (name, value) = Just $ XML.Attr (unqual name) value++validAttributes :: [(T.Text, T.Text)] -> [XML.Attr]+validAttributes pairs = mapMaybe maybeAttribute pairs++appendContents :: [Content] -> Element -> Element+appendContents newContents el = el {elContent = (elContent el) ++ newContents}++prependContents :: [Content] -> Element -> Element+prependContents newContents el = el {elContent = newContents ++ (elContent el)}++addAttributes :: [XML.Attr] -> Element -> Element+addAttributes newAttrs el = el {elAttribs = newAttrs ++ elAttribs el}++addAttribute :: T.Text -> T.Text -> Element -> Element+addAttribute attr_name attr_value el = el {elAttribs = new_attr : elAttribs el}+  where+    new_attr = XML.Attr (unqual attr_name) attr_value++addAttrAttributes :: PandocAttr -> Element -> Element+addAttrAttributes (identifier, classes, attributes) el = addAttributes attrs' el+  where+    attrs' = mapMaybe maybeAttribute (("id", identifier) : ("class", T.intercalate " " classes) : attributes)++addCitations :: [Citation] -> Element -> Element+addCitations citations el = appendContents [Elem $ elementWithContents tgNameCitations $ (text_node "\n") : concatMap citation_to_elem citations] el+  where+    citation_to_elem :: Citation -> [Content]+    citation_to_elem citation = asBlockOfInlines with_suffix+      where+        cit_elem = elementWithAttributes (itemName citation) attrs+        prefix = citationPrefix citation+        suffix = citationSuffix citation+        with_prefix =+          if null prefix+            then cit_elem+            else appendContents [Elem $ elementWithContents tgNameCitationPrefix $ inlinesToXML prefix] cit_elem+        with_suffix =+          if null suffix+            then with_prefix+            else appendContents [Elem $ elementWithContents tgNameCitationSuffix $ inlinesToXML suffix] with_prefix+        attrs =+          map+            (\(n, v) -> XML.Attr (unqual n) v)+            [ ("id", citationId citation),+              (atNameCitationMode, T.pack $ show $ citationMode citation),+              (atNameCitationNoteNum, intAsText $ citationNoteNum citation),+              (atNameCitationHash, intAsText $ citationHash citation)+            ]++definitionListItemToXML :: ([Inline], [[Block]]) -> Content+definitionListItemToXML (inlines, defs) = Elem $ elementWithContents tgNameDefListItem $ term ++ wrapArrayOfBlocks tgNameDefListDef defs+  where+    term = asBlockOfInlines $ appendContents (inlinesToXML inlines) $ emptyElement tgNameDefListTerm++captionToXML :: Caption -> [Content]+captionToXML (Caption short blocks) = asBlockOfBlocks with_short_caption+  where+    el = elementWithContents "Caption" $ blocksToXML blocks+    with_short_caption = case (short) of+      Just inlines -> prependContents (asBlockOfInlines $ elementWithContents tgNameShortCaption $ inlinesToXML inlines) el+      _ -> el++colSpecToXML :: (Alignment, ColWidth) -> [Content]+colSpecToXML (align, cw) = asBlockOfInlines colspec+  where+    colspec = elementWithAttributes "ColSpec" $ validAttributes [(atNameAlignment, itemName align), (atNameColWidth, colwidth)]+    colwidth = case (cw) of+      ColWidth d -> T.pack $ show d+      ColWidthDefault -> "0"++colSpecsToXML :: [(Alignment, ColWidth)] -> [Content]+colSpecsToXML colspecs = asBlockOfBlocks $ elementWithContents tgNameColspecs $ concatMap colSpecToXML colspecs++tableHeadToXML :: TableHead -> [Content]+tableHeadToXML (TableHead attr rows) = asBlockOfBlocks $ elementWithAttrAndContents "TableHead" attr $ concatMap rowToXML rows++tableBodyToXML :: TableBody -> [Content]+tableBodyToXML (TableBody (idn, cls, attrs) (RowHeadColumns headcols) hrows brows) = asBlockOfBlocks $ elementWithAttrAndContents "TableBody" attr children+  where+    attr = (idn, cls, (atNameRowHeadColumns, intAsText headcols) : attrs)+    header_rows = asBlockOfBlocks $ elementWithContents tgNameBodyHeader $ concatMap rowToXML hrows+    body_rows = asBlockOfBlocks $ elementWithContents tgNameBodyBody $ concatMap rowToXML brows+    children = header_rows ++ body_rows++tableFootToXML :: TableFoot -> [Content]+tableFootToXML (TableFoot attr rows) = asBlockOfBlocks $ elementWithAttrAndContents "TableFoot" attr $ concatMap rowToXML rows++rowToXML :: Row -> [Content]+rowToXML (Row attr cells) = asBlockOfBlocks $ elementWithAttrAndContents "Row" attr $ concatMap cellToXML cells++cellToXML :: Cell -> [Content]+cellToXML (Cell (idn, cls, attrs) alignment (RowSpan rowspan) (ColSpan colspan) blocks) = asBlockOfBlocks $ elementWithAttrAndContents "Cell" attr $ blocksToXML blocks+  where+    with_alignment a = (atNameAlignment, itemName alignment) : a+    with_rowspan a = if rowspan > 1 then (atNameRowspan, intAsText rowspan) : a else a+    with_colspan a = if colspan > 1 then (atNameColspan, intAsText colspan) : a else a+    attrs' = (with_colspan . with_rowspan . with_alignment) attrs+    attr = (idn, cls, attrs')
+ src/Text/Pandoc/XMLFormat.hs view
@@ -0,0 +1,188 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Text.Pandoc.XMLFormat+  ( atNameAlignment,+    atNameApiVersion,+    atNameCitationHash,+    atNameCitationMode,+    atNameCitationNoteNum,+    atNameColspan,+    atNameColWidth,+    atNameFormat,+    atNameImageUrl,+    atNameLevel,+    atNameLinkUrl,+    atNameMathType,+    atNameMetaBoolValue,+    atNameMetaMapEntryKey,+    atNameNumberDelim,+    atNameNumberStyle,+    atNameQuoteType,+    atNameRowHeadColumns,+    atNameRowspan,+    atNameSpaceCount,+    atNameStart,+    atNameStrContent,+    atNameTitle,+    tgNameBodyBody,+    tgNameBodyHeader,+    tgNameCitations,+    tgNameCitationPrefix,+    tgNameCitationSuffix,+    tgNameColspecs,+    tgNameDefListDef,+    tgNameDefListItem,+    tgNameDefListTerm,+    tgNameLineItem,+    tgNameListItem,+    tgNameMetaMapEntry,+    tgNameShortCaption,+  )+where++import Data.Text (Text)++-- the attribute carrying the API version of pandoc types in the main Pandoc element+atNameApiVersion :: Text+atNameApiVersion = "api-version"++-- the element of a <meta> or <MetaMap> entry+tgNameMetaMapEntry :: Text+tgNameMetaMapEntry = "entry"++-- the attribute carrying the key name of a <meta> or <MetaMap> entry+atNameMetaMapEntryKey :: Text+atNameMetaMapEntryKey = "key"++-- the attribute carrying the boolean value ("true" or "false") of a MetaBool+atNameMetaBoolValue :: Text+atNameMetaBoolValue = "value"++-- level of a Header+atNameLevel :: Text+atNameLevel = "level"++-- start number of an OrderedList+atNameStart :: Text+atNameStart = "start"++-- number delimiter of an OrderedList+atNameNumberDelim :: Text+atNameNumberDelim = "number-delim"++-- number style of an OrderedList+atNameNumberStyle :: Text+atNameNumberStyle = "number-style"++-- target title in Image and Link+atNameTitle :: Text+atNameTitle = "title"++-- target url in Image+atNameImageUrl :: Text+atNameImageUrl = "src"++-- target url in Link+atNameLinkUrl :: Text+atNameLinkUrl = "href"++-- QuoteType of a Quoted+atNameQuoteType :: Text+atNameQuoteType = "quote-type"++-- MathType of a Math+atNameMathType :: Text+atNameMathType = "math-type"++-- format of a RawInline or a RawBlock+atNameFormat :: Text+atNameFormat = "format"++-- alignment attribute in a ColSpec or in a Cell+atNameAlignment :: Text+atNameAlignment = "alignment"++-- ColWidth attribute in a ColSpec+atNameColWidth :: Text+atNameColWidth = "col-width"++-- RowHeadColumns attribute in a TableBody+atNameRowHeadColumns :: Text+atNameRowHeadColumns = "row-head-columns"++-- RowSpan attribute in a Cell+atNameRowspan :: Text+atNameRowspan = "row-span"++-- ColSpan attribute in a Cell+atNameColspan :: Text+atNameColspan = "col-span"++-- the citationMode of a Citation+atNameCitationMode :: Text+atNameCitationMode = "mode"++-- the citationHash of a Citation+atNameCitationHash :: Text+atNameCitationHash = "hash"++-- the citationNoteNum of a Citation+atNameCitationNoteNum :: Text+atNameCitationNoteNum = "note-num"++-- the number of consecutive spaces of the <Space> element+atNameSpaceCount :: Text+atNameSpaceCount = "count"++-- the content of the <Str> element+atNameStrContent :: Text+atNameStrContent = "content"++-- container of Citation elements in Cite inlines+tgNameCitations :: Text+tgNameCitations = "citations"++-- element around the prefix inlines of a Citation+tgNameCitationPrefix :: Text+tgNameCitationPrefix = "prefix"++-- element around the suffix inlines of a Citation+tgNameCitationSuffix :: Text+tgNameCitationSuffix = "suffix"++-- list item for BulletList and OrderedList+tgNameListItem :: Text+tgNameListItem = "item"++-- list item for DefinitionList+tgNameDefListItem :: Text+tgNameDefListItem = "item"++-- element around the inlines of the term of a DefinitionList item+tgNameDefListTerm :: Text+tgNameDefListTerm = "term"++-- element around the blocks of a definition in a DefinitionList item+tgNameDefListDef :: Text+tgNameDefListDef = "def"++-- optional element of the ShortCaption+tgNameShortCaption :: Text+tgNameShortCaption = "ShortCaption"++-- element around the ColSpec of a Table+tgNameColspecs :: Text+tgNameColspecs = "colspecs"++-- element around the header rows of a TableBody+tgNameBodyHeader :: Text+tgNameBodyHeader = "header"++-- element around the body rows of a TableBody+tgNameBodyBody :: Text+tgNameBodyBody = "body"++-- element around the inlines of a line in a LineBlock+tgNameLineItem :: Text+tgNameLineItem = "line"
test/Tests/Readers/HTML.hs view
@@ -130,10 +130,10 @@           [ test html "attributes in pre > code element" $             "<pre><code id=\"a\" class=\"python\">\nprint('hi')\n</code></pre>"             =?>-            codeBlockWith ("a", ["python"], []) "print('hi')"+            codeBlockWith ("a", ["python"], []) "\nprint('hi')"            , test html "attributes in pre take precedence" $-            "<pre id=\"c\"><code id=\"d\">\nprint('hi mom!')\n</code></pre>"+            "<pre id=\"c\"><code id=\"d\">print('hi mom!')\n</code></pre>"             =?>             codeBlockWith ("c", [], []) "print('hi mom!')"           ]
test/Tests/Readers/Markdown.hs view
@@ -29,10 +29,6 @@ markdownSmart = purely $  readMarkdown def { readerExtensions =                              enableExtension Ext_smart pandocExtensions } -markdownCDL :: Text -> Pandoc-markdownCDL = purely $ readMarkdown def { readerExtensions = enableExtension-                 Ext_compact_definition_lists pandocExtensions }- markdownGH :: Text -> Pandoc markdownGH = purely $ readMarkdown def {readerExtensions = enableExtension                  Ext_wikilinks_title_before_pipe githubMarkdownExtensions }@@ -461,14 +457,14 @@           , "blank space before first def" =:             "foo1\n\n  :  bar\n\nfoo2\n\n  : bar2\n  : bar3\n" =?>             definitionList [ (text "foo1", [para (text "bar")])-                           , (text "foo2", [para (text "bar2"),-                                            plain (text "bar3")])+                           , (text "foo2", [plain (text "bar2"),+                                            para (text "bar3")])                            ]           , "blank space before second def" =:             "foo1\n  :  bar\n\nfoo2\n  : bar2\n\n  : bar3\n" =?>             definitionList [ (text "foo1", [plain (text "bar")])                            , (text "foo2", [plain (text "bar2"),-                                            para (text "bar3")])+                                            plain (text "bar3")])                            ]           , "laziness" =:             "foo1\n  :  bar\nbaz\n  : bar2\n" =?>@@ -478,8 +474,8 @@                            ]           , "no blank space before first of two paragraphs" =:             "foo1\n  : bar\n\n    baz\n" =?>-            definitionList [ (text "foo1", [para (text "bar") <>-                                            para (text "baz")])+            definitionList [ (text "foo1", [plain (text "bar") <>+                                            plain (text "baz")])                            ]           , "first line not indented" =:             "foo\n: bar\n" =?>@@ -492,14 +488,6 @@             divWith nullAttr (definitionList               [ (text "foo", [bulletList [plain (text "bar")]]) ])           ]-        , testGroup "+compact_definition_lists"-          [ test markdownCDL "basic compact list" $-            "foo1\n:   bar\n    baz\nfoo2\n:   bar2\n" =?>-            definitionList [ (text "foo1", [plain (text "bar" <> softbreak <>-                                                     text "baz")])-                           , (text "foo2", [plain (text "bar2")])-                           ]-          ]         , testGroup "lists"           [ "issue #1154" =:               " -  <div>\n    first div breaks\n    </div>\n\n    <button>if this button exists</button>\n\n    <div>\n    with this div too.\n    </div>\n"@@ -590,4 +578,11 @@                   (str "@cita" <> space <> str "[foo]")               )           ]+      , testGroup "figures"+        [ "latex placement" =:+          "![caption](img.jpg){latex-placement=\"htbp\" alt=\"alt text\"}" =?>+          figureWith ("", [], [("latex-placement", "htbp")])+            (simpleCaption $ plain "caption")+            (plain $ image (T.pack "img.jpg") (T.pack "") (text "alt text"))         ]+      ]
test/Tests/Readers/ODT.hs view
@@ -180,6 +180,8 @@                                   , "referenceToText"                                   , "simpleTable"                                   , "simpleTableWithCaption"+                                  , "simpleTableWithHeader"+                                  , "simpleTableWithMultipleHeaderRows"                                   , "tab" --                                , "table"                                   , "textMixedStyles"
test/Tests/Readers/Org/Block/Header.hs view
@@ -118,6 +118,13 @@         in headerWith ("compile", [], []) 1 (waiting <> space <> "compile")         <> headerWith ("lunch", [], []) 1 (cancelled <> space <> "lunch")         <> headerWith ("todo-feature", [], []) 1 (done <> space <> "todo-feature")++    , "Fast access TODO states" =:+        T.unlines [ "#+TODO: TODO(t) | DONE(d)"+                  , "* TODO test"+                  ] =?>+        let todoSpan = spanWith ("", ["todo", "TODO"], []) "TODO"+        in headerWith ("test", [], []) 1 (todoSpan <> space <> "test")     ]    , "Tagged headers" =:
test/Tests/Readers/Org/Inline.hs view
@@ -88,6 +88,10 @@       "2^{n-1}" =?>       para (str "2" <> superscript "n-1") +  , "Superscript-like, but not after string" =:+      "a ^caret" =?>+      para "a ^caret"+   , "Subscript simple expression" =:       "a_n" =?>       para (str "a" <> subscript "n")@@ -95,6 +99,14 @@   , "Subscript multi char" =:       "a_{n+1}" =?>       para (str "a" <> subscript "n+1")++  , "Subscript-like, but not after string" =:+      "_underscore" =?>+      para "_underscore"++  , "Subscript takes precedence before underline" =:+      "text_subscript_" =?>+      para (str "text" <> subscript "subscript" <> str "_")    , "Linebreak" =:       "line \\\\ \nbreak" =?>
test/Tests/Readers/Org/Inline/Smart.hs view
@@ -47,6 +47,10 @@     ("/foo---/" =?>      para (emph "foo—")) +  , test orgSmart "Support for shy (soft) hyphen"+    ("Ur\\-instinkt" =?>+     para "Ur\173instinkt")+   , test orgSmart "Single quotes can be followed by emphasized text"     ("Singles on the '/meat market/'" =?>      para ("Singles on the " <> singleQuoted (emph "meat market")))
test/Tests/Readers/Pod.hs view
@@ -145,6 +145,17 @@             "E<rchevron>" =?>             para "»"         ]+      , testGroup "html"+        [ "trade" =:+           "E<trade>" =?>+           para "™"+        , "ccaron" =:+           "E<ccaron>" =?>+           para "č"+        , "cent" =:+           "E<cent>" =?>+           para "¢"+        ]       , testGroup "numeric"         [ "decimal" =:             "E<162>" =?>@@ -170,6 +181,7 @@         , bogusEntity "0xhh"         , bogusEntity "077x"         , bogusEntity "0x63 skidoo"+        , bogusEntity "trade;"         ]       ]     ]
test/Tests/Writers/LaTeX.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} module Tests.Writers.LaTeX (tests) where -import Data.Text (unpack)+import Data.Text (pack, unpack) import Test.Tasty import Test.Tasty.HUnit (HasCallStack) import Tests.Helpers@@ -13,7 +13,7 @@ latex = latexWithOpts def  latexListing :: (ToPandoc a) => a -> String-latexListing = latexWithOpts def{ writerListings = True }+latexListing = latexWithOpts def{ writerHighlightMethod = IdiomaticHighlighting }  latexWithOpts :: (ToPandoc a) => WriterOptions -> a -> String latexWithOpts opts = unpack . purely (writeLaTeX opts) . toPandoc@@ -241,5 +241,15 @@                       , "\\addcontentsline{toc}{paragraph}{header6}"                       ]             ]+          ]+        , testGroup "figures"+          [ "placement" =:+            figureWith ("", [], [("latex-placement", "htbp")])+            (simpleCaption $ plain "caption")+            (plain $ image (pack "img.jpg") (pack "") (text "alt text"))+            =?>+              "\\begin{figure}[htbp]\n\\centering\n"+              <> "\\pandocbounded{\\includegraphics[keepaspectratio,alt={alt text}]{img.jpg}}\n"+              <> "\\caption{caption}\n\\end{figure}"           ]         ]
+ test/Tests/XML.hs view
@@ -0,0 +1,28 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+--   Module      : Tests.XML+--   Copyright   : Copyright (C) 2025- Massimiliano Farinella and John MacFarlane+--   License     : GNU GPL, version 2 or above+--+--   Maintainer  : Massimiliano Farinella <massifrg@gmail.com>+--   Stability   : WIP+--   Portability : portable+Runs a roundtrip conversion of an AST trough the XML format:+- first from AST to XML (XML Writer),+- then back to AST (XML Reader),+- and checks that the two ASTs are the same+-}+module Tests.XML (tests) where++import Control.Monad ((>=>))+import Test.Tasty (TestTree)+import Test.Tasty.QuickCheck+import Tests.Helpers+import Text.Pandoc+import Text.Pandoc.Arbitrary ()++p_xml_roundtrip :: Pandoc -> Bool+p_xml_roundtrip d = d == purely (writeXML def {writerTemplate = Just mempty} >=> readXML def) d++tests :: [TestTree]+tests = [testProperty "p_xml_roundtrip" p_xml_roundtrip]
test/command/10160.md view
@@ -7,5 +7,9 @@ \begin{table}[h] \end{table} ^D-[ Para [ Math DisplayMath "[0,1)" ] ]+[ Para+    [ Math+        DisplayMath "\\begin{equation}\n  [0,1)\n\\end{equation}"+    ]+] ```
test/command/10185.md view
@@ -36,7 +36,7 @@ \section{References}\label{references}  \protect\phantomsection\label{refs}-\begin{CSLReferences}{1}{0}+\begin{CSLReferences}{1}{1} \bibitem[\citeproctext]{ref-foo} John Doe. n.d. \emph{The Title}. 
+ test/command/10338-rst-multiple-header-rows.md view
@@ -0,0 +1,155 @@+```+% pandoc -f rst -t native+Multiple Headers+================++========== =========+Header A1  Header A2+Header B1  Header B2+========== =========+body a1    body a1+body b1    body b2+========== =========++Headless+========++========== =========+body a1    body a1+body b1    body b2+========== =========++End Section+===========+^D+[ Header+    1+    ( "multiple-headers" , [] , [] )+    [ Str "Multiple" , Space , Str "Headers" ]+, Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Header" , Space , Str "A1" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Header" , Space , Str "A2" ] ]+           ]+       , Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Header" , Space , Str "B1" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "Header" , Space , Str "B2" ] ]+           ]+       ])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "body" , Space , Str "a1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "body" , Space , Str "a1" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "body" , Space , Str "b1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "body" , Space , Str "b2" ] ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+, Header 1 ( "headless" , [] , [] ) [ Str "Headless" ]+, Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    ]+    (TableHead ( "" , [] , [] ) [])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "body" , Space , Str "a1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "body" , Space , Str "a1" ] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "body" , Space , Str "b1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "body" , Space , Str "b2" ] ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+, Header+    1+    ( "end-section" , [] , [] )+    [ Str "End" , Space , Str "Section" ]+]+```
+ test/command/10635.md view
@@ -0,0 +1,24 @@+# Support for KOMA's `\minisec` command++```+% pandoc -f latex -t native+\minisec{Montage}+Zunächst suche man das Mauseloch.+^D+[ Header+    6+    ( "montage" , [ "unnumbered" , "unlisted" ] , [] )+    [ Str "Montage" ]+, Para+    [ Str "Zun\228chst"+    , Space+    , Str "suche"+    , Space+    , Str "man"+    , Space+    , Str "das"+    , Space+    , Str "Mauseloch."+    ]+]+```
+ test/command/10816.md view
@@ -0,0 +1,7 @@+```+% pandoc -f markdown -t typst+# Test①+^D+= Test①+#label("test①")+```
+ test/command/10889.md view
@@ -0,0 +1,16 @@+```+% pandoc+apple++: pomaceous++  fruit+^D+<dl>+<dt>apple</dt>+<dd>+<p>pomaceous</p>+<p>fruit</p>+</dd>+</dl>+```
+ test/command/10890.md view
@@ -0,0 +1,15 @@+```+% pandoc --tab-stop=2 --from=native --to=markdown+[ DefinitionList+    [ ( [ Str "apple" ]+      , [ [ Para [ Str "pomaceous" ] , Para [ Str "fruit" ] ] ]+      )+    ]+]+^D+apple++: pomaceous++  fruit+```
+ test/command/10912.md view
@@ -0,0 +1,16 @@+```+% pandoc -f docbook -t native+<orderedlist numeration="arabic" startingnumber="4">+<listitem>+<simpara>Para1</simpara>+</listitem>+<listitem>+<simpara>Para2</simpara>+</listitem>+</orderedlist>+^D+[ OrderedList+    ( 4 , Decimal , DefaultDelim )+    [ [ Para [ Str "Para1" ] ] , [ Para [ Str "Para2" ] ] ]+]+```
+ test/command/10915.md view
@@ -0,0 +1,8 @@+```+% pandoc -f latex+\newcommand{\a}{\ifmmode x \else y \fi}+$\a$ and \a+^D+<p><span class="math inline"><em>x</em></span> and y</p>+```+
+ test/command/10919.md view
@@ -0,0 +1,21 @@+# Org output with smart quotes turned on++```+% pandoc -t org+smart_quotes -s+"It's nice" she said.+^D+#+options: ':t++"It's nice" she said.+```++Same test, but with special strings turned off.+```+% pandoc -t org+smart_quotes-special_strings -s+"It's nice" she said.+^D+#+options: ':t+#+options: -:nil++"It’s nice" she said.+```
+ test/command/10926.md view
@@ -0,0 +1,19 @@+````+% pandoc -f html -t gfm+<div class="sourceCode" id="cb1"><pre+class="sourceCode ruby"><code class="sourceCode ruby"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="fu">test</span></span></code></pre></div>+^D+``` ruby+test+```+````++````+% pandoc -f html -t gfm+<pre+class="border language-ruby"><code class="sourceCode ruby"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="fu">test</span></span></code></pre>+^D+``` ruby+test+```+````
+ test/command/10965.md view
@@ -0,0 +1,47 @@+```+% pandoc -f markdown -t typst+::: {lang="en"}+This text should be in English.+:::+^D+#block[+#set text(lang: "en"); This text should be in English.++]+```++```+% pandoc -f markdown -t typst+::: {lang="fr"}+Ce texte devrait être en français.+:::+^D+#block[+#set text(lang: "fr"); Ce texte devrait être en français.++]+```++```+% pandoc -f markdown -t typst+::: {lang="de-DE"}+Dieser Text sollte auf Deutsch sein.+:::+^D+#block[+#set text(lang: "de"); Dieser Text sollte auf Deutsch sein.++]+```++```+% pandoc -f markdown -t typst+::: {lang=""}+This should not have lang set.+:::+^D+#block[+This should not have lang set.++]+```
+ test/command/10983.md view
@@ -0,0 +1,22 @@+```+% pandoc --citeproc --csl command/chicago-fullnote-bibliography.csl -t plain+---+references:+- id: test4+  type: blog-post+  title: "Username as author"+  author:+  - brtw+  container-title: "Reddit"+  issued:+    year: 2004+suppress-bibliography: true+...++[@test4]+^D+[1]++[1] brtw, “Username as Author,” Reddit, 2004.++```
+ test/command/10984.md view
@@ -0,0 +1,16 @@+ ```+ % pandoc -f html -t djot+<h1 id="foo" class="a b">Hi</hi>+^D+{#foo .a .b}+# Hi+```++In this one the id is suppressed by the djot writer because+the same one would be automatically generated by the djot reader:+```+% pandoc -f html -t djot+<h2 id="Introduction">Introduction</h2>+^D+## Introduction+```
+ test/command/11006.md view
@@ -0,0 +1,56 @@+```+% pandoc -f html -t asciidoc+<ul>+  <li>+    <p>Paragraph one</p>+    <p>Paragraph two to force a list continuation</p>+    <ul>+      <li>First nested</li>+      <li>Second nested</li>+    </ul>+  </li>+</ul>++<p>How about ordered lists?</p>++<ol>+  <li>+    <p>Paragraph one</p>+    <p>Paragraph two to force a list continuation</p>+    <ol><li>Nested item</li></ol>+  </li>+</ol>++<p>With non-default attributes:</p>++<ol>+  <li>+    <p>Paragraph one</p>+    <p>Paragraph two to force a list continuation</p>+    <ol start=5><li>Nested item</li></ol>+  </li>+</ol>+^D+* Paragraph one+++Paragraph two to force a list continuation++** First nested+** Second nested++How about ordered lists?++. Paragraph one+++Paragraph two to force a list continuation++.. Nested item++With non-default attributes:++. Paragraph one+++Paragraph two to force a list continuation+[start=5]+.. Nested item+```
+ test/command/11013.md view
@@ -0,0 +1,23 @@+```+% pandoc --csl command/chicago-fullnote-bibliography.csl -C --wrap=none -t plain+---+references:+- id: test10+  type: blog-post+  title: "Test 10: Lowercase username in brackets, Works!"+  author:+  - literal: "[deleted]"+  container-title: "Reddit"+  issued:+    year: 2009+...++blah [@test10].+^D+blah.[1]++[deleted]. “Test 10: Lowercase Username in Brackets, Works!” Reddit, 2009.++[1] [deleted], “Test 10: Lowercase Username in Brackets, Works!” Reddit, 2009.++```
+ test/command/11014.md view
@@ -0,0 +1,9 @@+```+% pandoc -f djot -t html+{.foo}+- bar+^D+<ul class="foo">+<li>bar</li>+</ul>+```
+ test/command/11017.md view
@@ -0,0 +1,9 @@+```+% pandoc -t markdown -f typst+#show heading: smallcaps++= Introduction+^D+# [Introduction]{.smallcaps}++```
+ test/command/11046.md view
@@ -0,0 +1,19 @@+```+% pandoc --citeproc -t plain+smart --csl command/chicago-note-bibliography.csl+---+references:+- id: doe+  title: Title+  type: book+  date: 2006+  author: John Doe+...++blah blah [@doe]---blah blah.+^D+blah blah[1]---blah blah.++John Doe. Title, n.d.++[1] John Doe, Title.+```
+ test/command/11047.md view
@@ -0,0 +1,7 @@+```+% pandoc -t typst --wrap=auto+Full-time study: 2001-2003; Thesis submission: Nov 2005; Award: Jul 2006.+^D+Full-time study: 2001-2003; Thesis submission: Nov 2005; Award: Jul+\2006.+```
+ test/command/11048.md view
@@ -0,0 +1,48 @@+```+% pandoc -f biblatex -t markdown -s+@article{khatri2021spooky,+    title = {Spooky action at a global distance: analysis of space-based+             entanglement distribution for the quantum internet},+    author = {Khatri, Sumeet and Brady, Anthony J and Desporte, Ren{\'e}e A and+              Bart, Manon P and Dowling, Jonathan P},+    journal = {{npj} Quantum Information},+    volume = {7},+    number = {1},+    pages = {4},+    doi = {10.1038/s41534-020-00327-5},+    url = {https://doi.org/10.1038/s41534-020-00327-5},+    year = {2021},+    publisher = {Nature Publishing Group UK London},+}+^D+---+nocite: "[@*]"+references:+- author:+  - family: Khatri+    given: Sumeet+  - family: Brady+    given: Anthony J+  - family: Desporte+    given: Renée A+  - family: Bart+    given: Manon P+  - family: Dowling+    given: Jonathan P+  container-title: "[npj]{.nocase} Quantum Information"+  doi: 10.1038/s41534-020-00327-5+  id: khatri2021spooky+  issue: 1+  issued: 2021+  page: 4+  publisher: Nature Publishing Group UK London+  title: "Spooky action at a global distance: Analysis of space-based+    entanglement distribution for the quantum internet"+  title-short: Spooky action at a global distance+  type: article-journal+  url: "https://doi.org/10.1038/s41534-020-00327-5"+  volume: 7+---+++```
+ test/command/11090.md view
@@ -0,0 +1,49 @@+```+% pandoc -f typst -t native+#include "command/11090/ch1.typ"++== Chapter Two++#figure(+  image("command/11090/media/image1.png"),+  caption: [This is an image.] +)+^D+[ Header+    2 ( "" , [] , [] ) [ Str "Chapter" , Space , Str "One" ]+, Figure+    ( "" , [] , [] )+    (Caption+       Nothing [ Para [ Str "An" , Space , Str "image." ] ])+    [ Para+        [ Image+            ( "" , [] , [] )+            []+            ( "command/11090/media/image1.png" , "" )+        ]+    ]+, Header+    2 ( "" , [] , [] ) [ Str "Chapter" , Space , Str "Two" ]+, Figure+    ( "" , [] , [] )+    (Caption+       Nothing+       [ Para+           [ Str "This"+           , Space+           , Str "is"+           , Space+           , Str "an"+           , Space+           , Str "image."+           ]+       ])+    [ Para+        [ Image+            ( "" , [] , [] )+            []+            ( "command/11090/media/image1.png" , "" )+        ]+    ]+]+```
+ test/command/11090/ch1.typ view
@@ -0,0 +1,6 @@+== Chapter One++#figure(+  image("media/image1.png"),+  caption: [An image.]+)
+ test/command/11113.docx view

binary file changed (absent → 14206 bytes)

+ test/command/11113.md view
@@ -0,0 +1,7 @@+```+% pandoc command/11113.docx -t plain+^D+Colored:❤️😏📖👌😒🤍++BW: 😊︎+```
test/command/1629.md view
@@ -1,5 +1,5 @@ ```-% pandoc -t latex --listings+% pandoc -t latex --syntax-highlighting=idiomatic bla bla `a % b`  *bla bla `a % b`*
test/command/2118.md view
@@ -8,7 +8,7 @@ \end{figure} ^D [ Figure-    ( "fig:setminus" , [] , [] )+    ( "fig:setminus" , [] , [ ( "latex-placement" , "ht" ) ] )     (Caption        Nothing [ Plain [ Str "Set" , Space , Str "subtraction" ] ])     [ Plain
test/command/3113.md view
@@ -11,7 +11,7 @@ [ Para     [ Math         DisplayMath-        "\\begin{aligned}\nA&=&B,\\\\\nC&=&D,\\\\\n%\\end{eqnarray}\n%\\begin{eqnarray}\nE&=&F\n\\end{aligned}"+        "\\begin{eqnarray}\nA&=&B,\\\\\nC&=&D,\\\\\n%\\end{eqnarray}\n%\\begin{eqnarray}\nE&=&F\n\\end{eqnarray}"     ] ] ```
test/command/3422.md view
@@ -1,7 +1,7 @@ See #3422  ```-% pandoc -t latex --listings+% pandoc -t latex --syntax-highlighting=idiomatic `int main(int argc, const char *argv[]);`{.c} ^D \passthrough{\lstinline[language=C]!int main(int argc, const char *argv[]);!}
test/command/3577.md view
@@ -15,7 +15,7 @@     \caption{Subfigure with Subfloat} \end{figure} ^D-<figure>+<figure data-latex-placement="ht"> <figure> <img src="img1.jpg" /> <figcaption>Caption 1</figcaption>@@ -34,7 +34,7 @@     \caption{Caption 3} \end{figure} ^D-<figure>+<figure data-latex-placement="ht"> <img src="img1.jpg" /> <figcaption>Caption 3</figcaption> </figure>
test/command/4164.md view
@@ -8,11 +8,9 @@  Here is inline html: -<div>-+::: {} `<balise>`{=html} bla bla--</div>+:::  ``` 
test/command/5420.md view
@@ -1,5 +1,5 @@ ```-% pandoc --listings -t latex+% pandoc --syntax-highlighting=idiomatic -t latex `int a = 1;`{.cpp style=cpp} ^D \passthrough{\lstinline[language={C++}, style=cpp]!int a = 1;!}
test/command/6783.md view
@@ -20,7 +20,7 @@ This is a test(Jupyter 2018).  Jupyter, Project. 2018. “Binder 2.0 - Reproducible, Interactive,-Sharable Environments for Science at Scale.” In Proceedings of the 17th+Sharable Environments for Science at Scale.” Proceedings of the 17th Python in Science Conference. ``` 
test/command/6890.md view
@@ -38,13 +38,11 @@             , citationHash = 0             }         ]-        [ Str "Fr\252chtel,"-        , Space-        , Str "Budde,"+        [ Str "Fr\252chtel"         , Space-        , Str "and"+        , Str "et"         , Space-        , Str "Cyprian"+        , Str "al."         , Space         , Str "(2013)"         ]@@ -65,13 +63,11 @@                     , citationHash = 0                     }                 ]-                [ Str "Fr\252chtel,"-                , Space-                , Str "Budde,"+                [ Str "Fr\252chtel"                 , Space-                , Str "and"+                , Str "et"                 , Space-                , Str "Cyprian"+                , Str "al."                 , Space                 , Str "(2013)"                 ]@@ -81,7 +77,7 @@ , Div     ( "refs"     , [ "references" , "csl-bib-body" , "hanging-indent" ]-    , [ ( "entry-spacing" , "0" ) ]+    , []     )     [ Div         ( "ref-fruchtel-sozialer-2013a" , [ "csl-entry" ] , [] )@@ -126,10 +122,6 @@             , Str "3rd"             , Space             , Str "ed."-            , Space-            , Str "Wiesbaden,"-            , Space-            , Str "Germany:"             , Space             , Str "Springer"             , Space
test/command/6951.md view
@@ -14,5 +14,5 @@  Crazy. n.d. -Doe, John. 2005. First Book. Cambridge: Cambridge University Press.+Doe, John. 2005. First Book. Cambridge University Press. ```
test/command/7219.md view
@@ -20,6 +20,6 @@ and also in (1958)  Reese, Trevor R. 1958. “Georgia in Anglo-Spanish Diplomacy, 1736-1739.”-William and Mary Quarterly, 3rd series, 15: 168–90.+William and Mary Quarterly, 3rd series, vol. 15: 168–90.  ```
test/command/7329.md view
@@ -32,7 +32,7 @@ <<refs>>  <<ref-item1>>-Doe, John. 2005. /First Book/. Cambridge: Cambridge University Press.+Doe, John. 2005. /First Book/. Cambridge University Press. ```  @@ -45,7 +45,7 @@ <<refs>>  <<ref-item1>>-Doe, John. 2005. /First Book/. Cambridge: Cambridge University Press.+Doe, John. 2005. /First Book/. Cambridge University Press. ```  ```
test/command/7512.md view
@@ -4,7 +4,12 @@ [d,\delta]=0. \end{equation*} ^D-[ Para [ Math DisplayMath "[d,\\delta]=0." ] ]+[ Para+    [ Math+        DisplayMath+        "\\begin{equation*}\n[d,\\delta]=0.\n\\end{equation*}"+    ]+] ```  ```
+ test/command/7691.docx view

binary file changed (absent → 11923 bytes)

+ test/command/7691.md view
@@ -0,0 +1,5 @@+```+% pandoc command/7691.docx+^D+<p>Some text</p>+```
test/command/8354.md view
@@ -26,7 +26,7 @@ ^D <h2 class="unnumbered" id="references">References</h2> <div id="refs" class="references csl-bib-body hanging-indent"-data-entry-spacing="0" role="list">+role="list"> <div id="ref-feketeExploringReproducibilityVisualization2020" class="csl-entry" role="listitem"> Fekete, Jean-Daniel, and Juliana Freire. 2020. <span>“Exploring
test/command/8745.md view
@@ -16,7 +16,7 @@ ^D [ Para [ Str "Sample" , Space , Str "text" ] , Figure-    ( "fig:Mondrian" , [] , [] )+    ( "fig:Mondrian" , [] , [ ( "latex-placement" , "ht" ) ] )     (Caption        Nothing        [ Plain
+ test/command/8869.md view
@@ -0,0 +1,20 @@+Org arguments can either be single words, or quoted.++```+% pandoc -f org -t native+#+begin_src jupyter-julia :exports both+1 + 2+#+end_src++#+begin_src jupyter-julia :exports "both"+1 + 2+#+end_src+^D+[ CodeBlock+    ( "" , [ "julia" , "code" ] , [ ( "exports" , "both" ) ] )+    "1 + 2\n"+, CodeBlock+    ( "" , [ "julia" , "code" ] , [ ( "exports" , "both" ) ] )+    "1 + 2\n"+]+```
+ test/command/8957.md view
@@ -0,0 +1,7 @@+```+% pandoc -f latex -t html --wrap=none+![Sample figure caption.](fig.jpg){width="342pt" height="9pc"}+^D+<p>![Sample figure caption.](fig.jpg)<span>width="342pt" height="9pc"</span></p>++```
+ test/command/9000.md view
@@ -0,0 +1,14 @@+```+% pandoc -t org --wrap=auto --columns=20+[This is a link with a long description that should not+wrap](http://example.com) and+some regular text after it so we can see how wrapping works.+^D+[[http://example.com][This is a link with a long description that should not wrap]]+and some regular+text after it so we+can see how wrapping+works.++```+
test/command/9017.md view
@@ -45,7 +45,8 @@ <ref-list>   <title></title>   <ref id="ref-degroot_probability">-    <mixed-citation>DeGroot. 2002. “Probability.”</mixed-citation>+    <mixed-citation>DeGroot. 2002.+    <italic>Probability</italic>.</mixed-citation>   </ref> </ref-list> </back>
test/command/9452.md view
@@ -14,6 +14,6 @@  With supplement @something2024[p.~3]. -And just the year #cite(<something2024>, form: "year");.+And just the year (#cite(<something2024>, form: "year");).  ```
test/command/982.md view
@@ -7,5 +7,9 @@ y=x^2 \EEQ ^D-[ Para [ Math DisplayMath "y=x^2" ] ]+[ Para+    [ Math+        DisplayMath "\\begin{equation}\ny=x^2\n\\end{equation}"+    ]+] ```
test/command/9904.md view
@@ -153,7 +153,7 @@ , Div     ( "refs"     , [ "references" , "csl-bib-body" , "hanging-indent" ]-    , [ ( "entry-spacing" , "0" ) ]+    , []     )     [ Div         ( "ref-item1" , [ "csl-entry" ] , [] )@@ -166,8 +166,6 @@             , Space             , Emph [ Str "First" , Space , Str "Book" ]             , Str "."-            , Space-            , Str "Cambridge:"             , Space             , Str "Cambridge"             , Space
test/command/biblatex-angenendt.md view
@@ -50,7 +50,7 @@   author:   - family: Angenendt     given: Arnold-  container-title: Revue d'Histoire Ecclésiastique+  container-title: Revue d'Histoire Eccl[é]{.nocase}siastique   id: angenendt   issued: 2002   language: de-DE
test/command/citeproc-87.md view
@@ -18,7 +18,7 @@ The Quoted is passed to citeproc as a Span ("",["csl-quoted"],[]) so that flipflopping and localization occur. ```-% pandoc -C -t plain -Mlang=en+% pandoc -C -t plain -Mlang=en --csl command/le-tapuscrit-note.csl --- references: - id: a@@ -30,13 +30,15 @@  Foo [@a 50]. ^D-Foo (Aristotele, n.d., 50).+Foo.[1] -Aristotele. n.d. “Metafisica Et ‘Physica’.”+ARISTOTELE, “Metafisica et ‘Physica’.”++[1] Aristotele, “Metafisica et ‘Physica’,” p. 50. ```  ```-% pandoc -C -t plain -Mlang=it+% pandoc -C -t plain -Mlang=it --csl command/le-tapuscrit-note.csl --- references: - id: a@@ -48,8 +50,10 @@  Foo [@a 50]. ^D-Foo (Aristotele, s.d., 50).+Foo.[1] -Aristotele. s.d. «Metafisica et “Physica”».+ARISTOTELE, «Metafisica et “Physica”».++[1] Aristotele, «Metafisica et “Physica”», p. 50. ``` 
test/command/lists-inside-definition.md view
@@ -33,6 +33,7 @@     2. list ^D \begin{description}+\tightlist \item[Definition] Foo 
test/command/macros.md view
@@ -61,9 +61,9 @@ ^D \(5-67\) -\[\begin{aligned}+\begin{align} x &= y\\-\end{aligned}\]+\end{align}  \emph{hi} 
test/command/pandoc-citeproc-118.md view
@@ -19,10 +19,9 @@ ^D (Hitchcock 1959) is a spy thriller film. -:::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+:::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-nbn .csl-entry}-Hitchcock, Alfred, dir. 1959. *North by Northwest*. USA:-Metro-Goldwyn-Mayer.+Hitchcock, Alfred, dir. 1959. *North by Northwest*. Metro-Goldwyn-Mayer. ::: :::: ```
test/command/pandoc-citeproc-136.md view
@@ -15,7 +15,7 @@ ^D *Stanze in lode della donna brutta* (1547) is an anoynymous work. -:::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+:::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-stanze .csl-entry} *Stanze in lode della donna brutta*. 1547. Florence. :::
test/command/pandoc-citeproc-14.md view
@@ -51,27 +51,27 @@ References {#references .unnumbered} ========== ^D-Foo (Pelikan 1971b, 1:12). Bar (Pelikan 1971c, 1:12). Baz (Pelikan-1971a, 12).+Foo (Pelikan 1971b, 1:12). Bar (Pelikan 1971c, 12). Baz (Pelikan 1971a,+12).  # References {#references .unnumbered} -:::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+:::::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-CTv1c2 .csl-entry}-Pelikan, Jaroslav. 1971a. "Chapter Two." In *The Christian Tradition: A-History of the Development of Doctrine*, 1:34--56. Chicago: University-of Chicago Press.+Pelikan, Jaroslav. 1971a. "Chapter Two." In *The Emergence of the+Catholic Tradition (100--600)*, vol. 1 of *The Christian Tradition: A+History of the Development of Doctrine*. University of Chicago Press. :::  ::: {#ref-CT .csl-entry}----------. 1971b. *The Christian Tradition: A History of the Development-of Doctrine*. Chicago: University of Chicago Press.+Pelikan, Jaroslav. 1971b. *The Christian Tradition: A History of the+Development of Doctrine*. University of Chicago Press. :::  ::: {#ref-CTv1 .csl-entry}----------. 1971c. *The Emergence of the Catholic Tradition (100--600)*.-*The Christian Tradition: A History of the Development of Doctrine*.-Vol. 1. Chicago: University of Chicago Press.+Pelikan, Jaroslav. 1971c. *The Emergence of the Catholic Tradition+(100--600)*. In *The Christian Tradition: A History of the Development+of Doctrine*, vol. 1. University of Chicago Press. ::: :::::: ```
test/command/pandoc-citeproc-175.md view
@@ -35,9 +35,9 @@  > Doe, Jane. 2011. "A Title." *A Magazine*, January--February. -:::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+:::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-item1 .csl-entry}-Doe, Jane. 2011. "A Title." *A Magazine*, January--February 2011.+Doe, Jane. 2011. "A Title." *A Magazine*, January--February, 33--44. ::: :::: ```
test/command/pandoc-citeproc-25.md view
@@ -22,9 +22,9 @@  # References {#references .unnumbered} -:::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+:::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-item1 .csl-entry}-Author, Al. 1998. "Foo Bar Baz: Bazbaz Foo."+Author, Al. 1998. *Foo Bar Baz: Bazbaz Foo*. ::: :::: ```
test/command/pandoc-citeproc-250.md view
@@ -13,9 +13,9 @@ ^D ([Doe, n.d.](#ref-doe)) -:::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+:::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-doe .csl-entry}-Doe. n.d. "Title."+Doe. n.d. *Title*. ::: :::: ```
test/command/pandoc-citeproc-301.md view
@@ -10,16 +10,16 @@  @test; @test2 ^D-"Essays Presented to N.R. Ker (On Art)" (n.d.); "*Test:* An Experiment:-An Abridgement" (n.d.)+*Essays Presented to N.R. Ker (On Art)* (n.d.); **Test:* An Experiment:+An Abridgement* (n.d.) -::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+::::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-test .csl-entry}-"Essays Presented to N.R. Ker (On Art)." n.d.+*Essays Presented to N.R. Ker (On Art)*. n.d. :::  ::: {#ref-test2 .csl-entry}-"*Test:* An Experiment: An Abridgement." n.d.+**Test:* An Experiment: An Abridgement*. n.d. ::: ::::: ```
test/command/pandoc-citeproc-307.md view
@@ -22,7 +22,7 @@ ^D Bonjour(Bazin 1954) ! -:::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+:::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-bazin_cybernetique_1954 .csl-entry} Bazin, André. 1954. « La Cybernétique d'André Cayatte ». *Cahiers du cinéma*, nᵒ 36 (juin): 22‑27.
test/command/pandoc-citeproc-320a.md view
@@ -61,17 +61,17 @@  Uch, Ann. 2000. -‘Udhrī, Jamīl al-. 2000. “Inverted Curly Apostrophe = Opening Single-Curly Quote (for Ayn).”+‘Udhrī, Jamīl al-. 2000. Inverted Curly Apostrophe = Opening Single+Curly Quote (for Ayn). -ʿUdhrī, Jamīl al-. 2000. “Ayn.”+ʿUdhrī, Jamīl al-. 2000. Ayn. -’Udhrī, Jamīl al-. 2000a. “Curly Apostrophe = Closing Single Curly Quote-(for Hamza).”+’Udhrī, Jamīl al-. 2000a. Curly Apostrophe = Closing Single Curly Quote+(for Hamza). -ʾUdhrī, Jamīl al-. 2000. “Hamza.”+ʾUdhrī, Jamīl al-. 2000. Hamza. -’Udhrī, Jamīl al-. 2000b. “Straight Apostrophe.”+’Udhrī, Jamīl al-. 2000b. Straight Apostrophe.  Uebel, Joe. 2000. 
test/command/pandoc-citeproc-325.md view
@@ -16,15 +16,15 @@  [@item1; @item2] ^D-(Smith, n.d.a, n.d.b)+(Smith, n.d.-a, n.d.-b) -::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+::::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-item1 .csl-entry}-Smith, John. n.d.a.+Smith, John. n.d.-a. :::  ::: {#ref-item2 .csl-entry}----------. n.d.b.+Smith, John. n.d.-b. ::: ::::: ```
test/command/pandoc-citeproc-327.md view
@@ -45,7 +45,7 @@ ::: {#ref-LiLiaoDongWanHaiYuDiQiDongWuCiJiShengChanLiYanJiuJiShengJingGuaYiXingPingJie2017 .csl-entry} [\[1\] ]{.csl-left-margin}[李轶平, 于旭光, 孙明, 等. [辽东湾海域底栖动物次级生产力研究及生境适宜性评价](http://kns.cnki.net/kns/detail/detail.aspx?QueryID=4&CurRec=4&recid=&FileName=CHAN201706006&DbName=CJFDLAST2018&DbCode=CJFQ&yx=Y&pr=&URLID=21.1110.S.20171129.1725.006)\[J\].-水产科学, 2017(6): 728--734.]{.csl-right-inline}+水产科学, 2017(6): 728~734.]{.csl-right-inline} ::: :::: ```
test/command/pandoc-citeproc-371.md view
@@ -28,13 +28,13 @@  # References {#references .unnumbered} -::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+::::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-item2 .csl-entry} Doe, Jane. 2018. *Title Two*. :::  ::: {#ref-item1 .csl-entry}----------. In press. *Title One*.+Doe, Jane. In press. *Title One*. ::: ::::: ```
test/command/pandoc-citeproc-38.md view
@@ -19,11 +19,11 @@  @a ^D-Doe, Doe, and Roe (2007)+Doe et al. (2007) -:::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+:::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-a .csl-entry}-Doe, Ann, Ben Doe, and Ron Roe. 2007. "Title."+Doe, Ann, Ben Doe, and Ron Roe. 2007. *Title*. ::: :::: ```
test/command/pandoc-citeproc-401.md view
@@ -43,17 +43,17 @@ ^D Haslanger (\[2003\] 2012, \[2000\] 2012) says... -::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+::::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-haslanger2012FeminismMetaphysicsNegotiating .csl-entry} Haslanger, Sally. (2000) 2012. "Feminism in Metaphysics: Negotiating the Natural." In *Resisting Reality: Social Construction and Social-Critique*, 139--57. Oxford: Oxford University Press.+Critique*. Oxford University Press. :::  ::: {#ref-haslanger2012SocialConstructionDebunking .csl-entry}----------. (2003) 2012. "Social Construction: The 'Debunking' Project."-In *Resisting Reality: Social Construction and Social Critique*,-113--38. Oxford: Oxford University Press.+Haslanger, Sally. (2003) 2012. "Social Construction: The 'Debunking'+Project." In *Resisting Reality: Social Construction and Social+Critique*. Oxford University Press. ::: ::::: ```
test/command/pandoc-citeproc-408.md view
@@ -27,13 +27,13 @@ ^D (Smith and Smith 2019; Smith 2019) -::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+::::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-smith1 .csl-entry}-Smith, Mary. 2019. "Foo."+Smith, Mary. 2019. *Foo*. :::  ::: {#ref-smithsmith .csl-entry}-Smith, Mary, and John Smith. 2019. "Foo Bar."+Smith, Mary, and John Smith. 2019. *Foo Bar*. ::: ::::: ```
test/command/pandoc-citeproc-416.md view
@@ -44,17 +44,17 @@  # References {#references .unnumbered} -:::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+:::::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-item2 .csl-entry}-Doe, J. 2007. "The Title," December 12--13, 2007.+Doe, J. 2007. *The Title*. December 12--13. :::  ::: {#ref-item3 .csl-entry}----------. 2008. "The Title," 2008.+Doe, J. 2008. *The Title*. :::  ::: {#ref-item1 .csl-entry}----------. 2010. "The Title," December 13, 2010.+Doe, J. 2010. *The Title*. December 13. ::: :::::: ```
test/command/pandoc-citeproc-47.md view
@@ -69,8 +69,8 @@ References {#references .unnumbered} ========== ^D-Foo (Doe 2000a). Bar (Doe and Poe 2000). Foo (Doe 2000b). Bar (Doe, Loe,-and Toe 2000).+Foo (Doe 2000a). Bar (Doe and Poe 2000). Foo (Doe 2000b). Bar (Doe et+al. 2000).  Expected output: @@ -92,13 +92,13 @@  # References {#references .unnumbered} -::::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+::::::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-doe .csl-entry} Doe, A. 2000a. *Title*. :::  ::: {#ref-doe-ed .csl-entry}----------, ed. 2000b. *Title*.+Doe, A., ed. 2000b. *Title*. :::  ::: {#ref-doeloetoe .csl-entry}
test/command/pandoc-citeproc-51.md view
@@ -33,7 +33,7 @@ ^D Doe (1987--1988); Roe (1987) -::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+::::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-item1 .csl-entry} Doe, John. 1987--1988. "The Title." *Journal of Something* 3: 12--34. :::
test/command/pandoc-citeproc-64.md view
@@ -1,5 +1,5 @@ ```-% pandoc --citeproc -t markdown-citations+% pandoc --citeproc -t markdown-citations --csl command/chicago-fullnote-bibliography.csl --- bibliography: - command/biblio.bib@@ -8,17 +8,17 @@  ^D :::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}-::: {#ref-item1 .csl-entry}-Doe, John. 2005. *First Book*. Cambridge: Cambridge University Press.+::: {#ref-item2 .csl-entry}+Doe, John. "Article." *Journal of Generic Studies* 6 (2006): 33--34. ::: -::: {#ref-item2 .csl-entry}----------. 2006. "Article." *Journal of Generic Studies* 6: 33--34.+::: {#ref-item1 .csl-entry}+---------. *First Book*. Cambridge: Cambridge University Press, 2005. :::  ::: {#ref-пункт3 .csl-entry}-Doe, John, and Jenny Roe. 2007. "Why Water Is Wet." In *Third Book*,-edited by Sam Smith. Oxford: Oxford University Press.+Doe, John, and Jenny Roe. "Why Water Is Wet." In *Third Book*, edited by+Sam Smith. Oxford: Oxford University Press, 2007. ::: :::::: ```
test/command/pandoc-citeproc-65.md view
@@ -28,11 +28,10 @@ ^D (Stotz 1996--2004) -:::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+:::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-stotz:1996handbuch .csl-entry} Stotz, Peter. 1996--2004. *Handbuch zur lateinischen Sprache des-Mittelalters*. 5 vols. Handbuch der Altertumswissenschaft 2.5. Munich:-Beck.+Mittelalters*. 5 vols. Handbuch der Altertumswissenschaft, 2.5. Beck. ::: :::: ```
test/command/pandoc-citeproc-7.md view
@@ -23,9 +23,9 @@ ^D Author (2011) -:::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+:::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-item1 .csl-entry}-Author, Ann. 2011. "Title." *Journal*, September 24--26, 2011.+Author, Ann. 2011. "Title." *Journal*, September 24--26. ::: :::: ```
test/command/pandoc-citeproc-70.md view
@@ -56,14 +56,14 @@ ^D (Thorndike 1955; Dinkova-Bruun 2009) -::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+::::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-bruun:2009samuel .csl-entry} Dinkova-Bruun, Greti. 2009. "Samuel Presbyter and the Glosses to His Versification of Psalm 1: An Anti-Church Invective?" In *Florilegium mediaevale: Études offertes à Jacqueline Hamesse à l'occasion de son-éméritat*, edited by José Francisco Meirinhos and Olga Weijers, 155--74.-Textes et études du moyen âge 50. Louvain-la-Neuve: Fédération-Internationale des Instituts d'Études Médiévales.+éméritat*, edited by José Francisco Meirinhos and Olga Weijers. Textes+et études du moyen âge 50. Fédération Internationale des Instituts+d'Études Médiévales. :::  ::: {#ref-thorndike:1955unde .csl-entry}
test/command/pandoc-citeproc-76.md view
@@ -44,21 +44,21 @@ ^D Author (1998c), Author (1998d), Author (1998a), Author (1998b) -::::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+::::::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-item3 .csl-entry}-Author, Al. 1998a. "Foo Bar Baz: A Bazbaz Bar Foo."+Author, Al. 1998a. *Foo Bar Baz: A Bazbaz Bar Foo*. :::  ::: {#ref-item4 .csl-entry}----------. 1998b. "Foo Bar Baz: An Abazbaz Bar Foo."+Author, Al. 1998b. *Foo Bar Baz: An Abazbaz Bar Foo*. :::  ::: {#ref-item1 .csl-entry}----------. 1998c. "Foo Bar Baz: Bazbaz Bar Foo."+Author, Al. 1998c. *Foo Bar Baz: Bazbaz Bar Foo*. :::  ::: {#ref-item2 .csl-entry}----------. 1998d. "Foo Bar Baz: The Bazbaz Bar Foo."+Author, Al. 1998d. *Foo Bar Baz: The Bazbaz Bar Foo*. ::: ::::::: ```
test/command/pandoc-citeproc-87.md view
@@ -108,49 +108,49 @@ References ========== ^D-Doe (2006c) -- webpage, date+Doe (2006a) -- webpage, date -Doe (2006d) -- webpage, date range+Doe (2006c) -- webpage, date range -Doe (2006a) -- webpage, date range YM+Doe (2006b) -- webpage, date range YM  Doe (2006--2007) -- webpage, date range across years  Doe (2006e) -- article-newspaper -Doe (2006b) -- article-newspaper YM+Doe (2006d) -- article-newspaper YM  # References {#references .unnumbered} -::::::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}-::: {#ref-item2a .csl-entry}-Doe, John. 2006a. "Title." The Web Site. October--November 2006.+::::::::: {#refs .references .csl-bib-body .hanging-indent}+::: {#ref-item1 .csl-entry}+Doe, John. 2006a. "Title." The Web Site, October 26. <http://www.example.com>. ::: -::: {#ref-item3b .csl-entry}----------. 2006b. "Title." *The Newspaper*, October--November 2006.+::: {#ref-item2a .csl-entry}+Doe, John. 2006b. "Title." The Web Site, October--November. <http://www.example.com>. ::: -::: {#ref-item1 .csl-entry}----------. 2006c. "Title." The Web Site. October 26, 2006.+::: {#ref-item2 .csl-entry}+Doe, John. 2006c. "Title." The Web Site, October 26--November 27. <http://www.example.com>. ::: -::: {#ref-item2 .csl-entry}----------. 2006d. "Title." The Web Site. October 26--November 27, 2006.+::: {#ref-item3b .csl-entry}+Doe, John. 2006d. "Title." *The Newspaper*, October--November. <http://www.example.com>. :::  ::: {#ref-item3 .csl-entry}----------. 2006e. "Title." *The Newspaper*, October 26--November 27,-2006. <http://www.example.com>.+Doe, John. 2006e. "Title." *The Newspaper*, October 26--November 27.+<http://www.example.com>. :::  ::: {#ref-item2b .csl-entry}----------. 2006--2007. "Title." The Web Site. December 31, 2006--January-1, 2007. <http://www.example.com>.+Doe, John. 2006--2007. "Title." The Web Site, December 31--January 1.+<http://www.example.com>. ::: ::::::::: ```
test/command/pandoc-citeproc-chicago-author-date.md view
@@ -83,18 +83,18 @@  # References {#references .unnumbered} -:::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+:::::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-item1 .csl-entry}-Doe, John. 2005. *First Book*. Cambridge: Cambridge University Press.+Doe, John. 2005. *First Book*. Cambridge University Press. :::  ::: {#ref-item2 .csl-entry}----------. 2006. "Article." *Journal of Generic Studies* 6: 33--34.+Doe, John. 2006. "Article." *Journal of Generic Studies* 6: 33--34. :::  ::: {#ref-пункт3 .csl-entry} Doe, John, and Jenny Roe. 2007. "Why Water Is Wet." In *Third Book*,-edited by Sam Smith. Oxford: Oxford University Press.+edited by Sam Smith. Oxford University Press. ::: :::::: 
test/command/pandoc-citeproc-no-author.md view
@@ -45,29 +45,29 @@ *Magazine* (2012a, 3), *Magazine* (2012b), *Magazine* (2012c), *Magazine* (2012d), *Newspaper* (2012a), *Newspaper* (2012b) -::::::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+::::::::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-item1 .csl-entry}-*Magazine*. 2012a. "Title A," 2012.+*Magazine*. 2012a. "Title A." :::  ::: {#ref-item2 .csl-entry}----------. 2012b. "Title B," 2012.+*Magazine*. 2012b. "Title B." :::  ::: {#ref-item3 .csl-entry}----------. 2012c. "Title C," 2012.+*Magazine*. 2012c. "Title C." :::  ::: {#ref-item4 .csl-entry}----------. 2012d. "Title D," 2012.+*Magazine*. 2012d. "Title D." :::  ::: {#ref-item5 .csl-entry}-*Newspaper*. 2012a. "Title E," 2012.+*Newspaper*. 2012a. "Title E." :::  ::: {#ref-item6 .csl-entry}----------. 2012b. "Title F," 2012.+*Newspaper*. 2012b. "Title F." ::: ::::::::: ```
test/command/pandoc-citeproc-number-of-volumes.md view
@@ -21,9 +21,9 @@ ^D Author (2013) -:::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+:::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-item1 .csl-entry}-Author, Al. 2013. *Title*. 2 vols. Location: Publisher.+Author, Al. 2013. *Title*. 2 vols. Publisher. ::: :::: ```
test/command/refs.md view
@@ -118,7 +118,7 @@ , Para     [ Math         DisplayMath-        "\\label{eq:Accuracy}\n  Accuracy = \\frac{t_p + t_n}{t_p + f_p + f_n + t_n}"+        "\\begin{equation}\n  \\label{eq:Accuracy}\n  Accuracy = \\frac{t_p + t_n}{t_p + f_p + f_n + t_n}\n\\end{equation}"     ] ] ```
test/docbook-reader.docbook view
@@ -405,8 +405,8 @@   </sect2>   <sect2 id="fancy-list-markers">     <title>Fancy list markers</title>-    <orderedlist numeration="arabic">-      <listitem override="2">+    <orderedlist numeration="arabic" startingnumber="2">+      <listitem>         <para>           begins with 2         </para>@@ -418,8 +418,8 @@         <para>           with a continuation         </para>-        <orderedlist numeration="lowerroman">-          <listitem override="4">+        <orderedlist numeration="lowerroman" startingnumber="4">+          <listitem>             <para>               sublist with roman numerals, starting with 4             </para>@@ -457,13 +457,13 @@             <para>               Upper Roman.             </para>-            <orderedlist numeration="arabic">-              <listitem override="6">+            <orderedlist numeration="arabic" startingnumber="6">+              <listitem>                 <para>                   Decimal start with 6                 </para>-                <orderedlist numeration="loweralpha">-                  <listitem override="3">+                <orderedlist numeration="loweralpha" startingnumber="3">+                  <listitem>                     <para>                       Lower alpha with paren                     </para>@@ -1624,6 +1624,39 @@             Here's another one. Note the blank line between rows.           </entry>         </row>+      </tbody>+    </tgroup>+  </informaltable>+  <para>+    Multiline table with cells spanning multiple columns and rows without caption.+  </para>+  <informaltable>+    <tgroup cols="3">+      <colspec align="left" colname="c1" />+      <colspec align="left" colname="c2" />+      <colspec align="left" colname="c3" />+      <colspec align="left" colname="c4" />+      <thead>+  <tr>+    <th namest="c1" nameend="c3">Columns</th>+  </tr>+  <tr>+    <th>A</th>+    <th>B</th>+    <th>C</th>+  </tr>+      </thead>+      <tbody>+	<tr>+	  <td namest="c1" nameend="c2">A1 + B1</td>+	  <td morerows="1">C1 + C2</td>+	</tr>+  <tr>+	  <td namest="c1" nameend="c2" morerows="1">A2 + B2 + A3 + B3</td>+	</tr>+  <tr>+	  <td>C3</td>+	</tr>       </tbody>     </tgroup>   </informaltable>
test/docbook-reader.native view
@@ -3046,6 +3046,128 @@           ]       ]       (TableFoot ( "" , [] , [] ) [])+  , Para+      [ Str "Multiline"+      , Space+      , Str "table"+      , Space+      , Str "with"+      , Space+      , Str "cells"+      , Space+      , Str "spanning"+      , Space+      , Str "multiple"+      , Space+      , Str "columns"+      , Space+      , Str "and"+      , Space+      , Str "rows"+      , Space+      , Str "without"+      , Space+      , Str "caption."+      ]+  , Table+      ( "" , [] , [] )+      (Caption Nothing [])+      [ ( AlignLeft , ColWidthDefault )+      , ( AlignLeft , ColWidthDefault )+      , ( AlignLeft , ColWidthDefault )+      ]+      (TableHead+         ( "" , [] , [] )+         [ Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 3)+                 [ Plain [ Str "Columns" ] ]+             ]+         , Row+             ( "" , [] , [] )+             [ Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Plain [ Str "A" ] ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Plain [ Str "B" ] ]+             , Cell+                 ( "" , [] , [] )+                 AlignDefault+                 (RowSpan 1)+                 (ColSpan 1)+                 [ Plain [ Str "C" ] ]+             ]+         ])+      [ TableBody+          ( "" , [] , [] )+          (RowHeadColumns 0)+          []+          [ Row+              ( "" , [] , [] )+              [ Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 2)+                  [ Plain+                      [ Str "A1" , Space , Str "+" , Space , Str "B1" ]+                  ]+              , Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 2)+                  (ColSpan 1)+                  [ Plain+                      [ Str "C1" , Space , Str "+" , Space , Str "C2" ]+                  ]+              ]+          , Row+              ( "" , [] , [] )+              [ Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 2)+                  (ColSpan 2)+                  [ Plain+                      [ Str "A2"+                      , Space+                      , Str "+"+                      , Space+                      , Str "B2"+                      , Space+                      , Str "+"+                      , Space+                      , Str "A3"+                      , Space+                      , Str "+"+                      , Space+                      , Str "B3"+                      ]+                  ]+              ]+          , Row+              ( "" , [] , [] )+              [ Cell+                  ( "" , [] , [] )+                  AlignDefault+                  (RowSpan 1)+                  (ColSpan 1)+                  [ Plain [ Str "C3" ] ]+              ]+          ]+      ]+      (TableFoot ( "" , [] , [] ) [])   , OrderedList       ( 1 , DefaultStyle , DefaultDelim )       [ [ Para [ Str "A" , Space , Str "Step" ] ]
test/docx/golden/block_quotes.docx view

binary file changed (10689 → 10692 bytes)

test/docx/golden/codeblock.docx view

binary file changed (10507 → 10510 bytes)

test/docx/golden/comments.docx view

binary file changed (10838 → 10841 bytes)

test/docx/golden/custom_style_no_reference.docx view

binary file changed (10609 → 10609 bytes)

test/docx/golden/custom_style_preserve.docx view

binary file changed (11235 → 11236 bytes)

test/docx/golden/definition_list.docx view

binary file changed (10498 → 10501 bytes)

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

binary file changed (10512 → 10515 bytes)

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

binary file changed (10997 → 11000 bytes)

test/docx/golden/headers.docx view

binary file changed (10652 → 10655 bytes)

test/docx/golden/image.docx view

binary file changed (27380 → 27383 bytes)

test/docx/golden/inline_code.docx view

binary file changed (10448 → 10451 bytes)

test/docx/golden/inline_formatting.docx view

binary file changed (10624 → 10627 bytes)

test/docx/golden/inline_images.docx view

binary file changed (27380 → 27383 bytes)

binary file changed (10661 → 10664 bytes)

test/docx/golden/links.docx view

binary file changed (10839 → 10842 bytes)

test/docx/golden/lists.docx view

binary file changed (11031 → 11034 bytes)

test/docx/golden/lists_9994.docx view

binary file changed (10785 → 10788 bytes)

test/docx/golden/lists_continuing.docx view

binary file changed (10699 → 10702 bytes)

test/docx/golden/lists_div_bullets.docx view

binary file changed (10682 → 10685 bytes)

test/docx/golden/lists_multiple_initial.docx view

binary file changed (10915 → 10918 bytes)

test/docx/golden/lists_restarting.docx view

binary file changed (10696 → 10699 bytes)

test/docx/golden/nested_anchors_in_header.docx view

binary file changed (10842 → 10845 bytes)

test/docx/golden/notes.docx view

binary file changed (10612 → 10615 bytes)

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

binary file changed (10541 → 10544 bytes)

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

binary file changed (10680 → 10683 bytes)

test/docx/golden/table_one_row.docx view

binary file changed (10519 → 10522 bytes)

test/docx/golden/table_with_list_cell.docx view

binary file changed (10969 → 10972 bytes)

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

binary file changed (10879 → 10882 bytes)

test/docx/golden/tables.docx view

binary file changed (10893 → 10896 bytes)

test/docx/golden/tables_separated_with_rawblock.docx view

binary file changed (10516 → 10519 bytes)

test/docx/golden/task_list.docx view

binary file changed (10780 → 10783 bytes)

test/docx/golden/track_changes_deletion.docx view

binary file changed (10489 → 10492 bytes)

test/docx/golden/track_changes_insertion.docx view

binary file changed (10473 → 10476 bytes)

test/docx/golden/track_changes_move.docx view

binary file changed (10503 → 10506 bytes)

test/docx/golden/track_changes_scrubbed_metadata.docx view

binary file changed (10614 → 10617 bytes)

test/docx/golden/unicode.docx view

binary file changed (10465 → 10468 bytes)

test/docx/golden/verbatim_subsuper.docx view

binary file changed (10476 → 10479 bytes)

test/man-reader.man view
@@ -1,4 +1,4 @@-.TH "Pandoc Man tests" "" "Oct 17, 2018" "" ""+.TH "PANDOC-MAN-TESTS" "1" "Oct 17, 2018" "v1.0.1" "Pandoc Tests" .PP This is a set of tests for pandoc. .PP
test/man-reader.native view
@@ -6,16 +6,12 @@             , MetaInlines                 [ Str "Oct" , Space , Str "17," , Space , Str "2018" ]             )-          , ( "section" , MetaInlines [] )-          , ( "title"-            , MetaInlines-                [ Str "Pandoc"-                , Space-                , Str "Man"-                , Space-                , Str "tests"-                ]+          , ( "footer" , MetaInlines [ Str "v1.0.1" ] )+          , ( "header"+            , MetaInlines [ Str "Pandoc" , Space , Str "Tests" ]             )+          , ( "section" , MetaInlines [ Str "1" ] )+          , ( "title" , MetaInlines [ Str "PANDOC-MAN-TESTS" ] )           ]     }   [ Para
test/odt/native/simpleTable.native view
@@ -1,1 +1,1 @@-[Table ("",[],[]) (Caption Nothing []) [(AlignDefault,ColWidthDefault),(AlignDefault,ColWidthDefault)] (TableHead ("",[],[]) [Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [],Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) []]]) [TableBody ("",[],[]) (RowHeadColumns 0) [] [Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Content"]],Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "More",Space,Str "content"]]]]] (TableFoot ("",[],[]) []),Para []]+[Table ("",[],[]) (Caption Nothing []) [(AlignDefault,ColWidthDefault),(AlignDefault,ColWidthDefault)] (TableHead ("",[],[]) []) [TableBody ("",[],[]) (RowHeadColumns 0) [] [Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Content"]],Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "More",Space,Str "content"]]]]] (TableFoot ("",[],[]) []),Para []]
test/odt/native/simpleTableWithCaption.native view
@@ -1,1 +1,1 @@-[Table ("",[],[]) (Caption Nothing [Para [Str "Table",Space,Str "1:",Space,Str "Some",Space,Str "caption",Space,Str "for",Space,Str "a",Space,Str "table"]]) [(AlignDefault,ColWidthDefault),(AlignDefault,ColWidthDefault)] (TableHead ("",[],[]) [Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [],Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) []]]) [TableBody ("",[],[]) (RowHeadColumns 0) [] [Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Content"]],Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "More",Space,Str "content"]]]]] (TableFoot ("",[],[]) []),Para []]+[Table ("",[],[]) (Caption Nothing [Para [Str "Table",Space,Str "1:",Space,Str "Some",Space,Str "caption",Space,Str "for",Space,Str "a",Space,Str "table"]]) [(AlignDefault,ColWidthDefault),(AlignDefault,ColWidthDefault)] (TableHead ("",[],[]) []) [TableBody ("",[],[]) (RowHeadColumns 0) [] [Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Content"]],Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "More",Space,Str "content"]]]]] (TableFoot ("",[],[]) []),Para []]
+ test/odt/native/simpleTableWithHeader.native view
@@ -0,0 +1,79 @@+[ Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "A" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "B" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "C" ] ]+           ]+       ])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [ Plain [] ]+            , Cell+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [ Plain [] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "2" ] ]+            , Cell+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [ Plain [] ]+            , Cell+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [ Plain [] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "3" ] ]+            , Cell+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [ Plain [] ]+            , Cell+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [ Plain [] ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+, Para []+]
+ test/odt/native/simpleTableWithMultipleHeaderRows.native view
@@ -0,0 +1,125 @@+[ Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "A" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "B" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "C" ] ]+           ]+       , Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "I" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "II" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "II" ] ]+           ]+       ])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "2" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [] ]+            ]+        , Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "3" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [] ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+, Para []+]+
test/odt/native/tableWithContents.native view
@@ -1,1 +1,1 @@-[Table ("",[],[]) (Caption Nothing []) [(AlignDefault,ColWidthDefault),(AlignDefault,ColWidthDefault)] (TableHead ("",[],[]) [Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [],Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) []]]) [TableBody ("",[],[]) (RowHeadColumns 0) [] [Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "A"]],Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "B"]]],Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "C"]],Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "D"]]]]] (TableFoot ("",[],[]) []),Para []]+[Table ("",[],[]) (Caption Nothing []) [(AlignDefault,ColWidthDefault),(AlignDefault,ColWidthDefault)] (TableHead ("",[],[]) []) [TableBody ("",[],[]) (RowHeadColumns 0) [] [Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "A"]],Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "B"]]],Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "C"]],Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "D"]]]]] (TableFoot ("",[],[]) []),Para []]
+ test/odt/odt/simpleTableWithHeader.odt view

binary file changed (absent → 10377 bytes)

+ test/odt/odt/simpleTableWithMultipleHeaderRows.odt view

binary file changed (absent → 10173 bytes)

test/s5-basic.html view
@@ -11,6 +11,9 @@   <meta name="date" content="2006-07-15" />   <title>My S5 Document</title>   <style type="text/css">+    /* Default styles provided by pandoc.+    ** See https://pandoc.org/MANUAL.html#variables-for-html for config info.+    */     code{white-space: pre-wrap;}     span.smallcaps{font-variant: small-caps;}     div.columns{display: flex; gap: min(4vw, 1.5em);}
test/s5-fancy.html view
@@ -11,6 +11,9 @@   <meta name="date" content="2006-07-15" />   <title>My S5 Document</title>   <style type="text/css">+    /* Default styles provided by pandoc.+    ** See https://pandoc.org/MANUAL.html#variables-for-html for config info.+    */     code{white-space: pre-wrap;}     span.smallcaps{font-variant: small-caps;}     div.columns{display: flex; gap: min(4vw, 1.5em);}
test/s5-inserts.html view
@@ -9,6 +9,9 @@   <meta name="date" content="2006-07-15" />   <title>My S5 Document</title>   <style type="text/css">+    /* Default styles provided by pandoc.+    ** See https://pandoc.org/MANUAL.html#variables-for-html for config info.+    */     code{white-space: pre-wrap;}     span.smallcaps{font-variant: small-caps;}     div.columns{display: flex; gap: min(4vw, 1.5em);}
test/test-pandoc.hs view
@@ -1,6 +1,4 @@-{-# OPTIONS_GHC -Wall #-}--module Main where+module Main (main) where  import System.Environment (getArgs, getExecutablePath) import qualified Control.Exception as E@@ -52,6 +50,7 @@ import qualified Tests.Writers.AnnotatedTable import qualified Tests.Writers.TEI import qualified Tests.Writers.Markua+import qualified Tests.XML import qualified Tests.MediaBag import Text.Pandoc.Shared (inDirectory) @@ -61,6 +60,7 @@         , testGroup "Old" (Tests.Old.tests pandocPath)         , testGroup "Shared" Tests.Shared.tests         , testGroup "MediaBag" Tests.MediaBag.tests+        , testGroup "XML" Tests.XML.tests         , testGroup "Writers"           [ testGroup "Native" Tests.Writers.Native.tests           , testGroup "ConTeXt" Tests.Writers.ConTeXt.tests
test/writer.docbook4 view
@@ -512,8 +512,8 @@     </sect2>     <sect2 id="fancy-list-markers">       <title>Fancy list markers</title>-      <orderedlist numeration="arabic">-        <listitem override="2">+      <orderedlist numeration="arabic" startingnumber="2">+        <listitem>           <para>             begins with 2           </para>@@ -525,8 +525,8 @@           <para>             with a continuation           </para>-          <orderedlist numeration="lowerroman" spacing="compact">-            <listitem override="4">+          <orderedlist numeration="lowerroman" spacing="compact" startingnumber="4">+            <listitem>               <para>                 sublist with roman numerals, starting with 4               </para>@@ -564,13 +564,13 @@               <para>                 Upper Roman.               </para>-              <orderedlist numeration="arabic" spacing="compact">-                <listitem override="6">+              <orderedlist numeration="arabic" spacing="compact" startingnumber="6">+                <listitem>                   <para>                     Decimal start with 6                   </para>-                  <orderedlist numeration="loweralpha" spacing="compact">-                    <listitem override="3">+                  <orderedlist numeration="loweralpha" spacing="compact" startingnumber="3">+                    <listitem>                       <para>                         Lower alpha with paren                       </para>
test/writer.docbook5 view
@@ -514,8 +514,8 @@     </section>     <section xml:id="fancy-list-markers">       <title>Fancy list markers</title>-      <orderedlist numeration="arabic">-        <listitem override="2">+      <orderedlist numeration="arabic" startingnumber="2">+        <listitem>           <para>             begins with 2           </para>@@ -527,8 +527,8 @@           <para>             with a continuation           </para>-          <orderedlist numeration="lowerroman" spacing="compact">-            <listitem override="4">+          <orderedlist numeration="lowerroman" spacing="compact" startingnumber="4">+            <listitem>               <para>                 sublist with roman numerals, starting with 4               </para>@@ -566,13 +566,13 @@               <para>                 Upper Roman.               </para>-              <orderedlist numeration="arabic" spacing="compact">-                <listitem override="6">+              <orderedlist numeration="arabic" spacing="compact" startingnumber="6">+                <listitem>                   <para>                     Decimal start with 6                   </para>-                  <orderedlist numeration="loweralpha" spacing="compact">-                    <listitem override="3">+                  <orderedlist numeration="loweralpha" spacing="compact" startingnumber="3">+                    <listitem>                       <para>                         Lower alpha with paren                       </para>
test/writer.html4 view
@@ -9,6 +9,9 @@   <meta name="date" content="2006-07-17" />   <title>Pandoc Test Suite</title>   <style type="text/css">+    /* Default styles provided by pandoc.+    ** See https://pandoc.org/MANUAL.html#variables-for-html for config info.+    */     html {       color: #1a1a1a;       background-color: #fdfdfd;
test/writer.html5 view
@@ -9,6 +9,9 @@   <meta name="dcterms.date" content="2006-07-17" />   <title>Pandoc Test Suite</title>   <style>+    /* Default styles provided by pandoc.+    ** See https://pandoc.org/MANUAL.html#variables-for-html for config info.+    */     html {       color: #1a1a1a;       background-color: #fdfdfd;
test/writer.jats_archiving view
@@ -687,7 +687,7 @@     <list-item>       <p>Here’s some display math: <disp-formula><alternatives>       <tex-math><![CDATA[\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}]]></tex-math>-      <mml:math display="block" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mfrac><mml:mi>d</mml:mi><mml:mrow><mml:mi>d</mml:mi><mml:mi>x</mml:mi></mml:mrow></mml:mfrac><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo><mml:mo>=</mml:mo><mml:munder><mml:mi>lim</mml:mi><mml:mrow><mml:mi>h</mml:mi><mml:mo>→</mml:mo><mml:mn>0</mml:mn></mml:mrow></mml:munder><mml:mfrac><mml:mrow><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo>+</mml:mo><mml:mi>h</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo><mml:mo>−</mml:mo><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo></mml:mrow><mml:mi>h</mml:mi></mml:mfrac></mml:mrow></mml:math></alternatives></disp-formula></p>+      <mml:math display="block" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mfrac><mml:mi>d</mml:mi><mml:mrow><mml:mi>d</mml:mi><mml:mi>x</mml:mi></mml:mrow></mml:mfrac><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo><mml:mo>=</mml:mo><mml:munder><mml:mi mathvariant="normal">lim</mml:mi><mml:mrow><mml:mi>h</mml:mi><mml:mo>→</mml:mo><mml:mn>0</mml:mn></mml:mrow></mml:munder><mml:mfrac><mml:mrow><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo>+</mml:mo><mml:mi>h</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo><mml:mo>−</mml:mo><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo></mml:mrow><mml:mi>h</mml:mi></mml:mfrac></mml:mrow></mml:math></alternatives></disp-formula></p>     </list-item>     <list-item>       <p>Here’s one that has a line break in it: <inline-formula><alternatives>
test/writer.jats_articleauthoring view
@@ -673,7 +673,7 @@     </list-item>     <list-item>       <p>Here’s some display math:-      <disp-formula><mml:math display="block" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mfrac><mml:mi>d</mml:mi><mml:mrow><mml:mi>d</mml:mi><mml:mi>x</mml:mi></mml:mrow></mml:mfrac><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo><mml:mo>=</mml:mo><mml:munder><mml:mi>lim</mml:mi><mml:mrow><mml:mi>h</mml:mi><mml:mo>→</mml:mo><mml:mn>0</mml:mn></mml:mrow></mml:munder><mml:mfrac><mml:mrow><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo>+</mml:mo><mml:mi>h</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo><mml:mo>−</mml:mo><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo></mml:mrow><mml:mi>h</mml:mi></mml:mfrac></mml:mrow></mml:math></disp-formula></p>+      <disp-formula><mml:math display="block" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mfrac><mml:mi>d</mml:mi><mml:mrow><mml:mi>d</mml:mi><mml:mi>x</mml:mi></mml:mrow></mml:mfrac><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo><mml:mo>=</mml:mo><mml:munder><mml:mi mathvariant="normal">lim</mml:mi><mml:mrow><mml:mi>h</mml:mi><mml:mo>→</mml:mo><mml:mn>0</mml:mn></mml:mrow></mml:munder><mml:mfrac><mml:mrow><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo>+</mml:mo><mml:mi>h</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo><mml:mo>−</mml:mo><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo></mml:mrow><mml:mi>h</mml:mi></mml:mfrac></mml:mrow></mml:math></disp-formula></p>     </list-item>     <list-item>       <p>Here’s one that has a line break in it:
test/writer.jats_publishing view
@@ -687,7 +687,7 @@     <list-item>       <p>Here’s some display math: <disp-formula><alternatives>       <tex-math><![CDATA[\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}]]></tex-math>-      <mml:math display="block" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mfrac><mml:mi>d</mml:mi><mml:mrow><mml:mi>d</mml:mi><mml:mi>x</mml:mi></mml:mrow></mml:mfrac><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo><mml:mo>=</mml:mo><mml:munder><mml:mi>lim</mml:mi><mml:mrow><mml:mi>h</mml:mi><mml:mo>→</mml:mo><mml:mn>0</mml:mn></mml:mrow></mml:munder><mml:mfrac><mml:mrow><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo>+</mml:mo><mml:mi>h</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo><mml:mo>−</mml:mo><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo></mml:mrow><mml:mi>h</mml:mi></mml:mfrac></mml:mrow></mml:math></alternatives></disp-formula></p>+      <mml:math display="block" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mfrac><mml:mi>d</mml:mi><mml:mrow><mml:mi>d</mml:mi><mml:mi>x</mml:mi></mml:mrow></mml:mfrac><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo><mml:mo>=</mml:mo><mml:munder><mml:mi mathvariant="normal">lim</mml:mi><mml:mrow><mml:mi>h</mml:mi><mml:mo>→</mml:mo><mml:mn>0</mml:mn></mml:mrow></mml:munder><mml:mfrac><mml:mrow><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo>+</mml:mo><mml:mi>h</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo><mml:mo>−</mml:mo><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo></mml:mrow><mml:mi>h</mml:mi></mml:mfrac></mml:mrow></mml:math></alternatives></disp-formula></p>     </list-item>     <list-item>       <p>Here’s one that has a line break in it: <inline-formula><alternatives>
test/writer.markdown view
@@ -353,33 +353,23 @@  Simple block on one line: -<div>-+::: {} foo--</div>+:::  And nested without indentation: -<div>--<div>--<div>-+:::::: {}+:::: {}+::: {} foo--</div>--</div>--<div>+:::+:::: +::: {} bar--</div>--</div>+:::+::::::  Interpreted markdown in a table: @@ -397,11 +387,9 @@  Here's a simple block: -<div>-+::: {} foo--</div>+:::  This should be a code block, though: @@ -415,19 +403,13 @@  Now, nested: -<div>--<div>--<div>-+::::: {}+:::: {}+::: {} foo--</div>--</div>--</div>+:::+::::+:::::  This should just be an HTML comment: 
test/writer.markua view
@@ -317,17 +317,17 @@  : red fruit -    contains seeds, crisp, pleasant to taste+  contains seeds, crisp, pleasant to taste  *orange*  : orange fruit -    ```-    { orange code block }-    ```+  ```+  { orange code block }+  ``` -    > orange block quote+  > orange block quote  Multiple definitions, tight: @@ -365,8 +365,8 @@  : orange fruit -    1. sublist-    2. sublist+  1. sublist+  2. sublist  {id: html-blocks} # HTML Blocks
test/writer.opml view
@@ -44,7 +44,7 @@ </outline> <outline text="Definition Lists" _note="Tight using spaces:&#10;&#10;apple&#10;:   red fruit&#10;&#10;orange&#10;:   orange fruit&#10;&#10;banana&#10;:   yellow fruit&#10;&#10;Tight using tabs:&#10;&#10;apple&#10;:   red fruit&#10;&#10;orange&#10;:   orange fruit&#10;&#10;banana&#10;:   yellow fruit&#10;&#10;Loose:&#10;&#10;apple&#10;&#10;:   red fruit&#10;&#10;orange&#10;&#10;:   orange fruit&#10;&#10;banana&#10;&#10;:   yellow fruit&#10;&#10;Multiple blocks with italics:&#10;&#10;*apple*&#10;&#10;:   red fruit&#10;&#10;    contains seeds, crisp, pleasant to taste&#10;&#10;*orange*&#10;&#10;:   orange fruit&#10;&#10;        { orange code block }&#10;&#10;    &gt; orange block quote&#10;&#10;Multiple definitions, tight:&#10;&#10;apple&#10;:   red fruit&#10;:   computer&#10;&#10;orange&#10;:   orange fruit&#10;:   bank&#10;&#10;Multiple definitions, loose:&#10;&#10;apple&#10;&#10;:   red fruit&#10;&#10;:   computer&#10;&#10;orange&#10;&#10;:   orange fruit&#10;&#10;:   bank&#10;&#10;Blank line after term, indented marker, alternate markers:&#10;&#10;apple&#10;&#10;:   red fruit&#10;&#10;:   computer&#10;&#10;orange&#10;&#10;:   orange fruit&#10;&#10;    1.  sublist&#10;    2.  sublist"> </outline>-<outline text="HTML Blocks" _note="Simple block on one line:&#10;&#10;&lt;div&gt;&#10;&#10;foo&#10;&#10;&lt;/div&gt;&#10;&#10;And nested without indentation:&#10;&#10;&lt;div&gt;&#10;&#10;&lt;div&gt;&#10;&#10;&lt;div&gt;&#10;&#10;foo&#10;&#10;&lt;/div&gt;&#10;&#10;&lt;/div&gt;&#10;&#10;&lt;div&gt;&#10;&#10;bar&#10;&#10;&lt;/div&gt;&#10;&#10;&lt;/div&gt;&#10;&#10;Interpreted markdown in a table:&#10;&#10;&lt;table&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;&#10;This is *emphasized*&#10;&lt;/td&gt;&#10;&lt;td&gt;&#10;And this is **strong**&#10;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/table&gt;&#10;&lt;script type=&quot;text/javascript&quot;&gt;document.write('This *should not* be interpreted as markdown');&lt;/script&gt;&#10;&#10;Here's a simple block:&#10;&#10;&lt;div&gt;&#10;&#10;foo&#10;&#10;&lt;/div&gt;&#10;&#10;This should be a code block, though:&#10;&#10;    &lt;div&gt;&#10;        foo&#10;    &lt;/div&gt;&#10;&#10;As should this:&#10;&#10;    &lt;div&gt;foo&lt;/div&gt;&#10;&#10;Now, nested:&#10;&#10;&lt;div&gt;&#10;&#10;&lt;div&gt;&#10;&#10;&lt;div&gt;&#10;&#10;foo&#10;&#10;&lt;/div&gt;&#10;&#10;&lt;/div&gt;&#10;&#10;&lt;/div&gt;&#10;&#10;This should just be an HTML comment:&#10;&#10;&lt;!-- Comment --&gt;&#10;&#10;Multiline:&#10;&#10;&lt;!--&#10;Blah&#10;Blah&#10;--&gt;&#10;&lt;!--&#10;    This is another comment.&#10;--&gt;&#10;&#10;Code block:&#10;&#10;    &lt;!-- Comment --&gt;&#10;&#10;Just plain comment, with trailing spaces on the line:&#10;&#10;&lt;!-- foo --&gt;&#10;&#10;Code:&#10;&#10;    &lt;hr /&gt;&#10;&#10;Hr's:&#10;&#10;&lt;hr&gt;&#10;&lt;hr /&gt;&#10;&lt;hr /&gt;&#10;&lt;hr&gt;&#10;&lt;hr /&gt;&#10;&lt;hr /&gt;&#10;&lt;hr class=&quot;foo&quot; id=&quot;bar&quot; /&gt;&#10;&lt;hr class=&quot;foo&quot; id=&quot;bar&quot; /&gt;&#10;&lt;hr class=&quot;foo&quot; id=&quot;bar&quot;&gt;&#10;&#10;--------------------------------------------------------------------------------">+<outline text="HTML Blocks" _note="Simple block on one line:&#10;&#10;::: {}&#10;foo&#10;:::&#10;&#10;And nested without indentation:&#10;&#10;:::::: {}&#10;:::: {}&#10;::: {}&#10;foo&#10;:::&#10;::::&#10;&#10;::: {}&#10;bar&#10;:::&#10;::::::&#10;&#10;Interpreted markdown in a table:&#10;&#10;&lt;table&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;&#10;This is *emphasized*&#10;&lt;/td&gt;&#10;&lt;td&gt;&#10;And this is **strong**&#10;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/table&gt;&#10;&lt;script type=&quot;text/javascript&quot;&gt;document.write('This *should not* be interpreted as markdown');&lt;/script&gt;&#10;&#10;Here's a simple block:&#10;&#10;::: {}&#10;foo&#10;:::&#10;&#10;This should be a code block, though:&#10;&#10;    &lt;div&gt;&#10;        foo&#10;    &lt;/div&gt;&#10;&#10;As should this:&#10;&#10;    &lt;div&gt;foo&lt;/div&gt;&#10;&#10;Now, nested:&#10;&#10;::::: {}&#10;:::: {}&#10;::: {}&#10;foo&#10;:::&#10;::::&#10;:::::&#10;&#10;This should just be an HTML comment:&#10;&#10;&lt;!-- Comment --&gt;&#10;&#10;Multiline:&#10;&#10;&lt;!--&#10;Blah&#10;Blah&#10;--&gt;&#10;&lt;!--&#10;    This is another comment.&#10;--&gt;&#10;&#10;Code block:&#10;&#10;    &lt;!-- Comment --&gt;&#10;&#10;Just plain comment, with trailing spaces on the line:&#10;&#10;&lt;!-- foo --&gt;&#10;&#10;Code:&#10;&#10;    &lt;hr /&gt;&#10;&#10;Hr's:&#10;&#10;&lt;hr&gt;&#10;&lt;hr /&gt;&#10;&lt;hr /&gt;&#10;&lt;hr&gt;&#10;&lt;hr /&gt;&#10;&lt;hr /&gt;&#10;&lt;hr class=&quot;foo&quot; id=&quot;bar&quot; /&gt;&#10;&lt;hr class=&quot;foo&quot; id=&quot;bar&quot; /&gt;&#10;&lt;hr class=&quot;foo&quot; id=&quot;bar&quot;&gt;&#10;&#10;--------------------------------------------------------------------------------"> </outline> <outline text="Inline Markup" _note="This is *emphasized*, and so *is this*.&#10;&#10;This is **strong**, and so **is this**.&#10;&#10;An *[emphasized link](/url)*.&#10;&#10;***This is strong and em.***&#10;&#10;So is ***this*** word.&#10;&#10;***This is strong and em.***&#10;&#10;So is ***this*** word.&#10;&#10;This is code: `&gt;`, `$`, `\`, `\$`, `&lt;html&gt;`.&#10;&#10;~~This is *strikeout*.~~&#10;&#10;Superscripts: a^bc^d a^*hello*^ a^hello there^.&#10;&#10;Subscripts: H~2~O, H~23~O, H~many of them~O.&#10;&#10;These should not be superscripts or subscripts, because of the unescaped spaces:&#10;a\^b c\^d, a\~b c\~d.&#10;&#10;--------------------------------------------------------------------------------"> </outline>
test/writer.org view
@@ -563,16 +563,16 @@ :PROPERTIES: :CUSTOM_ID: smart-quotes-ellipses-dashes :END:-"Hello," said the spider. "'Shelob' is my name."+“Hello,” said the spider. “‘Shelob’ is my name.” -'A', 'B', and 'C' are letters.+‘A’, ‘B’, and ‘C’ are letters. -'Oak,' 'elm,' and 'beech' are names of trees. So is 'pine.'+‘Oak,’ ‘elm,’ and ‘beech’ are names of trees. So is ‘pine.’ -'He said, "I want to go."' Were you alive in the 70's?+‘He said, “I want to go.”’ Were you alive in the 70's? -Here is some quoted '=code=' and a "[[http://example.com/?foo=1&bar=2][quoted-link]]".+Here is some quoted ‘=code=’ and a+“[[http://example.com/?foo=1&bar=2][quoted link]]”.  Some dashes: one---two --- three---four --- five. @@ -599,7 +599,7 @@ These shouldn't be math:  - To get the famous equation, write =$e = mc^2$=.-- $22,000 is a /lot/ of money. So is $34,000. (It worked if "lot" is+- $22,000 is a /lot/ of money. So is $34,000. (It worked if “lot” is   emphasized.) - Shoes ($20) and socks ($5). - Escaped =$=: $73 /this should be emphasized/ 23$.@@ -762,7 +762,7 @@ :PROPERTIES: :CUSTOM_ID: images :END:-From "Voyage dans la Lune" by Georges Melies (1902):+From “Voyage dans la Lune” by Georges Melies (1902):  #+caption: lalune [[file:lalune.jpg]]
test/writer.typst view
@@ -39,7 +39,9 @@   authors: (),   keywords: (),   date: none,+  abstract-title: none,   abstract: none,+  thanks: none,   cols: 1,   margin: (x: 1.25in, y: 1.25in),   paper: "us-letter",@@ -47,66 +49,92 @@   region: "US",   font: (),   fontsize: 11pt,+  mathfont: none,+  codefont: none,+  linestretch: 1,   sectionnumbering: none,+  linkcolor: none,+  citecolor: none,+  filecolor: none,   pagenumbering: "1",   doc, ) = {   set document(     title: title,-    author: authors.map(author => content-to-string(author.name)),     keywords: keywords,   )+  set document(+      author: authors.map(author => content-to-string(author.name)).join(", ", last: " & "),+  ) if authors != none and authors != ()   set page(     paper: paper,     margin: margin,     numbering: pagenumbering,-    columns: cols,-    )-  set par(justify: true)+  )++  set par(+    justify: true,+    leading: linestretch * 0.65em+  )   set text(lang: lang,            region: region,            font: font,            size: fontsize)++  show math.equation: set text(font: mathfont) if mathfont != none+  show raw: set text(font: codefont) if codefont != none+   set heading(numbering: sectionnumbering) -  place(top, float: true, scope: "parent", clearance: 4mm)[-  #if title != none {-    align(center)[#block(inset: 2em)[-      #text(weight: "bold", size: 1.5em)[#title]-      #(if subtitle != none {-        parbreak()-        text(weight: "bold", size: 1.25em)[#subtitle]-      })-    ]]+  show link: set text(fill: rgb(content-to-string(linkcolor))) if linkcolor != none+  show ref: set text(fill: rgb(content-to-string(citecolor))) if citecolor != none+  show link: this => {+    if filecolor != none and type(this.dest) == label {+      text(this, fill: rgb(content-to-string(filecolor)))+    }   } -  #if authors != none and authors != [] {-    let count = authors.len()-    let ncols = calc.min(count, 3)-    grid(-      columns: (1fr,) * ncols,-      row-gutter: 1.5em,-      ..authors.map(author =>-          align(center)[-            #author.name \-            #author.affiliation \-            #author.email-          ]+  block(below: 4mm)[+    #if title != none {+      align(center)[#block(inset: 2em)[+          #text(weight: "bold", size: 1.5em)[#title #if thanks != none {+              footnote(thanks, numbering: "*")+              counter(footnote).update(n => n - 1)+            }]+          #(+            if subtitle != none {+              parbreak()+              text(weight: "bold", size: 1.25em)[#subtitle]+            }+          )+        ]]+    }++    #if authors != none and authors != [] {+      let count = authors.len()+      let ncols = calc.min(count, 3)+      grid(+        columns: (1fr,) * ncols,+        row-gutter: 1.5em,+        ..authors.map(author => align(center)[+          #author.name \+          #author.affiliation \+          #author.email+        ])       )-    )-  }+    } -  #if date != none {-    align(center)[#block(inset: 1em)[-      #date-    ]]-  }+    #if date != none {+      align(center)[#block(inset: 1em)[+          #date+        ]]+    } -  #if abstract != none {-    block(inset: 2em)[-    #text(weight: "semibold")[Abstract] #h(1em) #abstract-    ]-  }+    #if abstract != none {+      block(inset: 2em)[+        #text(weight: "semibold")[#abstract-title] #h(1em) #abstract+      ]+    }   ]    doc@@ -122,6 +150,7 @@       email: "" ),     ),   date: [July 17, 2006],+  abstract-title: [Abstract],   pagenumbering: "1",   cols: 1,   doc,
test/writers-lang-and-dir.latex view
@@ -60,6 +60,12 @@   \newenvironment{RTL}{\beginR}{\endR}   \newenvironment{LTR}{\beginL}{\endL} \fi+\ifluatex+  \newcommand{\RL}[1]{\bgroup\textdir TRT#1\egroup}+  \newcommand{\LR}[1]{\bgroup\textdir TLT#1\egroup}+  \newenvironment{RTL}{\textdir TRT\pardir TRT\bodydir TRT}{}+  \newenvironment{LTR}{\textdir TLT\pardir TLT\bodydir TLT}{}+\fi \usepackage{bookmark} \IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available \urlstyle{same}