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 +7/−0
- MANUAL.txt +135/−74
- README.md +2/−0
- changelog.md +407/−0
- data/default.csl +3929/−675
- data/docx/word/styles.xml +2/−9
- data/templates/common.latex +6/−0
- data/templates/default.latex +19/−1
- data/templates/default.org +6/−0
- data/templates/default.typst +28/−1
- data/templates/styles.html +3/−0
- data/templates/template.typst +65/−37
- pandoc.cabal +18/−10
- src/Text/Pandoc/App.hs +9/−4
- src/Text/Pandoc/App/CommandLineOptions.hs +52/−19
- src/Text/Pandoc/App/Input.hs +18/−1
- src/Text/Pandoc/App/Opt.hs +17/−12
- src/Text/Pandoc/App/OutputSettings.hs +7/−4
- src/Text/Pandoc/Citeproc.hs +25/−14
- src/Text/Pandoc/Citeproc/BibTeX.hs +2/−1
- src/Text/Pandoc/Class.hs +3/−1
- src/Text/Pandoc/Class/CommonState.hs +5/−0
- src/Text/Pandoc/Class/IO.hs +35/−24
- src/Text/Pandoc/Class/PandocMonad.hs +44/−8
- src/Text/Pandoc/Error.hs +9/−0
- src/Text/Pandoc/Extensions.hs +5/−3
- src/Text/Pandoc/Format.hs +8/−0
- src/Text/Pandoc/Highlighting.hs +6/−1
- src/Text/Pandoc/ImageSize.hs +217/−17
- src/Text/Pandoc/Options.hs +53/−8
- src/Text/Pandoc/PDF.hs +49/−48
- src/Text/Pandoc/Parsing/GridTable.hs +9/−8
- src/Text/Pandoc/Readers.hs +3/−0
- src/Text/Pandoc/Readers/DocBook.hs +18/−11
- src/Text/Pandoc/Readers/Docx.hs +2/−1
- src/Text/Pandoc/Readers/Docx/Parse.hs +51/−60
- src/Text/Pandoc/Readers/Docx/Parse/Styles.hs +2/−2
- src/Text/Pandoc/Readers/EndNote.hs +2/−0
- src/Text/Pandoc/Readers/HTML.hs +2/−6
- src/Text/Pandoc/Readers/LaTeX.hs +16/−10
- src/Text/Pandoc/Readers/LaTeX/Inline.hs +1/−0
- src/Text/Pandoc/Readers/LaTeX/Math.hs +27/−17
- src/Text/Pandoc/Readers/LaTeX/Parsing.hs +5/−0
- src/Text/Pandoc/Readers/Man.hs +10/−1
- src/Text/Pandoc/Readers/Markdown.hs +36/−58
- src/Text/Pandoc/Readers/ODT/Arrows/State.hs +15/−1
- src/Text/Pandoc/Readers/ODT/Arrows/Utils.hs +34/−1
- src/Text/Pandoc/Readers/ODT/Base.hs +5/−1
- src/Text/Pandoc/Readers/ODT/ContentReader.hs +19/−8
- src/Text/Pandoc/Readers/ODT/Generic/Fallible.hs +15/−1
- src/Text/Pandoc/Readers/ODT/Generic/Namespaces.hs +5/−1
- src/Text/Pandoc/Readers/ODT/Generic/SetMap.hs +7/−1
- src/Text/Pandoc/Readers/Org/Blocks.hs +12/−10
- src/Text/Pandoc/Readers/Org/Inlines.hs +62/−48
- src/Text/Pandoc/Readers/Org/Meta.hs +5/−1
- src/Text/Pandoc/Readers/Org/ParserState.hs +11/−3
- src/Text/Pandoc/Readers/Org/Parsing.hs +3/−1
- src/Text/Pandoc/Readers/Pod.hs +5/−1
- src/Text/Pandoc/Readers/RST.hs +8/−8
- src/Text/Pandoc/Readers/TikiWiki.hs +2/−3
- src/Text/Pandoc/Readers/Typst.hs +103/−68
- src/Text/Pandoc/Readers/XML.hs +540/−0
- src/Text/Pandoc/SelfContained.hs +16/−12
- src/Text/Pandoc/Templates.hs +1/−0
- src/Text/Pandoc/Translations.hs +2/−1
- src/Text/Pandoc/Writers.hs +3/−0
- src/Text/Pandoc/Writers/ANSI.hs +37/−17
- src/Text/Pandoc/Writers/AsciiDoc.hs +17/−11
- src/Text/Pandoc/Writers/ConTeXt.hs +12/−12
- src/Text/Pandoc/Writers/Djot.hs +6/−3
- src/Text/Pandoc/Writers/DocBook.hs +5/−12
- src/Text/Pandoc/Writers/Docx.hs +7/−2
- src/Text/Pandoc/Writers/Docx/OpenXML.hs +35/−19
- src/Text/Pandoc/Writers/HTML.hs +27/−15
- src/Text/Pandoc/Writers/LaTeX.hs +108/−20
- src/Text/Pandoc/Writers/LaTeX/Types.hs +2/−0
- src/Text/Pandoc/Writers/LaTeX/Util.hs +1/−0
- src/Text/Pandoc/Writers/Man.hs +4/−1
- src/Text/Pandoc/Writers/Markdown.hs +34/−23
- src/Text/Pandoc/Writers/Ms.hs +3/−1
- src/Text/Pandoc/Writers/ODT.hs +5/−2
- src/Text/Pandoc/Writers/OpenDocument.hs +8/−8
- src/Text/Pandoc/Writers/Org.hs +46/−14
- src/Text/Pandoc/Writers/Powerpoint/Output.hs +1/−0
- src/Text/Pandoc/Writers/Powerpoint/Presentation.hs +10/−8
- src/Text/Pandoc/Writers/Shared.hs +6/−0
- src/Text/Pandoc/Writers/Typst.hs +50/−33
- src/Text/Pandoc/Writers/XML.hs +365/−0
- src/Text/Pandoc/XMLFormat.hs +188/−0
- test/Tests/Readers/HTML.hs +2/−2
- test/Tests/Readers/Markdown.hs +12/−17
- test/Tests/Readers/ODT.hs +2/−0
- test/Tests/Readers/Org/Block/Header.hs +7/−0
- test/Tests/Readers/Org/Inline.hs +12/−0
- test/Tests/Readers/Org/Inline/Smart.hs +4/−0
- test/Tests/Readers/Pod.hs +12/−0
- test/Tests/Writers/LaTeX.hs +12/−2
- test/Tests/XML.hs +28/−0
- test/command/10160.md +5/−1
- test/command/10185.md +1/−1
- test/command/10338-rst-multiple-header-rows.md +155/−0
- test/command/10635.md +24/−0
- test/command/10816.md +7/−0
- test/command/10889.md +16/−0
- test/command/10890.md +15/−0
- test/command/10912.md +16/−0
- test/command/10915.md +8/−0
- test/command/10919.md +21/−0
- test/command/10926.md +19/−0
- test/command/10965.md +47/−0
- test/command/10983.md +22/−0
- test/command/10984.md +16/−0
- test/command/11006.md +56/−0
- test/command/11013.md +23/−0
- test/command/11014.md +9/−0
- test/command/11017.md +9/−0
- test/command/11046.md +19/−0
- test/command/11047.md +7/−0
- test/command/11048.md +48/−0
- test/command/11090.md +49/−0
- test/command/11090/ch1.typ +6/−0
- test/command/11113.docx binary
- test/command/11113.md +7/−0
- test/command/1629.md +1/−1
- test/command/2118.md +1/−1
- test/command/3113.md +1/−1
- test/command/3422.md +1/−1
- test/command/3577.md +2/−2
- test/command/4164.md +2/−4
- test/command/5420.md +1/−1
- test/command/6783.md +1/−1
- test/command/6890.md +7/−15
- test/command/6951.md +1/−1
- test/command/7219.md +1/−1
- test/command/7329.md +2/−2
- test/command/7512.md +6/−1
- test/command/7691.docx binary
- test/command/7691.md +5/−0
- test/command/8354.md +1/−1
- test/command/8745.md +1/−1
- test/command/8869.md +20/−0
- test/command/8957.md +7/−0
- test/command/9000.md +14/−0
- test/command/9017.md +2/−1
- test/command/9452.md +1/−1
- test/command/982.md +5/−1
- test/command/9904.md +1/−3
- test/command/biblatex-angenendt.md +1/−1
- test/command/citeproc-87.md +10/−6
- test/command/lists-inside-definition.md +1/−0
- test/command/macros.md +2/−2
- test/command/pandoc-citeproc-118.md +2/−3
- test/command/pandoc-citeproc-136.md +1/−1
- test/command/pandoc-citeproc-14.md +11/−11
- test/command/pandoc-citeproc-175.md +2/−2
- test/command/pandoc-citeproc-25.md +2/−2
- test/command/pandoc-citeproc-250.md +2/−2
- test/command/pandoc-citeproc-301.md +5/−5
- test/command/pandoc-citeproc-307.md +1/−1
- test/command/pandoc-citeproc-320a.md +7/−7
- test/command/pandoc-citeproc-325.md +4/−4
- test/command/pandoc-citeproc-327.md +1/−1
- test/command/pandoc-citeproc-371.md +2/−2
- test/command/pandoc-citeproc-38.md +3/−3
- test/command/pandoc-citeproc-401.md +5/−5
- test/command/pandoc-citeproc-408.md +3/−3
- test/command/pandoc-citeproc-416.md +4/−4
- test/command/pandoc-citeproc-47.md +4/−4
- test/command/pandoc-citeproc-51.md +1/−1
- test/command/pandoc-citeproc-64.md +7/−7
- test/command/pandoc-citeproc-65.md +2/−3
- test/command/pandoc-citeproc-7.md +2/−2
- test/command/pandoc-citeproc-70.md +4/−4
- test/command/pandoc-citeproc-76.md +5/−5
- test/command/pandoc-citeproc-87.md +17/−17
- test/command/pandoc-citeproc-chicago-author-date.md +4/−4
- test/command/pandoc-citeproc-no-author.md +7/−7
- test/command/pandoc-citeproc-number-of-volumes.md +2/−2
- test/command/refs.md +1/−1
- test/docbook-reader.docbook +41/−8
- test/docbook-reader.native +122/−0
- test/docx/golden/block_quotes.docx binary
- test/docx/golden/codeblock.docx binary
- test/docx/golden/comments.docx binary
- test/docx/golden/custom_style_no_reference.docx binary
- test/docx/golden/custom_style_preserve.docx binary
- test/docx/golden/definition_list.docx binary
- test/docx/golden/document-properties-short-desc.docx binary
- test/docx/golden/document-properties.docx binary
- test/docx/golden/headers.docx binary
- test/docx/golden/image.docx binary
- test/docx/golden/inline_code.docx binary
- test/docx/golden/inline_formatting.docx binary
- test/docx/golden/inline_images.docx binary
- test/docx/golden/link_in_notes.docx binary
- test/docx/golden/links.docx binary
- test/docx/golden/lists.docx binary
- test/docx/golden/lists_9994.docx binary
- test/docx/golden/lists_continuing.docx binary
- test/docx/golden/lists_div_bullets.docx binary
- test/docx/golden/lists_multiple_initial.docx binary
- test/docx/golden/lists_restarting.docx binary
- test/docx/golden/nested_anchors_in_header.docx binary
- test/docx/golden/notes.docx binary
- test/docx/golden/raw-blocks.docx binary
- test/docx/golden/raw-bookmarks.docx binary
- test/docx/golden/table_one_row.docx binary
- test/docx/golden/table_with_list_cell.docx binary
- test/docx/golden/tables-default-widths.docx binary
- test/docx/golden/tables.docx binary
- test/docx/golden/tables_separated_with_rawblock.docx binary
- test/docx/golden/task_list.docx binary
- test/docx/golden/track_changes_deletion.docx binary
- test/docx/golden/track_changes_insertion.docx binary
- test/docx/golden/track_changes_move.docx binary
- test/docx/golden/track_changes_scrubbed_metadata.docx binary
- test/docx/golden/unicode.docx binary
- test/docx/golden/verbatim_subsuper.docx binary
- test/man-reader.man +1/−1
- test/man-reader.native +5/−9
- test/odt/native/simpleTable.native +1/−1
- test/odt/native/simpleTableWithCaption.native +1/−1
- test/odt/native/simpleTableWithHeader.native +79/−0
- test/odt/native/simpleTableWithMultipleHeaderRows.native +125/−0
- test/odt/native/tableWithContents.native +1/−1
- test/odt/odt/simpleTableWithHeader.odt binary
- test/odt/odt/simpleTableWithMultipleHeaderRows.odt binary
- test/s5-basic.html +3/−0
- test/s5-fancy.html +3/−0
- test/s5-inserts.html +3/−0
- test/test-pandoc.hs +3/−3
- test/writer.docbook4 +8/−8
- test/writer.docbook5 +8/−8
- test/writer.html4 +3/−0
- test/writer.html5 +3/−0
- test/writer.jats_archiving +1/−1
- test/writer.jats_articleauthoring +1/−1
- test/writer.jats_publishing +1/−1
- test/writer.markdown +18/−36
- test/writer.markua +7/−7
- test/writer.opml +1/−1
- test/writer.org +8/−8
- test/writer.typst +66/−37
- test/writers-lang-and-dir.latex +6/−0
@@ -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
@@ -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 @@  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. + {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 \
@@ -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
@@ -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:
@@ -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="———" 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>
@@ -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"/>
@@ -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
@@ -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
@@ -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$
@@ -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)$
@@ -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)$
@@ -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
@@ -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
@@ -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] ++
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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]
@@ -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
@@ -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
@@ -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 }
@@ -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))
@@ -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"
@@ -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
@@ -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 ]
@@ -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
@@ -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 =
@@ -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"]
@@ -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/"
@@ -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
@@ -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
@@ -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).
@@ -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 <$>
@@ -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}
@@ -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'
@@ -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
@@ -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 }
@@ -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
@@ -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
@@ -281,6 +281,7 @@ , ("_", lit "_") , ("{", lit "{") , ("}", lit "}")+ , ("-", lit "\x00ad") -- soft hyphen , ("qed", lit "\a0\x25FB") , ("lq", return (str "‘")) , ("rq", return (str "’"))
@@ -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")
@@ -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]
@@ -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) .
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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]]
@@ -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 = ()
@@ -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)
@@ -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
@@ -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")
@@ -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)
@@ -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 $
@@ -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 =
@@ -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 (..)
@@ -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
@@ -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
@@ -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
@@ -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)) ]
@@ -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")
@@ -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.
@@ -102,6 +102,7 @@ "native" -> return "" "csljson" -> return "" "json" -> return ""+ "xml" -> return "" "fb2" -> return "" "pptx" -> return "" "ipynb" -> return ""
@@ -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(..))
@@ -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).
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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'
@@ -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)
@@ -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)
@@ -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
@@ -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 }
@@ -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"
@@ -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
@@ -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
@@ -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
@@ -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)
@@ -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
@@ -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) <> "]]"
@@ -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)
@@ -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.
@@ -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
@@ -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
@@ -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')
@@ -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"
@@ -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!')" ]
@@ -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" =:+ "{latex-placement=\"htbp\" alt=\"alt text\"}" =?>+ figureWith ("", [], [("latex-placement", "htbp")])+ (simpleCaption $ plain "caption")+ (plain $ image (T.pack "img.jpg") (T.pack "") (text "alt text")) ]+ ]
@@ -180,6 +180,8 @@ , "referenceToText" , "simpleTable" , "simpleTableWithCaption"+ , "simpleTableWithHeader"+ , "simpleTableWithMultipleHeaderRows" , "tab" -- , "table" , "textMixedStyles"
@@ -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" =:
@@ -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" =?>
@@ -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")))
@@ -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;" ] ] ]
@@ -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}" ] ]
@@ -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]
@@ -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}"+ ]+] ```
@@ -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}.
@@ -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" ]+]+```
@@ -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."+ ]+]+```
@@ -0,0 +1,7 @@+```+% pandoc -f markdown -t typst+# Test①+^D+= Test①+#label("test①")+```
@@ -0,0 +1,16 @@+```+% pandoc+apple++: pomaceous++ fruit+^D+<dl>+<dt>apple</dt>+<dd>+<p>pomaceous</p>+<p>fruit</p>+</dd>+</dl>+```
@@ -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+```
@@ -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" ] ] ]+]+```
@@ -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>+```+
@@ -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.+```
@@ -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+```+````
@@ -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.++]+```
@@ -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.++```
@@ -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+```
@@ -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+```
@@ -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.++```
@@ -0,0 +1,9 @@+```+% pandoc -f djot -t html+{.foo}+- bar+^D+<ul class="foo">+<li>bar</li>+</ul>+```
@@ -0,0 +1,9 @@+```+% pandoc -t markdown -f typst+#show heading: smallcaps++= Introduction+^D+# [Introduction]{.smallcaps}++```
@@ -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.+```
@@ -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.+```
@@ -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+---+++```
@@ -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" , "" )+ ]+ ]+]+```
@@ -0,0 +1,6 @@+== Chapter One++#figure(+ image("media/image1.png"),+ caption: [An image.]+)
binary file changed (absent → 14206 bytes)
@@ -0,0 +1,7 @@+```+% pandoc command/11113.docx -t plain+^D+Colored:❤️😏📖👌😒🤍++BW: 😊︎+```
@@ -1,5 +1,5 @@ ```-% pandoc -t latex --listings+% pandoc -t latex --syntax-highlighting=idiomatic bla bla `a % b` *bla bla `a % b`*
@@ -8,7 +8,7 @@ \end{figure} ^D [ Figure- ( "fig:setminus" , [] , [] )+ ( "fig:setminus" , [] , [ ( "latex-placement" , "ht" ) ] ) (Caption Nothing [ Plain [ Str "Set" , Space , Str "subtraction" ] ]) [ Plain
@@ -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}" ] ] ```
@@ -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[]);!}
@@ -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>
@@ -8,11 +8,9 @@ Here is inline html: -<div>-+::: {} `<balise>`{=html} bla bla--</div>+::: ```
@@ -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;!}
@@ -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. ```
@@ -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
@@ -14,5 +14,5 @@ Crazy. n.d. -Doe, John. 2005. First Book. Cambridge: Cambridge University Press.+Doe, John. 2005. First Book. Cambridge University Press. ```
@@ -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. ```
@@ -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. ``` ```
@@ -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*}"+ ]+] ``` ```
binary file changed (absent → 11923 bytes)
@@ -0,0 +1,5 @@+```+% pandoc command/7691.docx+^D+<p>Some text</p>+```
@@ -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
@@ -16,7 +16,7 @@ ^D [ Para [ Str "Sample" , Space , Str "text" ] , Figure- ( "fig:Mondrian" , [] , [] )+ ( "fig:Mondrian" , [] , [ ( "latex-placement" , "ht" ) ] ) (Caption Nothing [ Plain
@@ -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"+]+```
@@ -0,0 +1,7 @@+```+% pandoc -f latex -t html --wrap=none+{width="342pt" height="9pc"}+^D+<p><span>width="342pt" height="9pc"</span></p>++```
@@ -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.++```+
@@ -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>
@@ -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");). ```
@@ -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}"+ ]+] ```
@@ -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
@@ -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
@@ -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. ```
@@ -33,6 +33,7 @@ 2. list ^D \begin{description}+\tightlist \item[Definition] Foo
@@ -61,9 +61,9 @@ ^D \(5-67\) -\[\begin{aligned}+\begin{align} x &= y\\-\end{aligned}\]+\end{align} \emph{hi}
@@ -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. ::: :::: ```
@@ -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. :::
@@ -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. ::: :::::: ```
@@ -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. ::: :::: ```
@@ -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*. ::: :::: ```
@@ -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*. ::: :::: ```
@@ -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. ::: ::::: ```
@@ -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.
@@ -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.
@@ -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. ::: ::::: ```
@@ -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} ::: :::: ```
@@ -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*. ::: ::::: ```
@@ -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*. ::: :::: ```
@@ -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. ::: ::::: ```
@@ -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*. ::: ::::: ```
@@ -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. ::: :::::: ```
@@ -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}
@@ -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. :::
@@ -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. ::: :::::: ```
@@ -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. ::: :::: ```
@@ -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. ::: :::: ```
@@ -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}
@@ -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*. ::: ::::::: ```
@@ -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>. ::: ::::::::: ```
@@ -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. ::: ::::::
@@ -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." ::: ::::::::: ```
@@ -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. ::: :::: ```
@@ -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}" ] ] ```
@@ -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>
@@ -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" ] ]
binary file changed (10689 → 10692 bytes)
binary file changed (10507 → 10510 bytes)
binary file changed (10838 → 10841 bytes)
binary file changed (10609 → 10609 bytes)
binary file changed (11235 → 11236 bytes)
binary file changed (10498 → 10501 bytes)
binary file changed (10512 → 10515 bytes)
binary file changed (10997 → 11000 bytes)
binary file changed (10652 → 10655 bytes)
binary file changed (27380 → 27383 bytes)
binary file changed (10448 → 10451 bytes)
binary file changed (10624 → 10627 bytes)
binary file changed (27380 → 27383 bytes)
binary file changed (10661 → 10664 bytes)
binary file changed (10839 → 10842 bytes)
binary file changed (11031 → 11034 bytes)
binary file changed (10785 → 10788 bytes)
binary file changed (10699 → 10702 bytes)
binary file changed (10682 → 10685 bytes)
binary file changed (10915 → 10918 bytes)
binary file changed (10696 → 10699 bytes)
binary file changed (10842 → 10845 bytes)
binary file changed (10612 → 10615 bytes)
binary file changed (10541 → 10544 bytes)
binary file changed (10680 → 10683 bytes)
binary file changed (10519 → 10522 bytes)
binary file changed (10969 → 10972 bytes)
binary file changed (10879 → 10882 bytes)
binary file changed (10893 → 10896 bytes)
binary file changed (10516 → 10519 bytes)
binary file changed (10780 → 10783 bytes)
binary file changed (10489 → 10492 bytes)
binary file changed (10473 → 10476 bytes)
binary file changed (10503 → 10506 bytes)
binary file changed (10614 → 10617 bytes)
binary file changed (10465 → 10468 bytes)
binary file changed (10476 → 10479 bytes)
@@ -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
@@ -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
@@ -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 []]
@@ -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 []]
@@ -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 []+]
@@ -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 []+]+
@@ -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 []]
binary file changed (absent → 10377 bytes)
binary file changed (absent → 10173 bytes)
@@ -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);}
@@ -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);}
@@ -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);}
@@ -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
@@ -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>
@@ -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>
@@ -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;
@@ -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;
@@ -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>
@@ -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:
@@ -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>
@@ -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:
@@ -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
@@ -44,7 +44,7 @@ </outline> <outline text="Definition Lists" _note="Tight using spaces: apple : red fruit orange : orange fruit banana : yellow fruit Tight using tabs: apple : red fruit orange : orange fruit banana : yellow fruit Loose: apple : red fruit orange : orange fruit banana : yellow fruit Multiple blocks with italics: *apple* : red fruit contains seeds, crisp, pleasant to taste *orange* : orange fruit { orange code block } > orange block quote Multiple definitions, tight: apple : red fruit : computer orange : orange fruit : bank Multiple definitions, loose: apple : red fruit : computer orange : orange fruit : bank Blank line after term, indented marker, alternate markers: apple : red fruit : computer orange : orange fruit 1. sublist 2. sublist"> </outline>-<outline text="HTML Blocks" _note="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: <table> <tr> <td> This is *emphasized* </td> <td> And this is **strong** </td> </tr> </table> <script type="text/javascript">document.write('This *should not* be interpreted as markdown');</script> Here's a simple block: <div> foo </div> This should be a code block, though: <div> foo </div> As should this: <div>foo</div> Now, nested: <div> <div> <div> foo </div> </div> </div> This should just be an HTML comment: <!-- Comment --> Multiline: <!-- Blah Blah --> <!-- This is another comment. --> Code block: <!-- Comment --> Just plain comment, with trailing spaces on the line: <!-- foo --> Code: <hr /> Hr's: <hr> <hr /> <hr /> <hr> <hr /> <hr /> <hr class="foo" id="bar" /> <hr class="foo" id="bar" /> <hr class="foo" id="bar"> --------------------------------------------------------------------------------">+<outline text="HTML Blocks" _note="Simple block on one line: ::: {} foo ::: And nested without indentation: :::::: {} :::: {} ::: {} foo ::: :::: ::: {} bar ::: :::::: Interpreted markdown in a table: <table> <tr> <td> This is *emphasized* </td> <td> And this is **strong** </td> </tr> </table> <script type="text/javascript">document.write('This *should not* be interpreted as markdown');</script> Here's a simple block: ::: {} foo ::: This should be a code block, though: <div> foo </div> As should this: <div>foo</div> Now, nested: ::::: {} :::: {} ::: {} foo ::: :::: ::::: This should just be an HTML comment: <!-- Comment --> Multiline: <!-- Blah Blah --> <!-- This is another comment. --> Code block: <!-- Comment --> Just plain comment, with trailing spaces on the line: <!-- foo --> Code: <hr /> Hr's: <hr> <hr /> <hr /> <hr> <hr /> <hr /> <hr class="foo" id="bar" /> <hr class="foo" id="bar" /> <hr class="foo" id="bar"> --------------------------------------------------------------------------------"> </outline> <outline text="Inline Markup" _note="This is *emphasized*, and so *is this*. This is **strong**, and so **is this**. An *[emphasized link](/url)*. ***This is strong and em.*** So is ***this*** word. ***This is strong and em.*** So is ***this*** word. This is code: `>`, `$`, `\`, `\$`, `<html>`. ~~This is *strikeout*.~~ Superscripts: a^bc^d a^*hello*^ a^hello there^. Subscripts: H~2~O, H~23~O, H~many of them~O. These should not be superscripts or subscripts, because of the unescaped spaces: a\^b c\^d, a\~b c\~d. --------------------------------------------------------------------------------"> </outline>
@@ -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]]
@@ -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,
@@ -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}